[英]Python class method chaining
為了避免迷失在架構決策中,我會用一個類似的例子來問這個問題:
假設我想要一個像這樣的Python類模式:
queue = TaskQueue(broker_conn)
queue.region("DFW").task(fn, "some arg")
這里的問題是如何讓設計成為一個類,以便某些方法可以以這種方式“鏈接”。
task()
需要訪問queue
類實例屬性, task
的操作取決於region()
的輸出。
我看到SQLalchemy做了這個(見下文),但我很難深入挖掘他們的代碼並隔離這種模式。
query = db.query(Task).filter(Task.objectid==10100)
SQLAlchemy在這些調用上生成一個克隆,請參閱Generative._generate()
方法 ,該方法只返回當前對象的克隆。
在每個生成方法調用(例如.filter()
.orderby()
等)上,返回一個新的克隆,並更改特定的方面(例如擴展的查詢樹等)。
SQLAlchemy使用@_generative
裝飾器標記必須操作的方法並在此返回克隆,為生成的克隆交換self
。
在您自己的代碼中使用此模式非常簡單:
from functools import wraps
class GenerativeBase(object):
def _generate(self):
s = self.__class__.__new__(self.__class__)
s.__dict__ = self.__dict__.copy()
return s
def _generative(func):
@wraps(func)
def decorator(self, *args, **kw):
new_self = self._generate()
func(new_self, *args, **kw)
return new_self
return decorator
class TaskQueue(GenerativeBase):
@_generative
def region(self, reg_id):
self.reg_id = reg_id
@_generative
def task(self, callable, *args, **kw):
self.tasks.append((callable, args, kw))
每次調用.task()
.region()
或.task()
現在都會產生一個克隆,通過改變狀態來更新裝飾方法。 然后返回克隆,保持原始實例對象不變。
只需從region
方法返回當前對象,就像這樣
def region(self, my_string):
...
...
return self
由於region
返回具有task
功能的當前對象,因此現在可以進行鏈接。
注意:
正如@chepner 在評論部分中提到的那樣 ,確保該region
對對象self
進行更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.