摆脱明确的超级
Getting rid of explicit super
我想实现这样的东西
def after(f):
def inner(*args, **kwargs):
super().f(*args, **kwargs)
f(*args, **kwargs)
return inner
class A:
def f(self):
print ('hello')
class B(A):
@after
def f(self):
print ('world')
b = B()
b.f()
那是我想在我的一些 classes 中摆脱显式 super
并将其替换为 @before
/ @after
装饰器(可能带有参数).
也就是说,在这个例子中,我希望打印hello world
。
想法是为了增加代码的可读性,因为在一些classes中我经常使用多重继承,所以我经常重写方法,经常不得不使用super()
.
我想我可以使用 inspect
来确定调用装饰器的 class 实例(尽管如果我有很多 class 个实例则性能不确定)。
有没有办法在不牺牲性能的情况下做到这一点?
您可以让您的装饰器工作,您只需要让它成为一个描述符 class,而不是一个函数。您需要实施 __set_name__
方法以获取对您已添加到的 class 的引用。使用 class 引用,您可以进行两个参数 super
调用:
import functools
class after:
def __init__(self, method):
self.method = method
def __set_name__(self, owner, name):
self.owner = owner
self.name = name # using self.method.__name__ might be better?
def __get__(self, instance, owner):
if instance is None:
return self
return functools.partial(self, instance)
def __call__(self, instance, *args, **kwargs):
assert(self.owner is not None and self.name is not None)
getattr(super(self.owner, instance), self.name)(*args, **kwargs)
return self.method(instance, *args, **kwargs)
你也可以做一个 before
,这几乎是一样的,只是最后两行的顺序相反(还有一些小动作来处理 return 值)。
我注意到这个装饰器比以正常方式调用 super
的用处要小得多,因为您无法与被重写方法编辑的值 return 进行有用的交互,或更改传递给它的参数。没有 before
或 after
修饰方法可以复制这些 classes:
class Foo:
def foo(self, x, y):
return x + y
class Bar(Foo):
def foo(self, x, y, z):
return super().foo(x//2, y+1) * z
我想实现这样的东西
def after(f):
def inner(*args, **kwargs):
super().f(*args, **kwargs)
f(*args, **kwargs)
return inner
class A:
def f(self):
print ('hello')
class B(A):
@after
def f(self):
print ('world')
b = B()
b.f()
那是我想在我的一些 classes 中摆脱显式 super
并将其替换为 @before
/ @after
装饰器(可能带有参数).
也就是说,在这个例子中,我希望打印hello world
。
想法是为了增加代码的可读性,因为在一些classes中我经常使用多重继承,所以我经常重写方法,经常不得不使用super()
.
我想我可以使用 inspect
来确定调用装饰器的 class 实例(尽管如果我有很多 class 个实例则性能不确定)。
有没有办法在不牺牲性能的情况下做到这一点?
您可以让您的装饰器工作,您只需要让它成为一个描述符 class,而不是一个函数。您需要实施 __set_name__
方法以获取对您已添加到的 class 的引用。使用 class 引用,您可以进行两个参数 super
调用:
import functools
class after:
def __init__(self, method):
self.method = method
def __set_name__(self, owner, name):
self.owner = owner
self.name = name # using self.method.__name__ might be better?
def __get__(self, instance, owner):
if instance is None:
return self
return functools.partial(self, instance)
def __call__(self, instance, *args, **kwargs):
assert(self.owner is not None and self.name is not None)
getattr(super(self.owner, instance), self.name)(*args, **kwargs)
return self.method(instance, *args, **kwargs)
你也可以做一个 before
,这几乎是一样的,只是最后两行的顺序相反(还有一些小动作来处理 return 值)。
我注意到这个装饰器比以正常方式调用 super
的用处要小得多,因为您无法与被重写方法编辑的值 return 进行有用的交互,或更改传递给它的参数。没有 before
或 after
修饰方法可以复制这些 classes:
class Foo:
def foo(self, x, y):
return x + y
class Bar(Foo):
def foo(self, x, y, z):
return super().foo(x//2, y+1) * z