NFi*_*ano 12 python magic-methods python-2.7
为了避免迷失在架构决策中,我会用一个类似的例子来问这个问题:
假设我想要一个像这样的Python类模式:
queue = TaskQueue(broker_conn)
queue.region("DFW").task(fn, "some arg")
Run Code Online (Sandbox Code Playgroud)
这里的问题是如何让设计成为一个类,以便某些方法可以以这种方式"链接".
task()需要访问queue类实例属性,操作task取决于输出region().
我看到SQLalchemy做了这个(见下文),但我很难深入挖掘他们的代码并隔离这种模式.
query = db.query(Task).filter(Task.objectid==10100)
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 14
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))
Run Code Online (Sandbox Code Playgroud)
每次调用.region()或.task()将生成一个克隆,其中装饰方法通过更改状态进行更新.然后返回克隆,保持原始实例对象不变.
只需从region方法返回当前对象,就像这样
def region(self, my_string):
...
...
return self
Run Code Online (Sandbox Code Playgroud)
由于region返回具有该task功能的当前对象,现在可以进行链接.
注意:
正如@chepner 在评论部分中提到的那样,确保region对对象进行更改self.
| 归档时间: |
|
| 查看次数: |
4771 次 |
| 最近记录: |