[英]Re-use a global function within a class decorator
假设我有一个生成路由器函数的函数,该函数根据数字是奇数还是偶数来调用指定的回调:
def odd_even_router(odd, even):
def r(n):
if n % 2:
odd(n)
else:
even(n)
return r
我还有一个类装饰器,它将一个名为check_number
的类似路由器方法check_number
到一个类:
def attach_default_router(cls):
def route(self, n):
if n % 2:
self.on_odd(n)
else:
self.on_even(n)
cls.check_number = route
return cls
然后,用@attach_default_router
修饰的类自动定义了check_number()
,只需要实现on_odd()
和on_even()
:
@attach_default_router
class A(object):
def on_odd(self, n):
print 'Odd number'
def on_even(self, n):
print 'Even number'
如果我想重新使用odd_even_router()
,路由器函数生成器,在attach_default_router()
,我可以这样做:
def attach_default_router(cls):
def route(self, n):
r = odd_even_router(self.on_odd, self.on_even)
r(n)
cls.check_number = route
return cls
然而,不期望的效果是,每次调用check_number()
时,都会生成新的(但相同的)路由器功能。 所以这是我的问题: 如何在attach_default_router()
装饰器中重新使用odd_even_router()
生成器,但attach_default_router()
生成新的路由器函数?
问题的核心是: odd_even_router()
返回一个接受一个参数的函数,但check_number()
是一个实例方法,需要两个(第一个是对象的self
)。 如果我没有掌握self
,我还无法生成路由器功能。 当我抓住self
,我已经在方法中,并且在那里生成它需要在每次调用方法时生成。
我怎么能解决这个难题?
你可以,但是你必须在运行时绑定你的odd
和even
钩子,需要稍微不同的工厂实现。
这是因为你的route
功能不仅每次产生一个新的,* odd
和even
方法也是even
。 每次执行该表达式时, self.odd
都会创建一个新的方法包装器,因为函数是描述符 ,并且每次需要时都绑定到实例( self
here)。
因此,如果要生成一个 route()
函数以用于装饰类的所有实例,则必须手动确保绑定仍然发生:
def odd_even_router_method_factory(odd, even):
def route(self, n):
if n % 2:
odd.__get__(self)(n)
else:
even.__get__(self)(n)
return route
def attach_default_router(cls):
route = odd_even_router_method_factory(cls.on_odd, cls.on_even)
cls.check_number = route
return cls
请注意,Python现在仍将创建一个route
方法对象 。 每次访问instance_of_your_decorated_class.route
,都会通过描述符协议创建方法对象。 当调用odd.__get__()
even.__get__()
发生同样的情况。 你也可以坚持你的原始版本,并为每个调用生成一个新的route()
函数,传入self.odd
和self.even
,因为它可能更具可读性,并保持你原来的odd_even_router()
工厂函数可以使用作为方法和功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.