面向对象的curring
Factor的Python项目详细描述
概述
factory是面向对象的部分函数应用程序方法,也称为curring。工厂模块是这个模式的一个更强大的实现。一些改进包括:
- 更安全,因为会立即检测到无效参数,而不是在调用时
- 对类、实例方法和所有其他可调用项的智能支持
- 绑定参数可以作为属性进行检查和修改
- (重新)绑定参数的几种简便方法
- 没有嵌套lambdas的“俄罗斯娃娃”
使用工厂可以:
- 简化回写
- 减少并发应用程序中的错误
- 提供简单的惰性评估
安装
工厂模块可从Cheeseshop获得。可以从Google Code project page获得源代码。
工厂模块可以像任何其他纯python模块一样安装。支持但不是必需的setuptools。您还可以将Factory.py文件直接包含在项目的源树中,但必须保留版权声明、版本和属性信息。
要运行模块测试,请在Factory/目录中执行以下命令:
- python doctest_Factory.py
- nosetests test_Factory.py
关于咖喱
Currin通过绑定一些原始参数:
创建一个新函数>>> def adder(x, y): ... return x + y >>> add_lambda = lambda y: adder(1, y) >>> add_lambda(10) 11
从python 2.5开始,这个模式是用partial函数内置的。
>>> add_partial = functools.partial(adder, 1) >>> add_partial(y=10) 11
工厂
工厂更好地实现了当前模式:
>>> from Factory import * >>> add_factory = Factory(adder, x=1) >>> add_factory #doctest: +ELLIPSIS <Factory(<function adder at ...>) at ...> >>> add_factory(y=10) 11
与lambdas和partial不同,工厂可以检查和修改:
>>> add_factory.x 1 >>> add_factory.x = 2 >>> add_factory(y=10) 12
可以检查将传递给函数的参数,其中 有时有助于调试:
>>> import pprint >>> args, kwargs = add_factory.generateArgs(y=10) >>> pprint.pprint(kwargs) {'x': 2, 'y': 10} >>> args []
用法
在下面的例子中,我们混合了{STR 1 } $FutuMyIXIN <强>以提供一个 ^基类上的{tt5}$classmethod。
>>> class Foo(FactoryMixin): ... def __init__(self, foo): ... self.foo = foo ... >>> foo_factory = Foo.factory() >>> foo_factory.foo = 66
这相当于:
>>> Factory(Foo) #doctest:+ELLIPSIS <Factory(<class 'Foo'>) at ...>
使用MIXIN不是严格必要的,但看起来不错,更容易拼写。
工厂有一个bind方法,可以用来设置几个属性 立即返回工厂。它对绑定参数很有用 不将工厂分配给局部变量。
>>> def doStuff(foo_factory): ... return foo_factory.foo >>> doStuff(foo_factory.bind(foo=11)) 11 >>> foo_factory2 = foo_factory.bind(foo=42) >>> foo_factory2 is foo_factory True >>> foo_factory.foo 42
在构造工厂时,还可以绑定属性:
>>> foo_factory = Factory(Foo, foo=11) >>> foo_factory.foo 11
工厂确保属性与参数匹配;这使得 更容易查找错误(而不是引发unexpected keyword argument 稍后):
>>> foo_factory.bar = 42 #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'No such argument bar'
调用工厂时,参数覆盖属性:
>>> foo = foo_factory(foo=1111) >>> foo.foo 1111
每次调用都返回一个新实例:
>>> foo2 = foo_factory() >>> foo2 is foo False
有效属性集是 继承链:
>>> class Bar(Foo): ... def __init__(self, bar, **kwargs): ... super(Bar, self).__init__(**kwargs) ... self.bar = bar ... >>> bar_factory = Bar.factory() >>> bar_factory.foo = 11 >>> bar_factory.bar = 42 >>> bar_factory.quux = 666 #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'No such argument quux' >>> bar = bar_factory() >>> bar.foo 11 >>> bar.bar 42
确保向factory传递一个可调用对象(类,而不是实例):
>>> Factory(bar) #doctest:+ELLIPSIS, +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: must provide known callable type, not <Factory.Bar object at ...>
可调用的对象当然可以:
>>> class CallMe(object): ... def __init__(self, x): ... self.x = x ... def __call__(self, y): ... return self.x + y >>> Factory(CallMe(1))(1) 2
现有工厂可以作为新工厂的^ {TT8}$。
>>> bar_factory = Bar.factory(bar=2) >>> bar_factory2 = Factory(bar_factory, foo = 1) >>> bar_factory is not bar_factory2 True >>> bar_factory2.bar 2 >>> bar_factory2.bar = 4 >>> bar_factory.bar 2
与使用lambdas不同,这不会创建嵌套的“俄罗斯玩偶”:
>>> bar_factory2.getCallable() <class 'Bar'>
装饰工
returnfactory是一个修饰符,它用其工厂生成的等价函数来替换函数:
>>> @returnFactory ... def mult(x, y): ... return x * y >>> fac = mult(x=10, y=5) >>> isinstance(fac, Factory) True >>> fac() 50
factoryattribute将factory属性添加到修饰函数:
>>> @factoryAttribute ... def adder(x, y): ... return x + y >>> fac = adder.factory(x=10) >>> isinstance(fac, Factory) True >>> fac2 = adder.factory() >>> fac is not fac2 True >>> fac(y=42) 52
factorydescriptor生成具有factory属性的实例方法。在类内部,使用此描述符而不是factoryattribute。这个类可以用作装饰符:
>>> class Quux(object): ... @factoryDescriptor ... def doStuff(self, whatnot): ... pass >>> quux = Quux() >>> fac = quux.doStuff.factory(whatnot=42) >>> isinstance(fac, Factory) True >>> fac.whatnot 42
对象模板
objecttemplates是用于创建对象的模板。他们和工厂合作得很好。
bunch只是一堆属性。将一组关键字参数转换为属性:
>>> b = Bunch(pants=42, shirt=15) >>> b.pants 42 >>> b.shirt 15
调用群返回一个新副本:
>>> c = b() >>> c.__dict__ == b.__dict__ True >>> c is b False
调用时,objecttemplate实例将生成一个新实例 共bunchClass。模板上的属性作为kwargs传递 对一群人来说。但是,如果属性是可调用的,则调用 并使用返回值:
>>> counter = itertools.count(1).next # an incrementing counter >>> def color(): ... return "blue" >>> template = ObjectTemplate(size=42, ... color=color, ... count=counter, ... bunchClass=Bunch) >>> bunch = template() >>> isinstance(bunch, Bunch) True >>> bunch.size 42 >>> bunch.color 'blue' >>> bunch.count 1
对模板的每次调用都会产生一个新的束。任何功能都将 再次拨打电话:
>>> bunch2 = template() >>> bunch2.count 2
如果要将可调用对象传递给束,请将其包装在lambda中:
>>> template = ObjectTemplate() >>> template.return_val = color >>> template.a_function = lambda: color >>> bunch = template() >>> bunch.return_val 'blue' >>> bunch.a_function #doctest:+ELLIPSIS <function color at ...>
错误
错误、功能请求和赞扬可以直接发送到the author。