尝试将 转换为简单的super(B, self).method()
bubble()
简单调用。
是吗,see below!
在这个例子中是否可以引用B类?
class A(object): pass
class B(A):
def test(self):
test2()
class C(B): pass
import inspect
def test2():
frame = inspect.currentframe().f_back
cls = frame.[?something here?]
# cls here should == B (class)
c = C()
c.test()
基本上,C
是B
的孩子,B
是A
的孩子。然后我们创建c
类型的C
。然后,对c.test()
的调用实际上调用B.test()
(通过继承),调用test2()
。
test2()
可以获得父框架frame
;通过frame.f_code
对方法的代码引用;
self
来自frame.f_locals['self']
;但是type(frame.f_locals['self'])
是C
(当然),但不是B
,其中定义了方法。
获取B
的任何方式?
答案 0 :(得分:3)
找到一种更短的方式super(B, self).test()
- > bubble()
来自下方。
(与多重继承一起使用,不需要参数,与子类相关)
解决方案是使用inspect.getmro(type(back_self))
(其中back_self
是来自被调用方的self
),然后使用cls
将其重复为method_name in cls.__dict__
并验证我们的代码引用是这个类中的一个(在find_class_by_code_object(self)
嵌套函数中实现)。
bubble()
可以使用*args, **kwargs
轻松扩展。
import inspect
def bubble(*args, **kwargs):
def find_class_by_code_object(back_self, method_name, code):
for cls in inspect.getmro(type(back_self)):
if method_name in cls.__dict__:
method_fun = getattr(cls, method_name)
if method_fun.im_func.func_code is code:
return cls
frame = inspect.currentframe().f_back
back_self = frame.f_locals['self']
method_name = frame.f_code.co_name
for _ in xrange(5):
code = frame.f_code
cls = find_class_by_code_object(back_self, method_name, code)
if cls:
super_ = super(cls, back_self)
return getattr(super_, method_name)(*args, **kwargs)
try:
frame = frame.f_back
except:
return
class A(object):
def test(self):
print "A.test()"
class B(A):
def test(self):
# instead of "super(B, self).test()" we can do
bubble()
class C(B):
pass
c = C()
c.test() # works!
b = B()
b.test() # works!
如果有人有更好的想法,那就听听吧。
已知错误:(感谢doublep)如果C.test = B.test
- > “无限”的递归。虽然对于儿童班来说实际上有一种方法似乎是不现实的,但是从父母的方法来看,这已经是=
。
已知错误2:(感谢doublep)装饰方法不起作用(可能无法修复,因为装饰器返回一个闭包)... 修复了{{1的装饰器问题}}:... for _ in xrange(5)
- 最多可处理5个装饰器,如果需要可以增加。 我喜欢Python!
性能比frame = frame.f_back
呼叫差5倍,但我们说的是200K呼叫,而不是每秒100万次呼叫,如果这不是你最严重的环路 - 没有理由担心。
答案 1 :(得分:0)
虽然此代码绝不能用于任何正常目的。为了回答这个问题,这里有一些工作;)
import inspect
def test2():
funcname = inspect.stack()[1][3]
frame = inspect.currentframe().f_back
self = frame.f_locals['self']
return contains(self.__class__, funcname)
def contains(class_, funcname):
if funcname in class_.__dict__:
return class_
for class_ in class_.__bases__:
class_ = contains(class_, funcname)
if class_:
return class_
答案 2 :(得分:-1)
由于Python中的函数没有绑定到类[1],因此一般答案是“不可能的”。 但是,对于遵循标准命名约定的非静态函数,您可以尝试
inspect.currentframe()。f_back.f_locals ['self']。 class
[1],你可以这样做:
class X: pass
X.foo = (lambda self: None)
编辑:
我设法提出了问题中已有的方法: - /。但是,我仍然很好奇你是如何设法做到这一点的,因为我仍然确定某些函数没有绑定到Python中的类。