面向对象的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

factoryattributefactory属性添加到修饰函数:

>>> @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

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
在Java中从本地文件系统导入文件   spring boot如何在Java SpringBoot项目中集成Olingo(Odata)   java查找连续数组中缺少的第k个元素(超过时间限制)   java为什么在mySql中插入1/2行时会得到2/4行   java不能在静态上下文中使用它   File Observer方法的java My onEvent()部分不起作用   java Netty NioSocketChannel在多线程写入时收到中断消息   java将文件夹与父文件夹一起复制   java我的TictaToe代码出了什么问题?如何检查已采取的措施?   java Swing JTable更新   java如何将cordinates查找为int   如何使用selenium和java在firefox中打开新的空选项卡   java Gradle构建输出Jar未运行   java没有GET/WEBINF/jsp/login的映射。jsp