获取是一种允许对象从其所在的包含层次结构获取属性的机制。
Acquisition的Python项目详细描述
环境收购
这个包实现了python的"环境获取",如 在joseph gil和david h.lorenz的论文中提出 < Buff行情> 我们提出了一个新的编程范式,环境获取 对象聚合的上下文,其中对象获取 运行时当前容器的行为。关键是 部件的性能可能取决于其外壳 复合材料。特别是,我们在 对象从中的对象类"继承"功能 它的环境。通过检查类的声明,它是 可以确定哪些类可能包含 组件,哪些组件必须包含在给定类型的 混合成的。这些关系是语言结构的基础 支持收购。
内容
- 4.6(2019-04-24)
- 4.5(2018-10-05)
- 4.4.4(2017-11-24)
- 4.4.3(2017-11-23)
- 4.4.2(2017-05-12)
- 4.4.1(2017-05-04)
- 4.4.0(2017-05-04)
- 4.3.0(2017-01-20)
- 4.2.2(2015-05-19)
- 4.2.1(2015-04-23)
- 4.2(2015-04-04)
- 4.1(2014-12-18)
- 4.0.3(2014-11-02)
- 4.0.2(2014-11-02)
- 4.0.1(2014-10-30)
- 4.0(2013-02-24)
- 4.0a1(2011-12-13)
- 2.13.9(2015-02-17)
- 2.13.8(2011-06-11)
- 2.13.7(2011-03-02) <HREF="id21"id="id68" rel="nofollow">2.13.6(2011-02-19)
- 2.13.5(2010-09-29)
- 2.13.4(2010-08-31)
- 2.13.3(2010-04-19)
- 2.13.2(2010-04-04)
- 2.13.1(2010-02-23)
- 2.13.0(2010-02-14)
- 2.12.4(2009-10-29)
- 2.12.3(2009-08-08)
- 2.12.2(2009-08-02)
- 2.12.1(2009-04-15)
- 2.12(2009-01-25)
介绍性示例
zope通过类中的"扩展类"混合实现获取。到 使用获取类必须从获取基继承 班级。例如:
>>> import ExtensionClass, Acquisition >>> class C(ExtensionClass.Base): ... color = 'red' >>> class A(Acquisition.Implicit): ... def report(self): ... print(self.color) ... >>> a = A() >>> c = C() >>> c.a = a >>> c.a.report() red >>> d = C() >>> d.color = 'green' >>> d.a = a >>> d.a.report() green >>> try: ... a.report() ... except AttributeError: ... pass ... else: ... raise AssertionError('AttributeError not raised.')
类从 获取。隐式 。对象, a ,"具有"的颜色 当通过对象访问时,对象 c 和d,但它没有 颜色本身。对象从其 环境,其环境由使用的访问路径定义 达到 a
采购包装
当支持采集的对象通过 扩展类实例,一个特殊的对象,称为获取 包装,返回。在上面的例子中,表达式 c.a 返回一个包含对 c 以及a。这个包装器在 c 中执行属性查找 当在 a 中找不到属性时
获取包装器通过 属性 aq_parent , aq_self , aq_base 。继续 以上示例:
>>> c.a.aq_parent is c True >>> c.a.aq_self is a True
显式和隐式采集
支持两种类型的习得:内隐和外显 获取。
隐式采集
隐式获取之所以这样命名是因为它搜索属性 当属性不能 直接从对象或通过继承获得。
如果属性的名称不以开头,则可以隐式获取该属性。 带下划线。
为了支持隐式获取,您的类应该继承自 混合类 获取。隐式
显式采集
使用显式获取时,属性不会自动 从环境中获得的。相反,aq_acquire方法必须是 使用。例如:
>>> print(c.a.aq_acquire('color')) red
为了支持显式获取,您的类应该继承自 在类中混合 获取。显式
控制采集
类(或实例)可以对 收购。您应该从 acquisition.explicit 继承子类,并设置 所有应该获取到特殊值的属性 采集。采集 。将属性设置为此值还允许 要用获取的属性重写的继承属性。例如:
>>> class C(Acquisition.Explicit): ... id = 1 ... secret = 2 ... color = Acquisition.Acquired ... __roles__ = Acquisition.Acquired
从包含 对象是颜色和角色。注意 >角色 阿特里亚特即使它的名字以 强调。实际上,特殊的 acquisition.acquired 值可以是 用于 获取。要隐式获取的隐式对象 闻起来像私人物品的选定对象。
有时,您希望动态地使隐式获取对象 明确获取。你可以通过获取对象的 aq_显式属性。此属性为对象提供 替换原始隐式包装的显式包装。
过滤采集
采集方法aq_acquire接受两个可选 论据。附加参数中的第一个是"筛选" 在考虑是否获取 对象。附加参数中的第二个是 调用筛选函数时作为额外数据传递 默认为 无 。filter函数用5调用 参数:
- 调用aq_acquire方法的对象,
- 找到对象的对象,
- 传递给aq_acquire的对象的名称,
- 找到该对象,并且
- 传递给aq_acquire的额外数据。
如果筛选器返回一个返回所找到对象的真对象, 否则,采集搜索将继续。
下面是一个示例:
>>> from Acquisition import Explicit >>> class HandyForTesting(object): ... def __init__(self, name): ... self.name = name ... def __str__(self): ... return "%s(%s)" % (self.name, self.__class__.__name__) ... __repr__=__str__ ... >>> class E(Explicit, HandyForTesting): pass ... >>> class Nice(HandyForTesting): ... isNice = 1 ... def __str__(self): ... return HandyForTesting.__str__(self)+' and I am nice!' ... __repr__ = __str__ ... >>> a = E('a') >>> a.b = E('b') >>> a.b.c = E('c') >>> a.p = Nice('spam') >>> a.b.p = E('p') >>> def find_nice(self, ancestor, name, object, extra): ... return hasattr(object,'isNice') and object.isNice >>> print(a.b.c.aq_acquire('p', find_nice)) spam(Nice) and I am nice!
最后一行的过滤采集跳过第一行
它找到的属性名为
zope中很少使用过滤式采集。
从上下文获取
通常,采集允许对象从其 容器。但是,对象可以从不是它的对象获取 容器。
到目前为止,我们看到的大多数例子都表明 使用getattr语义的获取上下文。例如, a.b 是 在 a 上下文中对 b 的引用
您也可以使用 方法。例如:
>>> from Acquisition import Implicit >>> class C(Implicit): pass ... >>> a = C() >>> b = C() >>> a.color = "red" >>> print(b.__of__(a).color) red
在这种情况下, a 不包含 b ,但它被放入 b 中 使用方法的上下文。
下面是另一个更微妙的示例,它展示了如何构造 包含非容器对象的获取上下文:
>>> from Acquisition import Implicit >>> class C(Implicit): ... def __init__(self, name): ... self.name = name >>> a = C("a") >>> a.b = C("b") >>> a.b.color = "red" >>> a.x = C("x") >>> print(a.b.x.color) red
即使 b 不包含 x , x 也可以获得颜色 属性来自 b 。这是因为在这种情况下,可以访问 在 b 的上下文中,即使它不包含在 b 中。
这里,获取上下文由用于访问的对象定义 另一个对象。
上下文之前的包含
如果在上面的示例中,假设a和b都有一个颜色属性:
>>> a = C("a") >>> a.color = "green" >>> a.b = C("b") >>> a.b.color = "red" >>> a.x = C("x") >>> print(a.b.x.color) green
为什么 a.b.x.color 从 a 而不是从 b 获取颜色? 答案是一个对象在 上下文中的非容器。
要了解为什么要使用 方法:
a.x -> x.__of__(a) a.b -> b.__of__(a) a.b.x -> x.__of__(a).__of__(b.__of__(a))
请记住,包装器中的属性查找是通过尝试 首先在包装对象中查找属性,然后在 父对象。所以在上面的表达式中,从左到 对,
这些规则的结果是通过 在上下文之前包含。
这个规则也适用于更复杂的例子。例如, a.b.c.d.e.f.g.属性 将在 g 中搜索属性 先把所有的容器都装进去。(按以下顺序搜索容器 如果属性不是 在 g 或其任何容器中发现,然后搜索移动到 f 及其所有容器,等等。
其他属性和方法
您可以使用特殊的方法来访问对象 只能用容器包装。在上面的例子中, a.b.x.aq_inner 等同于 a.x
您可以使用 像这样的aq_链方法:
< Buff行情>>>> import ExtensionClass, Acquisition >>> class C(ExtensionClass.Base): ... color = 'red' >>> class A(Acquisition.Implicit): ... def report(self): ... print(self.color) ... >>> a = A() >>> c = C() >>> c.a = a >>> c.a.report() red >>> d = C() >>> d.color = 'green' >>> d.a = a >>> d.a.report() green >>> try: ... a.report() ... except AttributeError: ... pass ... else: ... raise AssertionError('AttributeError not raised.')0
您可以找出一个对象是否在另一个对象的包含上下文中 对象使用 aq_incontextof 方法。例如:
< Buff行情>>>> import ExtensionClass, Acquisition >>> class C(ExtensionClass.Base): ... color = 'red' >>> class A(Acquisition.Implicit): ... def report(self): ... print(self.color) ... >>> a = A() >>> c = C() >>> c.a = a >>> c.a.report() red >>> d = C() >>> d.color = 'green' >>> d.a = a >>> d.a.report() green >>> try: ... a.report() ... except AttributeError: ... pass ... else: ... raise AssertionError('AttributeError not raised.')1
采集模块功能
除了直接使用采集属性和方法之外 对象可以使用 采集中定义的类似函数 模块。这些函数的优点是 检查以确保对象之前具有方法或属性 呼叫它。
< DL>获取具有给定名称的对象。
此函数可用于在使用显式 获取和获取通常不会是 已获取。
函数接受许多可选参数:
< DL>用于确定对象是否 应该获得。
使用五个参数调用筛选器:
- 调用aq_acquire方法的对象,
- 找到对象的对象,
- 传递给aq_acquire的对象的名称,
- 找到该对象,并且
- 传递给aq_acquire的额外参数。
如果过滤器返回一个真正的对象,则找到的对象是 返回,否则继续进行采集搜索。
指示是否显式获取的标志(布尔值) 应该使用。默认值为true。如果旗子是 是的,那么无论 搜索获取过程中遇到的包装器 层次结构是显式或隐式包装器。如果旗子是 false,则不搜索显式包装器的父级。
如果要应用不带 重写显式包装器。
此外,参数可以作为关键字提供。
在大多数情况下,使用这些模块功能更方便 而不是直接获取属性和方法。
采集和方法
支持获取的对象的python方法可以使用 属性。当对以下对象调用python方法时 由获取包装器包装,包装器被传递给方法 作为第一个论点。此规则也适用于用户定义的方法 在类的纯混合中定义的类型和to c方法。
不幸的是,在扩展基类中定义的c方法 他们自己的数据结构,不能在这里使用获取的属性 时间。这是因为包装器对象不符合数据 这些方法所期望的结构。实际上,你很少 发现这个问题。
结论
获取提供了动态共享信息的强大方法 在物体之间。Zope使用Acquisition来获取一些密钥 特性包括安全性、对象发布和DTML变量 查找。收购也提供了一个优雅的解决方案 许多类问题的循环引用。收购时 是强大的,在使用 应用。细节可能会变得复杂,尤其是 语境习得与语境习得的区别 控制。