[英]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.