Python可以确定访问方法的对象的类

时间:2009-09-30 11:58:36

标签: python introspection

无论如何都要做这样的事情:

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 个答案:

答案 0 :(得分: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"

Üglŷ哎呀,但它确实有效。现在为什么你想要这样做完全是另一个问题,我怀疑有更好的方法。 A的整个概念不允许称为B可能是一个错误。

答案 1 :(得分:4)

调用者始终是A的实例。您在B方法中调用它的事实不会改变它。换句话说:Insiode B.foorefA的一个实例,因此调用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"

答案 2 :(得分:0)

这样的事情可能会更好地满足您的需求:

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

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

class C(A):
    pass

......但如果不确切知道自己要做什么,就很难说。