Python能否确定访问方法的对象类
有没有办法做到像这样:
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的这种想法可能是个错误。