类的基于mixin的扩展的替代方法。
plumber的Python项目详细描述
水管工是基于混合的类扩展的替代品。动机
给出了python子类
的一个不完整的限制和/或设计选择列表以及水管工的解决方案。管道系统用代码示例详细描述。解释了一些设计选择和正在进行的
讨论。最后,在Miscellanea中,您可以找到术语、
覆盖率报告、贡献者列表、更改和一些TOdo。所有
非实验性功能都经过全面测试。
内容:
:深度:2
动机:子类化的局限性内容:
:本地:
所有
上的名称以及正在扩展的基类。
…代码块::pycon
>;>;类mixin(对象):
…a=1
>>>类混合2(对象):
…A=2
…b=2
>;>base=dict
>;>class mixedclass(mixin,mixin,base):
…传递
>;>mixedclass.a
1
>;>mixedclass.b
2
>;>mixedclass.keys
<;dict对象的方法"keys">;
链中后面的mixin不能优先于前面的mixin。
**解决方案**:水管工提供了3个装饰器,可以更好地控制
优先级(``default`,``override`,``最后敲定```.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"熟食"和"食物",
字典的所有其他方法都可以建立在这些方法的基础上。将存储转换为完整的mixin需要能够提供默认方法,如果基类没有提供(更有效的)实现,则采用此方法。
**解决方案**:plumber提供"default"装饰器来启用此类默认值。
`"super"链在类期间不进行验证。创建
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在传递之前,可以使用``super````mixin``来构建一个方法链,将`
键小写,`` mixi2``在返回结果之前,将结果乘以2
,两者都很健谈地讨论开始/停止。
代码块::pycon
>;>;类mixin(对象):
…定义获取项(self,key):
…打印"mixin start"
…key=key.lower()
…ret=super(mixin,self).\uu getitem(key)
…打印"mixin stop"
…ret
>>gt;类混合2(对象):
…定义获取项(self,key):
…打印"mixin start"
…ret=super(mixi2,self).\uu getitem(key)
…ret=2*ret
…打印"mixin stop"
…ret ret
>;>base=dict
>;>class mixedclass(mixin,mixin,base):
…通过
>;>mc=mixedclass()
>;>mc['abc']=6
>;>mc['abc']
mixin start
mixin start
mixin stop
mixin stop
12
`dict.\uu getitem\uuu``在返回值时形成链的端点
链接到链中稍后的方法(使用"super")。如果没有端点,则在运行时引发"attributeerror",而不是在创建类时引发。代码块::pycon
>;>;类mixin(对象):
…定义foo(self):
…super(mixin,self).foo()
>;>>类混合类(mixin,base):
…通过
>;>;mc=mixedclass()
>;>;mc.foo()
回溯(最后一次调用):
…
attributeerror:"super"对象没有属性"foo"
**解决方案**:plumber提供"plumb"装饰器,以使用嵌套闭包构建类似的链。这些是在类创建期间创建和验证的。
没有条件的"super"链
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
根据基类是否提供方法,无法有条件地钩住方法调用。
**解决方案**:plumber提供行为类似于"plumb"的"plumbifexists"装饰器,如果有可用的端点,
docstring不会累积
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**使用mixin的类docstring不是从
mixin的docstring生成的。
**解决方案**:plumber使用特殊的标记
`````````下一个不带标记的"mixin"
的docstring替换,docstrings是连接的。
管道系统
----
``plumber`元类根据管道行为中的说明创建管道类。首先,收集所有指令,然后将它们应用于两个阶段:阶段1:扩展,阶段2:管道、文档字符串和可选的"zope.interfaces"。有一个类装饰器"plumbing",应该使用它来支持从plumbler 1.3开始直接设置元类。内容:
:本地:
管道行为提供指令
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
管道行为对应于混合,但更强大和灵活。a
管道行为需要从"plumber.behavior"继承,并声明
属性以及如何使用它们的说明,下面是
"default"指令的示例(稍后)。代码块::pycon
>;>from plumber import behavior
>;>from plumber import default
>;>class behavior 1(behavior):
…A=默认值(真)
…
…@默认值
…定义foo(self):
…返回42
>;>;类行为2(行为):
…@默认值
…@属性
…定义栏(自):
…返回17
这些指令是作为赋值行为(``a=default(none)`)
或作为装饰器(``@default``)`)给出的。
plumbing声明将``plumbler``定义为元类和一个或多个要从左到右处理的管道行为。此外,它可以像每个普通类一样声明
属性,它们将被视为隐式的
``finalize``指令(请参阅第1阶段:扩展)。
…代码块::pycon
>;>来自水管工导入管道
>;>base=dict
>;@管道(behavior1,behavior2)
…类管道(基础):
…
…定义foobar(self):
…返回5
结果是根据管道声明创建的管道类。
…代码块::pycon
>;>plb=plumbing()
>;>plb.a
true
>;>plb.foo()
42
>;>plb.bar
>>17
>;>plb.foobar()
5
>;>>;plb['a']=1
>;>plb['a']
1
代码块::pycon
>;>class sub(管道):
…a='sub'
>;>sub.a
'sub'
>;>sub().foo()
42
>;>sub().bar
17
>;>gt;sub().foobar()
5
水管工收集指令
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
管道声明通过"管道"装饰器提供行为列表。行为提供两个阶段应用的指令:
stage1
-通过"default"、"override"和"finalize"扩展,这个
阶段的结果是阶段2的基础。
阶段2
-通过"plumb"和"plumbifexists"创建管道
-文档字符串的管道
-从"zope.interface"实现接口,iff可用
水管工从左到右(行为顺序)遍历行为列表。它以
的方式将指令收集到堆栈上,并按阶段和属性名排序。a保存所有指令的历史记录。代码块::pycon
>;>;pprint(管道和管道堆栈)
{history':
[<;&u实现非有效负载的接口',
<;默认'a'<;类'behavior1'>;有效负载=true>;,
<;默认'foo'<;类"behavior1">;payload=<;函数foo在x…>;,
<;\u实现非payload=()>;,
<;类"behavior2"的默认"bar">;payload=<;属性对象在x…>;],
"阶段":
{stage1':
{a':[<;默认'a'属于<;类'behavior1'>;有效载荷=真>;],
'bar':[<;默认'bar'属于<;类'behavior2'>;有效载荷=<;属性…
'foo':[<;默认'foo'属于<;类'behavior1'>;payload=<;function foo…
"stage2":
{"uu interfaces":[<;"u实现"非payload=()"uu interfaces"…
它要么按原样接受、丢弃、合并,要么引发一个
"plumbingcollision"。这将在以下章节中详细说明。
在所有指令收集到堆栈上之后,它们被应用于两个
阶段,其中考虑了管道类和基类的声明。
第一阶段的结果是应用第二阶段的基础。
。注意:指令的有效负载是通过函数调用或修饰传递给
指令的属性值。指令知道其声明的
行为。注意:行为是由"behaviorMetaClass"创建的。如果``zope.interface`
可用,它将为每个行为生成```implements``指令。
在行为创建过程中,接口尚未实现,将在稍后阶段进行检查。因此,即使行为没有实现接口,也会生成```implements``指令,这会导致
将空元组作为有效负载(另请参见``zope.interface support``.
。警告:不要依赖程序中的这个结构,它随时都可能改变。如果您需要"管道立管"中的信息,或者其中缺少
信息,例如,要创建管道检查员并为自己赢得一盒您最喜欢的饮料,请通知我们。
stage 1:extension
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
阶段2中创建的管道的终结点。如果
没有管道使用端点,则它将作为
管道类字典中的普通属性存在。
NGEST扩展指令。它将重写基类上的
声明和所有其他扩展指令
("override"和"default")。声明为
管道声明行为的属性是隐式的"finalize"声明。一个属性名的两个finalize将在类创建期间发生冲突并引发一个
``plumbingcollision`。
``override``
``override``比`finalize``弱,并重写基于
类和`default`声明的声明。
相同属性名的两个"override"指令不会冲突,而是使用第一个指令。
``default`
``default``是最弱的扩展指令。它甚至不会重写基类的
声明。第一个默认值将优先于随后的默认值。内容:
:本地:
交互:`` finalize``,管道申报和基类
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~代码块::pycon
>;>来自水管工导入finalize
>;>类行为1(行为):
…n=完成('behavior1')
…
>>>>类行为2(行为):
…m=定版('behavior2')
>>>类库(对象):
…k='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…l='管道'
>>>>>对于x in['k','l','m','n']:
…打印"%s from%s"%(x,getattr(plupping,x))
k from base
l from plupping
m from behavior2
n from behavior1
summary:
-k-q:由行为定义的属性,管道类和基类
-f:``finalize``声明
-x:管道类或基类声明
-?:基类声明不相关
-**y**:所选端点
-冲突:指示无效的组合,该组合引发一个``PlumbingCollision``
+——+——+——+——+——+——+——+——+——+——
attr behavior1 behavior2 pumbling base确定吗?|
=====================================================================================================================================================================================================是吗?||
+——————————————————————————————————————————————————————————————————————————————————————————————||
+————————————————————————————————————————————————————————————————————————————————————————————||
+——————————————————————————————————————————————————————————————————————————————————————————————|碰撞
+——+——+——+——+——+——+——+——+——+——+——+
p f x?|碰撞
+——+——+——+——+——+——+——+——+——+——+——
q f f?|碰撞
+——+——+——+——+——+——+——+——+——+——+——+
碰撞。
……代码块::pycon
>;>;类行为1(行为):
…o=完成(错误)
>;@管道(行为1)
…类管道(对象):
…o=真
回溯(最近一次调用):
…
管道碰撞:
管道类
具有:
<;确定<;类'behavior1'的'o'>;负载=假>;
>;>;类behavior2(行为):
…p=最终确定(错误)
>;@管道(行为2)
…类管道(对象):
…p=真
回溯(最近一次调用):
…
管道碰撞:
管道类
使用:
<;finalize‘p’of<;class‘behavior2’>;payload=false>;
>;>;class behavior1(behavior):
…q=最终确定(假)
>>>;类行为2(行为):
…q=最终确定(真)
>;@管道(behavior1,behavior2)
…类管道(对象):
…传递
回溯(最近一次调用的最后一次):
…
铅垂碰撞:
<;finalize'q'of<;class'behavior1'>;payload=false>;
with:
<;finalize'q'of<;class'behavior2'>;payload=true>;
交互:``override`,管道声明和基类
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
代码块::pycon
>;>来自水管工导入覆盖
>;>类行为1(行为):
…K=覆盖('behavior1')
…m=重写('behavior1')
>>>;类行为2(行为):
…K=覆盖('behavior2')
…L=覆盖('behavior2')
…m=重写('behavior2')
>>>类库(对象):
…K=‘基础’
…L=‘基础’
…m='基础'
>;@管道(行为1,行为2)
…类管道(基础):
…k='管道'
>>>>>对于x in['k','l','m']:
…打印"%s from%s"%(x,getattr(plupping,x))
k from plupping
l from behavior2
m from behavior1
摘要:
-k-m:由行为定义的属性,管道类和基类
-e:``override``声明
-x:管道类或基类声明
-?:基类声明与基类声明无关
-**y**:选择终点
>>>>+-------+------++--++-
124e***x**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——+——+——+——+——+——+——+——
代码块::pycon
>;>;类行为1(行为):
…n=默认值('behavior1')
>;>>类行为2(行为):
…k=默认值('behavior2')
…L=默认值('behavior2')
…m=默认值('behavior2')
…n=默认值('behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…l='管道'
>>>>>对于x in['k','l','m','n']:
…打印"%s from%s"%(x,getattr(plupping,x))
k from base
l from plupping
m from behavior2
n from behavior1
summary:
-k-n:由行为、管道类和基类定义的属性
-d=``default``声明管道等级或基类
-?基类声明与基类声明无关
-**y**=Y选终点
>>>>>>>>>>>>>>>>-----+-----+----++--->
attr behavior1 behavior2管道基地;
>+==================================================================================124d**x**|
+——————————————————————————————————————————————————————————————————————————————————————————————< BR>+——+——+——+——+——+——+———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————|||
+——+——+——+——+——+——+——+——+——
代码块::pycon
>;>;类行为1(行为):
…K=覆盖('behavior1')
…L=最终确定('Behavior1')
>>>类行为2(行为):
…K=完成('behavior2')
…l=重写('behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…对于x in['k','l']:
打印"%s from%s"%(x,getattr(管道,x))
k from behavior2
l from behavior1
summary:
-k-l:由行为、管道类和基类定义的属性
-e=``override``声明
-f=``finalize``声明
-?基类声明与基类声明无关,基类声明与所选端点无关
>+————+————+————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————124;**F**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——+——+——+——+——+——+——+——+——
交互:``finalize``战胜``default```:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~代码块::pycon
>;>;类行为1(行为):
…k=默认值('behavior1')
…L=最终确定('Behavior1')
>>>类行为2(行为):
…K=完成('behavior2')
…L=默认值('Behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…对于x in['k','l']:
打印"%s from%s"%(x,getattr(plupping,x))
k from behavior2
l from behavior1
summary:
-k-l:由行为、管道类和基类定义的属性
-d=``默认``声明
-f=``完成``声明
-?基类声明与基类声明无关,基类声明与所选终点无关
>>+————+——————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————124;**F**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——+——+——+——+——+——+——+——
代码块::pycon
>;>;类行为1(行为):
…k=默认值('behavior1')
…L=重写('behavior1')
>;>>类行为2(行为):
…K=覆盖('behavior2')
…L=默认值('Behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…对于x in['k','l']:
打印"%s from%s"%(x,getattr(管道,x))
k from behavior2
l from behavior1
摘要:
-k-l:由行为、管道类和基类定义的属性
-d=``default``声明
-e=``override``声明
-?基类声明与基类声明无关,基类声明与所选终点无关
>>+————+——————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————124;**E**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|代码中的子类化行为。代码块::pycon
>;>;类行为1(行为):
…j=默认值('behavior1')
…k=默认值('behavior1')
…m=重写('behavior1')
>;>>类行为2(behavior1):
…j=default('behavior2')覆盖``behavior1``的``j```
…L=默认值('behavior2')
…m=default('behavior2')即使"m"在
上,此项也会获胜…#超类是"override"指令。
…#由于普通的继承行为。
>;@plupping(behavior2)
…类管道(对象):
…通过
>;>plb=plumbing()
>;>plb.j
"行为2"
>;>plb.k
"行为1"
>;>plb.l
"行为2"
>; "行为2"
`` zope.interface``instructions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^管道管道对应于
``超级``链条。管道中的行为、方法和属性的文档字符串将累积。水管工是"zope.interface"的感知者,如果可以导入,则从行为中获取实现的接口。内容:
:本地:
管道。这种管道方法的特征是``def foo(`u next,self,*args,**kw)``。通过
```u next``传递要调用的下一个管道方法。`` self``是管道类的一个实例,而不是行为。
``plumb if exists`
类似于'plumb``,但只在端点存在时使用。
因此,
管道建成后,将为每个管道生成一个入口方法,
将第一个管道方法包装成正确的"下一个"。每个
``` u next``方法都是管道其余部分的入口。
跳过不定义具有相同属性名的管道元素的行为:
+--+--+--+--+--+--+--+--+--+--+--+
||————————————————————————————————————————————————————————————————————————————————————————————————|
a y y
n lt;————————————————————————————————————————————————————————————————————————————————---+————+
e————>;
s z z
<;—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————`` behavior1``小写
键在传递之前,``behavior2``将结果相乘,然后返回
。
。代码块::pycon
>;>来自水管工导入水管
>;>类行为1(行为):
…@铅垂
…定义获取项目(下一个,自己,键):
…打印"behavior1 start"
…key=key.lower()
…ret=下一个(self,key)
…打印"behavior1 stop"
…返回ret
>>>>类行为2(行为):
…@铅垂
…定义获取项目(下一个,自己,键):
…打印"behavior2 start"
…ret=2*_next(self,key)
…打印"behavior2 stop"
…ret ret
>;>base=dict
>;@管道(behavior1,behavior2)
…类管道(基础):
…通过管道需要端点。如果没有可用的端点,则会引发
``attributeerror`。
…代码块::pycon
>;>;类行为1(行为):
…@铅垂
…定义foo(_next,self):
…通过管道(行为1)
…类管道(对象):
…pass
traceback(最近一次调用的最后一次):
…
attributeerror:type object'plupping'没有属性'foo'
代码块::pycon
>>gt;来自水管工导入管道存在
>>gt;类行为1(行为):
…@铅存在
…定义foo(_next,self):
…通过
…
…@铅存在
…定义栏(_next,self):
…下一个返回2*(self)
>;@管道(behavior1)
…类管道(对象):
…
…定义栏(自):
…返回6
>;>;hasattr(管道,"foo")
false
>;>;管道().bar()
12
用于实现
`````getitem``和````setitem``的读写词典和只读词典,仅实现````getitem``而不实现```setitem``。
代码块::pycon
>;>;类行为1(行为):
…@铅垂
…@属性
…定义foo(_next,self):
…下一个返回2*(self)
>;@管道(behavior1)
…类管道(对象):
…
…@属性
…定义foo(self):
…返回3
>;>;plb=plumbing()
>;>;plb.foo
6
代码块::pycon
>;>;类行为1(行为):
…@铅垂
…@属性
…定义foo(_next,self):
…return 2*_next(self)
>>>;类行为2(行为):
…def set_foo(self,value):
…self._foo=值
…foo=plumb(属性(
…无,
…覆盖(设置foo),
…)
>;@管道(行为1,行为2)
…类管道(对象):
…
…@属性
…定义foo(self):
…返回self._foo
>;>;plb=plumbing()
>;>;plb.foo=4
>;>;plb.foo
8
>子类化行为
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
通过普通的子类化规则互相覆盖,流水线指令被聚合。代码块::pycon
>;>;类行为1(行为):
…
…@铅垂
…定义foo(_next,self):
…返回"behavior1"+_next(self)
…
…@铅垂
…定义栏(_next,self):
…返回"behavior1"+_next(self)
>>>;类behavior2(behavior1):
…
…@铅垂
…定义foo(_next,self):
…return'behavior2'+@下一个(self)
>;@管道(behavior2)
…类管道(对象):
…
…定义foo(self):
…返回"foo"
…
…定义栏(自):
…返回"bar"
>;>;plb=plumbing()
>;>;plb.foo()
"behavior2 behavior1 foo"
>;>;plb.bar()
"behavior1 bar"
不可能将属性与方法混合。代码块::pycon
>;>;类行为1(行为):
…@铅垂
…定义foo(_next,self):
…返回下一个(自身)
>;@管道(行为1)
…类管道(对象):
…
…@属性
…定义foo(self):
…返回5
回溯(最后一次调用的最近一次):
…
垂直冲突:
<;类"behavior1"的垂直"foo">;负载=<;函数foo at x…>;
使用:
<;类"管道">;
方法和属性
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
管道声明和行为类的正常docstring,铅垂
方法和铅垂属性由新行连接,新行以
铅垂声明开始,然后按相反顺序连接行为。
代码块::pycon
>>p1类(行为):
…""p1
…""
…@铅垂
…def foo(自我):
…""p1.foo
…""
…bar=垂直(属性(none,none,none,"p1.bar"))
>;>p2类(行为):
…@覆盖
…def foo(自我):
…""p2.foo
…"
…bar=铅垂线(属性(none,none,none,"p2.bar"))
>;@管道(p1,p2)
…类管道(对象):
…""管道
…""
…bar=属性(none,none,none,"plupping.bar")
>;>print plupping.\uu doc
plupping
<;blankline>;
&p1
<;blankline>;
>;print plupping.foo.\uu doc
p2.foo
<;blankline>;
p1.foo
<;空白线gt;
>;>print plumbing.bar.\uu doc\uu
plumbing.bar
<;blankline>;
p2.bar
<;blankline>;
p1.bar
docstring的累积是一个实验特性,可能会发生
更改。
槽和管道
~~~~~~~~~~~~~~~~~~~~
代码块::pycon
>>p1类(行为):
…@默认值
…给foo(self,foo_val)写的def somewhing_:
…self.foo=foo值
>;@管道(p1)
…带批(对象)的类:
…_插槽"foo"
>;>;带插槽。"foo"对象的成员"foo">;
>;ob=withslots()
>;>;ob.断言(ob.foo=="foo")
``zope.interface``(如果可用)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
水管工不依赖于``zope.interface``但知道它。这意味着它将尝试导入它,如果可用,它将检查已实现接口的管道行为,并使管道也实现它们。代码块::pycon
>;>来自zope。interface import interface
>;>来自zope。interface import implementer
代码块::pycon
>>>类IBase(接口):
…通过
>;@implementer(ibase)
…基类(对象):
…传递ibase.implementedby(base)
>;
true
代码块::pycon
>>>类ibehavior1(接口):
…通过
>;@implementer(ibehavior1)
…类行为1(行为):
…blub=1
>>>类ibehavior2数据库(接口):
…通过
>;@implementer(ibehavior2base)
…类behavior2base(behavior):
…通过IBehavior2类(接口):
…通过
>;@implementer(ibehavior2)
…类behavior2(behavior2base):
…通过
>;>;ibehavior1.实现者(行为1)
true
>;>;ibehavior2.实现者(行为2base)
true
>;>;ibehavior2.实现者(行为2)
true
>;>;ibehavior2.由(behavior2)实现
true
代码块::pycon
>>>类iplumbingClass(接口):
…通过
>;@implementer(iplumbingclass)
…@管道(行为1,行为2)
…铅垂类(基类):
…pass
实现直接声明和继承的接口。
…代码块::pycon
>;>;iplumbingClass.implemented by(plumbingClass)
true
>;>;ibase.implementedby(plumbingClass)
true
代码块::pycon
>;>;ibehavior1.实现者(PlumbingClass)
true
>;>;ibehavior2.实现者(PlumbingClass)
true
>;>;ibehavior2base.implementedby(PlumbingClass)
true
代码块::pycon
>;>管道=管道类()
>;>iplumbingclasS.ProvidedBy(管道)
true
>;>IBase.ProvidedBy(管道)
>;>IBehavior1.ProvidedBy(管道)
true
>;>IBehavior2.ProvidedBy(管道)
>;>true;ibehavior2base.providedby(管道)
true
plumber元类挂钩
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果一个人在管道工处编写了需要类操作的管道行为
元类执行时间提供了一个装饰器来注册回调
在水管工元类```````函数的末尾执行。
在最后一个任务中执行确保已经执行了阶段1和阶段2的指令,并且我们正在处理一个完整的管道类。
代码块::pycon
>;>>类IBehaviorInterface(接口):
…通过
>;@plumber.metaclasshook
…def test_metclass_hook(cls,name,base,dct):
…如果不是ibehaviorinterface.implementedby(cls):
…返回
…cls.hooked=true
>;@implementer(ibehaviorinterface)
…类元类consideredbehavior(行为):
…通过
>;@plupping(metaclassconsideredbehavior)
…类管道(对象):
…通过
>;>plumbing.hooked
true
Miscellanea
----
修饰符给出的指令是:``default`,
``override`,``finalize`,``plumb``和`plumbifexists`。
**plumbing**
plumbing是由``plumbing``修饰符修饰的类,它被传递给要应用的对象,例如`` plumbing(behavior1,behavior2)``。除了
还考虑了行为、基类声明和请求
管道工的类。创建后,管道看起来像任何
其他类,可以像往常一样进行子类化。
**管道行为**
管道行为提供属性(函数、属性和普通的
值)以及如何使用它们的说明。指令通过decorators:``default``,``override`,``finalize`,``plumb``和
``plumbifexists``给出(参见阶段1:……第二阶段:…).
**管道**
同名管道方法/属性构成管道。入口和终点具有常规方法的特征:``def
foo(self,*args,**kw)``。管道是一系列嵌套的
闭包(见````u next``)。
**入口(方法)**
一种具有正常特征的方法。也就是说,期望"self"作为第一个
参数,用于输入管道。它是一个"下一个"函数。在具有相同名称的类上声明的
方法将被覆盖,但管道中引用的
方法是最里面的方法,即端点。
**`````u next``函数**
````u next``函数用于调用管道中的下一个方法:在
管道的情况下方法,它的包装器将正确的
next```u next``作为第一个参数传递,如果是端点,则只传递
端点方法本身。
**端点(方法)**
方法是从具有"getattr()`"的管道类中检索的,在设置类的入口方法之前。
图片::https://travis-ci.org/bluedynamics/plumber.svg?branch=master
:目标:https://travis ci.org/bluedynamics/plumber
coverage report::
name stmts错过封面--src/管道工/例外情况。py 6 0 100%
src/管道工/说明。py 172 0 100%
src/管道工/管道工心脏/管道工/测试/globalmetaClass.py 15 0 100%
And you will be able to work with other versions (under under under under under under under)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ilaOlah
Changes
-----
1.5~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<><<<<<<<<<<<<<><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- Python 3 support.
[rnix,2017-05-18]
>1.3.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>
<1.3
~~~~~~~~~~~~~~~~~~>
>
>>
~>>
~~~~~~~~~~~~~~~~~~~~~~~呃,部分`.
[rnix,2014年7月31日改用"plumber.override"。
[rnix,2012-07-28]
-压下"plumber.part"。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>~~~~~br/>
-`。plbNext:``而不是'。下一步:`
[ChaoFlow 2011-02]
-阶段1处于"新建"模式,阶段2处于"新建"模式,
[ChaoFlow 2011-01-25]
-指令识别相等指令
[ChaoFlow 2011-01-24]
-来自基类的指令,现在类似于子类继承[ChaoFlow 2011
[ChaoFlow 2011-01-24]
-doctest order管道顺序:<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[ChaoFlow 2011-01-24]
-完全重写
[ChaoFlow 2011-01-22]
-prt,而不是cls
[ChaoFlow,RNIX 2011-01-19
2011-01-04]
许可证/免责声明
——
2011-2017版权所有,Bluedynamics联盟,奥地利,德国,瑞士
保留所有权利。
在满足以下条件的情况下,允许使用:
*源代码的重新分发必须保留上述版权声明、此
条件列表和以下免责声明。
*二进制形式的重新分发必须复制上述版权声明、此
列表文档中的条件和以下免责声明和/或分发时提供的其他材料。
*Bluedynamics联盟的名称或其
贡献者的名称均不得用于认可或推广由此软件衍生的产品未经事先书面许可。S软件由Bluedynamics Alliance"按原样"提供,任何
明示或默示保证,包括但不限于对适销性和特定用途适用性的
默示保证均不作任何声明。在任何情况下,Bluedynamics Alliance均不对任何
直接、间接、附带、特殊、示例或后续损害
(包括但不限于采购替代货物或服务;
使用、数据或利润损失负责;(或业务中断)无论是何种原因造成的,也无论是合同责任、严格责任或侵权责任(包括过失或其他责任)中的任何责任理论,无论是以何种方式使用本软件,即使已被告知或可能或此类损害。
给出了python子类
的一个不完整的限制和/或设计选择列表以及水管工的解决方案。管道系统用代码示例详细描述。解释了一些设计选择和正在进行的
讨论。最后,在Miscellanea中,您可以找到术语、
覆盖率报告、贡献者列表、更改和一些TOdo。所有
非实验性功能都经过全面测试。
内容:
:深度:2
动机:子类化的局限性内容:
:本地:
所有
上的名称以及正在扩展的基类。
…代码块::pycon
>;>;类mixin(对象):
…a=1
>>>类混合2(对象):
…A=2
…b=2
>;>base=dict
>;>class mixedclass(mixin,mixin,base):
…传递
>;>mixedclass.a
1
>;>mixedclass.b
2
>;>mixedclass.keys
<;dict对象的方法"keys">;
链中后面的mixin不能优先于前面的mixin。
**解决方案**:水管工提供了3个装饰器,可以更好地控制
优先级(``default`,``override`,``最后敲定```.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"熟食"和"食物",
字典的所有其他方法都可以建立在这些方法的基础上。将存储转换为完整的mixin需要能够提供默认方法,如果基类没有提供(更有效的)实现,则采用此方法。
**解决方案**:plumber提供"default"装饰器来启用此类默认值。
`"super"链在类期间不进行验证。创建
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在传递之前,可以使用``super````mixin``来构建一个方法链,将`
键小写,`` mixi2``在返回结果之前,将结果乘以2
,两者都很健谈地讨论开始/停止。
代码块::pycon
>;>;类mixin(对象):
…定义获取项(self,key):
…打印"mixin start"
…key=key.lower()
…ret=super(mixin,self).\uu getitem(key)
…打印"mixin stop"
…ret
>>gt;类混合2(对象):
…定义获取项(self,key):
…打印"mixin start"
…ret=super(mixi2,self).\uu getitem(key)
…ret=2*ret
…打印"mixin stop"
…ret ret
>;>base=dict
>;>class mixedclass(mixin,mixin,base):
…通过
>;>mc=mixedclass()
>;>mc['abc']=6
>;>mc['abc']
mixin start
mixin start
mixin stop
mixin stop
12
`dict.\uu getitem\uuu``在返回值时形成链的端点
链接到链中稍后的方法(使用"super")。如果没有端点,则在运行时引发"attributeerror",而不是在创建类时引发。代码块::pycon
>;>;类mixin(对象):
…定义foo(self):
…super(mixin,self).foo()
>;>>类混合类(mixin,base):
…通过
>;>;mc=mixedclass()
>;>;mc.foo()
回溯(最后一次调用):
…
attributeerror:"super"对象没有属性"foo"
**解决方案**:plumber提供"plumb"装饰器,以使用嵌套闭包构建类似的链。这些是在类创建期间创建和验证的。
没有条件的"super"链
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
根据基类是否提供方法,无法有条件地钩住方法调用。
**解决方案**:plumber提供行为类似于"plumb"的"plumbifexists"装饰器,如果有可用的端点,
docstring不会累积
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**使用mixin的类docstring不是从
mixin的docstring生成的。
**解决方案**:plumber使用特殊的标记
`````````下一个不带标记的"mixin"
的docstring替换,docstrings是连接的。
管道系统
----
``plumber`元类根据管道行为中的说明创建管道类。首先,收集所有指令,然后将它们应用于两个阶段:阶段1:扩展,阶段2:管道、文档字符串和可选的"zope.interfaces"。有一个类装饰器"plumbing",应该使用它来支持从plumbler 1.3开始直接设置元类。内容:
:本地:
管道行为提供指令
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
管道行为对应于混合,但更强大和灵活。a
管道行为需要从"plumber.behavior"继承,并声明
属性以及如何使用它们的说明,下面是
"default"指令的示例(稍后)。代码块::pycon
>;>from plumber import behavior
>;>from plumber import default
>;>class behavior 1(behavior):
…A=默认值(真)
…
…@默认值
…定义foo(self):
…返回42
>;>;类行为2(行为):
…@默认值
…@属性
…定义栏(自):
…返回17
这些指令是作为赋值行为(``a=default(none)`)
或作为装饰器(``@default``)`)给出的。
plumbing声明将``plumbler``定义为元类和一个或多个要从左到右处理的管道行为。此外,它可以像每个普通类一样声明
属性,它们将被视为隐式的
``finalize``指令(请参阅第1阶段:扩展)。
…代码块::pycon
>;>来自水管工导入管道
>;>base=dict
>;@管道(behavior1,behavior2)
…类管道(基础):
…
…定义foobar(self):
…返回5
结果是根据管道声明创建的管道类。
…代码块::pycon
>;>plb=plumbing()
>;>plb.a
true
>;>plb.foo()
42
>;>plb.bar
>>17
>;>plb.foobar()
5
>;>>;plb['a']=1
>;>plb['a']
1
代码块::pycon
>;>class sub(管道):
…a='sub'
>;>sub.a
'sub'
>;>sub().foo()
42
>;>sub().bar
17
>;>gt;sub().foobar()
5
水管工收集指令
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
管道声明通过"管道"装饰器提供行为列表。行为提供两个阶段应用的指令:
stage1
-通过"default"、"override"和"finalize"扩展,这个
阶段的结果是阶段2的基础。
阶段2
-通过"plumb"和"plumbifexists"创建管道
-文档字符串的管道
-从"zope.interface"实现接口,iff可用
水管工从左到右(行为顺序)遍历行为列表。它以
的方式将指令收集到堆栈上,并按阶段和属性名排序。a保存所有指令的历史记录。代码块::pycon
>;>;pprint(管道和管道堆栈)
{history':
[<;&u实现非有效负载的接口',
<;默认'a'<;类'behavior1'>;有效负载=true>;,
<;默认'foo'<;类"behavior1">;payload=<;函数foo在x…>;,
<;\u实现非payload=()>;,
<;类"behavior2"的默认"bar">;payload=<;属性对象在x…>;],
"阶段":
{stage1':
{a':[<;默认'a'属于<;类'behavior1'>;有效载荷=真>;],
'bar':[<;默认'bar'属于<;类'behavior2'>;有效载荷=<;属性…
'foo':[<;默认'foo'属于<;类'behavior1'>;payload=<;function foo…
"stage2":
{"uu interfaces":[<;"u实现"非payload=()"uu interfaces"…
它要么按原样接受、丢弃、合并,要么引发一个
"plumbingcollision"。这将在以下章节中详细说明。
在所有指令收集到堆栈上之后,它们被应用于两个
阶段,其中考虑了管道类和基类的声明。
第一阶段的结果是应用第二阶段的基础。
。注意:指令的有效负载是通过函数调用或修饰传递给
指令的属性值。指令知道其声明的
行为。注意:行为是由"behaviorMetaClass"创建的。如果``zope.interface`
可用,它将为每个行为生成```implements``指令。
在行为创建过程中,接口尚未实现,将在稍后阶段进行检查。因此,即使行为没有实现接口,也会生成```implements``指令,这会导致
将空元组作为有效负载(另请参见``zope.interface support``.
。警告:不要依赖程序中的这个结构,它随时都可能改变。如果您需要"管道立管"中的信息,或者其中缺少
信息,例如,要创建管道检查员并为自己赢得一盒您最喜欢的饮料,请通知我们。
stage 1:extension
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
阶段2中创建的管道的终结点。如果
没有管道使用端点,则它将作为
管道类字典中的普通属性存在。
NGEST扩展指令。它将重写基类上的
声明和所有其他扩展指令
("override"和"default")。声明为
管道声明行为的属性是隐式的"finalize"声明。一个属性名的两个finalize将在类创建期间发生冲突并引发一个
``plumbingcollision`。
``override``
``override``比`finalize``弱,并重写基于
类和`default`声明的声明。
相同属性名的两个"override"指令不会冲突,而是使用第一个指令。
``default`
``default``是最弱的扩展指令。它甚至不会重写基类的
声明。第一个默认值将优先于随后的默认值。内容:
:本地:
交互:`` finalize``,管道申报和基类
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~代码块::pycon
>;>来自水管工导入finalize
>;>类行为1(行为):
…n=完成('behavior1')
…
>>>>类行为2(行为):
…m=定版('behavior2')
>>>类库(对象):
…k='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…l='管道'
>>>>>对于x in['k','l','m','n']:
…打印"%s from%s"%(x,getattr(plupping,x))
k from base
l from plupping
m from behavior2
n from behavior1
summary:
-k-q:由行为定义的属性,管道类和基类
-f:``finalize``声明
-x:管道类或基类声明
-?:基类声明不相关
-**y**:所选端点
-冲突:指示无效的组合,该组合引发一个``PlumbingCollision``
+——+——+——+——+——+——+——+——+——+——
attr behavior1 behavior2 pumbling base确定吗?|
=====================================================================================================================================================================================================是吗?||
+——————————————————————————————————————————————————————————————————————————————————————————————||
+————————————————————————————————————————————————————————————————————————————————————————————||
+——————————————————————————————————————————————————————————————————————————————————————————————|碰撞
+——+——+——+——+——+——+——+——+——+——+——+
p f x?|碰撞
+——+——+——+——+——+——+——+——+——+——+——
q f f?|碰撞
+——+——+——+——+——+——+——+——+——+——+——+
碰撞。
……代码块::pycon
>;>;类行为1(行为):
…o=完成(错误)
>;@管道(行为1)
…类管道(对象):
…o=真
回溯(最近一次调用):
…
管道碰撞:
管道类
具有:
<;确定<;类'behavior1'的'o'>;负载=假>;
>;>;类behavior2(行为):
…p=最终确定(错误)
>;@管道(行为2)
…类管道(对象):
…p=真
回溯(最近一次调用):
…
管道碰撞:
管道类
使用:
<;finalize‘p’of<;class‘behavior2’>;payload=false>;
>;>;class behavior1(behavior):
…q=最终确定(假)
>>>;类行为2(行为):
…q=最终确定(真)
>;@管道(behavior1,behavior2)
…类管道(对象):
…传递
回溯(最近一次调用的最后一次):
…
铅垂碰撞:
<;finalize'q'of<;class'behavior1'>;payload=false>;
with:
<;finalize'q'of<;class'behavior2'>;payload=true>;
交互:``override`,管道声明和基类
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
代码块::pycon
>;>来自水管工导入覆盖
>;>类行为1(行为):
…K=覆盖('behavior1')
…m=重写('behavior1')
>>>;类行为2(行为):
…K=覆盖('behavior2')
…L=覆盖('behavior2')
…m=重写('behavior2')
>>>类库(对象):
…K=‘基础’
…L=‘基础’
…m='基础'
>;@管道(行为1,行为2)
…类管道(基础):
…k='管道'
>>>>>对于x in['k','l','m']:
…打印"%s from%s"%(x,getattr(plupping,x))
k from plupping
l from behavior2
m from behavior1
摘要:
-k-m:由行为定义的属性,管道类和基类
-e:``override``声明
-x:管道类或基类声明
-?:基类声明与基类声明无关
-**y**:选择终点
>>>>+-------+------++--++-
124e***x**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——+——+——+——+——+——+——+——
代码块::pycon
>;>;类行为1(行为):
…n=默认值('behavior1')
>;>>类行为2(行为):
…k=默认值('behavior2')
…L=默认值('behavior2')
…m=默认值('behavior2')
…n=默认值('behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…l='管道'
>>>>>对于x in['k','l','m','n']:
…打印"%s from%s"%(x,getattr(plupping,x))
k from base
l from plupping
m from behavior2
n from behavior1
summary:
-k-n:由行为、管道类和基类定义的属性
-d=``default``声明管道等级或基类
-?基类声明与基类声明无关
-**y**=Y选终点
>>>>>>>>>>>>>>>>-----+-----+----++--->
attr behavior1 behavior2管道基地;
>+==================================================================================124d**x**|
+——————————————————————————————————————————————————————————————————————————————————————————————< BR>+——+——+——+——+——+——+———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————|||
+——+——+——+——+——+——+——+——+——
代码块::pycon
>;>;类行为1(行为):
…K=覆盖('behavior1')
…L=最终确定('Behavior1')
>>>类行为2(行为):
…K=完成('behavior2')
…l=重写('behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…对于x in['k','l']:
打印"%s from%s"%(x,getattr(管道,x))
k from behavior2
l from behavior1
summary:
-k-l:由行为、管道类和基类定义的属性
-e=``override``声明
-f=``finalize``声明
-?基类声明与基类声明无关,基类声明与所选端点无关
>+————+————+————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————124;**F**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——+——+——+——+——+——+——+——+——
交互:``finalize``战胜``default```:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~代码块::pycon
>;>;类行为1(行为):
…k=默认值('behavior1')
…L=最终确定('Behavior1')
>>>类行为2(行为):
…K=完成('behavior2')
…L=默认值('Behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…对于x in['k','l']:
打印"%s from%s"%(x,getattr(plupping,x))
k from behavior2
l from behavior1
summary:
-k-l:由行为、管道类和基类定义的属性
-d=``默认``声明
-f=``完成``声明
-?基类声明与基类声明无关,基类声明与所选终点无关
>>+————+——————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————124;**F**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|
+——+——+——+——+——+——+——+——
代码块::pycon
>;>;类行为1(行为):
…k=默认值('behavior1')
…L=重写('behavior1')
>;>>类行为2(行为):
…K=覆盖('behavior2')
…L=默认值('Behavior2')
>>>类库(对象):
…K=‘基础’
…l='基础'
>;@plupping(behavior1,behavior2)
…类管道(基础):
…对于x in['k','l']:
打印"%s from%s"%(x,getattr(管道,x))
k from behavior2
l from behavior1
摘要:
-k-l:由行为、管道类和基类定义的属性
-d=``default``声明
-e=``override``声明
-?基类声明与基类声明无关,基类声明与所选终点无关
>>+————+——————+—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————124;**E**?|
+——————————————————————————————————————————————————————————————————————————————————————————————|代码中的子类化行为。代码块::pycon
>;>;类行为1(行为):
…j=默认值('behavior1')
…k=默认值('behavior1')
…m=重写('behavior1')
>;>>类行为2(behavior1):
…j=default('behavior2')覆盖``behavior1``的``j```
…L=默认值('behavior2')
…m=default('behavior2')即使"m"在
上,此项也会获胜…#超类是"override"指令。
…#由于普通的继承行为。
>;@plupping(behavior2)
…类管道(对象):
…通过
>;>plb=plumbing()
>;>plb.j
"行为2"
>;>plb.k
"行为1"
>;>plb.l
"行为2"
>;
`` zope.interface``instructions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^管道管道对应于
``超级``链条。管道中的行为、方法和属性的文档字符串将累积。水管工是"zope.interface"的感知者,如果可以导入,则从行为中获取实现的接口。内容:
:本地:
管道。这种管道方法的特征是``def foo(`u next,self,*args,**kw)``。通过
```u next``传递要调用的下一个管道方法。`` self``是管道类的一个实例,而不是行为。
``plumb if exists`
类似于'plumb``,但只在端点存在时使用。
因此,
管道建成后,将为每个管道生成一个入口方法,
将第一个管道方法包装成正确的"下一个"。每个
``` u next``方法都是管道其余部分的入口。
跳过不定义具有相同属性名的管道元素的行为:
+--+--+--+--+--+--+--+--+--+--+--+
||————————————————————————————————————————————————————————————————————————————————————————————————|
a y y
n lt;————————————————————————————————————————————————————————————————————————————————---+————+
e————>;
s z z
<;—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————`` behavior1``小写
键在传递之前,``behavior2``将结果相乘,然后返回
。
。代码块::pycon
>;>来自水管工导入水管
>;>类行为1(行为):
…@铅垂
…定义获取项目(下一个,自己,键):
…打印"behavior1 start"
…key=key.lower()
…ret=下一个(self,key)
…打印"behavior1 stop"
…返回ret
>>>>类行为2(行为):
…@铅垂
…定义获取项目(下一个,自己,键):
…打印"behavior2 start"
…ret=2*_next(self,key)
…打印"behavior2 stop"
…ret ret
>;>base=dict
>;@管道(behavior1,behavior2)
…类管道(基础):
…通过管道需要端点。如果没有可用的端点,则会引发
``attributeerror`。
…代码块::pycon
>;>;类行为1(行为):
…@铅垂
…定义foo(_next,self):
…通过管道(行为1)
…类管道(对象):
…pass
traceback(最近一次调用的最后一次):
…
attributeerror:type object'plupping'没有属性'foo'
代码块::pycon
>>gt;来自水管工导入管道存在
>>gt;类行为1(行为):
…@铅存在
…定义foo(_next,self):
…通过
…
…@铅存在
…定义栏(_next,self):
…下一个返回2*(self)
>;@管道(behavior1)
…类管道(对象):
…
…定义栏(自):
…返回6
>;>;hasattr(管道,"foo")
false
>;>;管道().bar()
12
用于实现
`````getitem``和````setitem``的读写词典和只读词典,仅实现````getitem``而不实现```setitem``。
代码块::pycon
>;>;类行为1(行为):
…@铅垂
…@属性
…定义foo(_next,self):
…下一个返回2*(self)
>;@管道(behavior1)
…类管道(对象):
…
…@属性
…定义foo(self):
…返回3
>;>;plb=plumbing()
>;>;plb.foo
6
代码块::pycon
>;>;类行为1(行为):
…@铅垂
…@属性
…定义foo(_next,self):
…return 2*_next(self)
>>>;类行为2(行为):
…def set_foo(self,value):
…self._foo=值
…foo=plumb(属性(
…无,
…覆盖(设置foo),
…)
>;@管道(行为1,行为2)
…类管道(对象):
…
…@属性
…定义foo(self):
…返回self._foo
>;>;plb=plumbing()
>;>;plb.foo=4
>;>;plb.foo
8
>子类化行为
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
通过普通的子类化规则互相覆盖,流水线指令被聚合。代码块::pycon
>;>;类行为1(行为):
…
…@铅垂
…定义foo(_next,self):
…返回"behavior1"+_next(self)
…
…@铅垂
…定义栏(_next,self):
…返回"behavior1"+_next(self)
>>>;类behavior2(behavior1):
…
…@铅垂
…定义foo(_next,self):
…return'behavior2'+@下一个(self)
>;@管道(behavior2)
…类管道(对象):
…
…定义foo(self):
…返回"foo"
…
…定义栏(自):
…返回"bar"
>;>;plb=plumbing()
>;>;plb.foo()
"behavior2 behavior1 foo"
>;>;plb.bar()
"behavior1 bar"
不可能将属性与方法混合。代码块::pycon
>;>;类行为1(行为):
…@铅垂
…定义foo(_next,self):
…返回下一个(自身)
>;@管道(行为1)
…类管道(对象):
…
…@属性
…定义foo(self):
…返回5
回溯(最后一次调用的最近一次):
…
垂直冲突:
<;类"behavior1"的垂直"foo">;负载=<;函数foo at x…>;
使用:
<;类"管道">;
方法和属性
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
管道声明和行为类的正常docstring,铅垂
方法和铅垂属性由新行连接,新行以
铅垂声明开始,然后按相反顺序连接行为。
代码块::pycon
>>p1类(行为):
…""p1
…""
…@铅垂
…def foo(自我):
…""p1.foo
…""
…bar=垂直(属性(none,none,none,"p1.bar"))
>;>p2类(行为):
…@覆盖
…def foo(自我):
…""p2.foo
…"
…bar=铅垂线(属性(none,none,none,"p2.bar"))
>;@管道(p1,p2)
…类管道(对象):
…""管道
…""
…bar=属性(none,none,none,"plupping.bar")
>;>print plupping.\uu doc
plupping
<;blankline>;
&p1
<;blankline>;
>;print plupping.foo.\uu doc
p2.foo
<;blankline>;
p1.foo
<;空白线gt;
>;>print plumbing.bar.\uu doc\uu
plumbing.bar
<;blankline>;
p2.bar
<;blankline>;
p1.bar
docstring的累积是一个实验特性,可能会发生
更改。
槽和管道
~~~~~~~~~~~~~~~~~~~~
代码块::pycon
>>p1类(行为):
…@默认值
…给foo(self,foo_val)写的def somewhing_:
…self.foo=foo值
>;@管道(p1)
…带批(对象)的类:
…_插槽"foo"
>;>;带插槽。"foo"对象的成员"foo">;
>;ob=withslots()
>;>;ob.断言(ob.foo=="foo")
``zope.interface``(如果可用)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
水管工不依赖于``zope.interface``但知道它。这意味着它将尝试导入它,如果可用,它将检查已实现接口的管道行为,并使管道也实现它们。代码块::pycon
>;>来自zope。interface import interface
>;>来自zope。interface import implementer
代码块::pycon
>>>类IBase(接口):
…通过
>;@implementer(ibase)
…基类(对象):
…传递ibase.implementedby(base)
>;
true
代码块::pycon
>>>类ibehavior1(接口):
…通过
>;@implementer(ibehavior1)
…类行为1(行为):
…blub=1
>>>类ibehavior2数据库(接口):
…通过
>;@implementer(ibehavior2base)
…类behavior2base(behavior):
…通过IBehavior2类(接口):
…通过
>;@implementer(ibehavior2)
…类behavior2(behavior2base):
…通过
>;>;ibehavior1.实现者(行为1)
true
>;>;ibehavior2.实现者(行为2base)
true
>;>;ibehavior2.实现者(行为2)
true
>;>;ibehavior2.由(behavior2)实现
true
代码块::pycon
>>>类iplumbingClass(接口):
…通过
>;@implementer(iplumbingclass)
…@管道(行为1,行为2)
…铅垂类(基类):
…pass
实现直接声明和继承的接口。
…代码块::pycon
>;>;iplumbingClass.implemented by(plumbingClass)
true
>;>;ibase.implementedby(plumbingClass)
true
代码块::pycon
>;>;ibehavior1.实现者(PlumbingClass)
true
>;>;ibehavior2.实现者(PlumbingClass)
true
>;>;ibehavior2base.implementedby(PlumbingClass)
true
代码块::pycon
>;>管道=管道类()
>;>iplumbingclasS.ProvidedBy(管道)
true
>;>IBase.ProvidedBy(管道)
>;>IBehavior1.ProvidedBy(管道)
true
>;>IBehavior2.ProvidedBy(管道)
>;>true;ibehavior2base.providedby(管道)
true
plumber元类挂钩
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果一个人在管道工处编写了需要类操作的管道行为
元类执行时间提供了一个装饰器来注册回调
在水管工元类```````函数的末尾执行。
在最后一个任务中执行确保已经执行了阶段1和阶段2的指令,并且我们正在处理一个完整的管道类。
代码块::pycon
>;>>类IBehaviorInterface(接口):
…通过
>;@plumber.metaclasshook
…def test_metclass_hook(cls,name,base,dct):
…如果不是ibehaviorinterface.implementedby(cls):
…返回
…cls.hooked=true
>;@implementer(ibehaviorinterface)
…类元类consideredbehavior(行为):
…通过
>;@plupping(metaclassconsideredbehavior)
…类管道(对象):
…通过
>;>plumbing.hooked
true
Miscellanea
----
修饰符给出的指令是:``default`,
``override`,``finalize`,``plumb``和`plumbifexists`。
**plumbing**
plumbing是由``plumbing``修饰符修饰的类,它被传递给要应用的对象,例如`` plumbing(behavior1,behavior2)``。除了
还考虑了行为、基类声明和请求
管道工的类。创建后,管道看起来像任何
其他类,可以像往常一样进行子类化。
**管道行为**
管道行为提供属性(函数、属性和普通的
值)以及如何使用它们的说明。指令通过decorators:``default``,``override`,``finalize`,``plumb``和
``plumbifexists``给出(参见阶段1:……第二阶段:…).
**管道**
同名管道方法/属性构成管道。入口和终点具有常规方法的特征:``def
foo(self,*args,**kw)``。管道是一系列嵌套的
闭包(见````u next``)。
**入口(方法)**
一种具有正常特征的方法。也就是说,期望"self"作为第一个
参数,用于输入管道。它是一个"下一个"函数。在具有相同名称的类上声明的
方法将被覆盖,但管道中引用的
方法是最里面的方法,即端点。
**`````u next``函数**
````u next``函数用于调用管道中的下一个方法:在
管道的情况下方法,它的包装器将正确的
next```u next``作为第一个参数传递,如果是端点,则只传递
端点方法本身。
**端点(方法)**
方法是从具有"getattr()`"的管道类中检索的,在设置类的入口方法之前。
图片::https://travis-ci.org/bluedynamics/plumber.svg?branch=master
:目标:https://travis ci.org/bluedynamics/plumber
coverage report::
name stmts错过封面--src/管道工/例外情况。py 6 0 100%
src/管道工/说明。py 172 0 100%
src/管道工/管道工心脏/管道工/测试/globalmetaClass.py 15 0 100%
And you will be able to work with other versions (under under under under under under under)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ilaOlah
Changes
-----
1.5~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<><<<<<<<<<<<<<><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- Python 3 support.
[rnix,2017-05-18]
>1.3.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>
<1.3
~~~~~~~~~~~~~~~~~~>
>>
~>>
~~~~~~~~~~~~~~~~~~~~~~~呃,部分`.
[rnix,2014年7月31日改用"plumber.override"。
[rnix,2012-07-28]
-压下"plumber.part"。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>~~~~~br/>
-`。plbNext:``而不是'。下一步:`
[ChaoFlow 2011-02]
-阶段1处于"新建"模式,阶段2处于"新建"模式,
[ChaoFlow 2011-01-25]
-指令识别相等指令
[ChaoFlow 2011-01-24]
-来自基类的指令,现在类似于子类继承[ChaoFlow 2011
[ChaoFlow 2011-01-24]
-doctest order管道顺序:<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[ChaoFlow 2011-01-24]
-完全重写
[ChaoFlow 2011-01-22]
-prt,而不是cls
[ChaoFlow,RNIX 2011-01-19
2011-01-04]
许可证/免责声明
——
2011-2017版权所有,Bluedynamics联盟,奥地利,德国,瑞士
保留所有权利。
在满足以下条件的情况下,允许使用:
*源代码的重新分发必须保留上述版权声明、此
条件列表和以下免责声明。
*二进制形式的重新分发必须复制上述版权声明、此
列表文档中的条件和以下免责声明和/或分发时提供的其他材料。
*Bluedynamics联盟的名称或其
贡献者的名称均不得用于认可或推广由此软件衍生的产品未经事先书面许可。S软件由Bluedynamics Alliance"按原样"提供,任何
明示或默示保证,包括但不限于对适销性和特定用途适用性的
默示保证均不作任何声明。在任何情况下,Bluedynamics Alliance均不对任何
直接、间接、附带、特殊、示例或后续损害
(包括但不限于采购替代货物或服务;
使用、数据或利润损失负责;(或业务中断)无论是何种原因造成的,也无论是合同责任、严格责任或侵权责任(包括过失或其他责任)中的任何责任理论,无论是以何种方式使用本软件,即使已被告知或可能或此类损害。