试图转换成一个简单的好super(B, self).method()
bubble()
电话.
做到了,见下文!
在这个例子中是否可以引用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()
Run Code Online (Sandbox Code Playgroud)
基本上,C
是孩子B
,B
是孩子A
.然后我们创建c
类型C
.然后调用c.test()
实际调用B.test()
(通过继承),调用test2()
.
test2()
可以得到父框架frame
; 代码引用方法via frame.f_code
;
self
通过frame.f_locals['self']
; 但type(frame.f_locals['self'])
是C
(当然),但不B
,其中定义的方法.
有B
什么方法可以得到?
找到了一种更短的方法super(B, self).test()
->bubble()
从下面开始。
(适用于多重继承,不需要参数,正确地处理子类)
解决方案是使用inspect.getmro(type(back_self))
(where back_self
is a self
from callee),然后像cls
with一样迭代它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!
Run Code Online (Sandbox Code Playgroud)
如果有人有更好的想法,让我们听听。
已知错误:(感谢 doublep)如果C.test = B.test
-->“无限”递归。尽管子类实际上拥有一种方法似乎不现实,但它是=
从父类中继承而来的。
已知 bug2:(感谢 doublep)装饰方法将不起作用(可能无法修复,因为装饰器返回一个闭包)...修复了装饰器问题for _ in xrange(5)
:...frame = frame.f_back
- 将处理最多 5 个装饰器,如果需要则增加。我喜欢Python!
性能比调用差 5 倍super()
,但我们谈论的是 200K 调用与每秒 100 万次调用,如果这不在您最紧密的循环中 - 没有理由担心。
归档时间: |
|
查看次数: |
435 次 |
最近记录: |