Python能否确定访问方法的对象类

2 投票
3 回答
5239 浏览
提问于 2025-04-15 14:42

有没有办法做到像这样:

class A:
    def foo(self):
        if isinstance(caller, B):
           print "B can't call methods in A"
        else:
           print "Foobar"
class B:
    def foo(self, ref): ref.foo()

class C:
    def foo(self, ref): ref.foo()


a = A();
B().foo(a)    # Outputs "B can't call methods in A"
C().foo(a)    # Outputs "Foobar"

在这里,调用者A中使用某种方式来检查调用方法的对象的类是什么?

编辑

最后,我根据一些建议把这个整合在一起:

import inspect
...
def check_caller(self, klass):
    frame = inspect.currentframe()
    current = lambda : frame.f_locals.get('self')
    while not current() is None:
        if isinstance(current(), klass): return True
        frame = frame.f_back
    return False

虽然并不是完美的,原因也有很多,但感谢大家的回复:这些对我帮助很大。

3 个回答

-1

像这样的东西可能更符合你的需求:

class A(object):
    def foo(self):
        # do stuff

class B(A):
    def foo(self):
        raise NotImplementedError

class C(A):
    pass

...不过,如果不知道你具体想做什么,就很难给出准确的建议。

4

调用者总是一个A的实例。你在B的方法里面调用它,这个事实并不会改变。换句话说,在B.foo里面,ref是一个A的实例,所以调用ref.foo()实际上是在调用A,而B在这个调用中并没有参与(这个调用可以在最外层进行)。

唯一合理的做法是传递一个self的引用,这样A就可以检查自己是不是B。

class A(object):
    def foo(self, caller=None):
        if isinstance(caller, B):
           print "B can't call methods in A"
        else:
           print "Foobar"

class B(object):
    def foo(self, ref): ref.foo(self)

class C(object):
    def foo(self, ref): ref.foo(self)

a = A();
B().foo(a)    # Outputs "B can't call methods in A"
C().foo(a)    # Outputs "Foobar"
a.foo()       # Outputs "Foobar"
6

假设调用者是一个方法,那么你可以通过查看之前的框架,找到self这个变量。

class Reciever:
    def themethod(self):
        frame = sys._getframe(1)
        arguments = frame.f_code.co_argcount
        if arguments == 0:
            print "Not called from a method"
            return
        caller_calls_self = frame.f_code.co_varnames[0]
        thecaller = frame.f_locals[caller_calls_self]
        print "Called from a", thecaller.__class__.__name__, "instance"

虽然这方法看起来有点奇怪,但确实能奏效。不过,为什么要这么做又是另一个问题,我觉得可能有更好的办法。一般来说,A不允许调用B的这种想法可能是个错误。

撰写回答