无论如何都要做这样的事情:
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
由于提供的所有原因并不完美,但感谢您的回复:他们是一个很大的帮助。
答案 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.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"
答案 2 :(得分:0)
这样的事情可能会更好地满足您的需求:
class A(object):
def foo(self):
# do stuff
class B(A):
def foo(self):
raise NotImplementedError
class C(A):
pass
......但如果不确切知道自己要做什么,就很难说。