获取是一种允许对象从其所在的包含层次结构获取属性的机制。

Acquisition的Python项目详细描述


环境收购

这个包实现了python的"环境获取",如 在joseph gil和david h.lorenz的论文中提出 < Buff行情> 我们提出了一个新的编程范式,环境获取 对象聚合的上下文,其中对象获取 运行时当前容器的行为。关键是 部件的性能可能取决于其外壳 复合材料。特别是,我们在 对象从中的对象类"继承"功能 它的环境。通过检查类的声明,它是 可以确定哪些类可能包含 组件,哪些组件必须包含在给定类型的 混合成的。这些关系是语言结构的基础 支持收购。

内容

  • 更改日志
  • 介绍性示例

    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!
    

    最后一行的过滤采集跳过第一行 它找到的属性名为 p ,因为该属性没有 满足过滤器中给出的条件。

    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>
    aq_acquire(object,name[,filter,extra,explicit,default,containment])

    获取具有给定名称的对象。

    此函数可用于在使用显式 获取和获取通常不会是 已获取。

    函数接受许多可选参数:

    < DL>
    过滤器

    用于确定对象是否 应该获得。

    使用五个参数调用筛选器:

    • 调用aq_acquire方法的对象,
    • 找到对象的对象,
    • 传递给aq_acquire的对象的名称,
    • 找到该对象,并且
    • 传递给aq_acquire的额外参数。

    如果过滤器返回一个真正的对象,则找到的对象是 返回,否则继续进行采集搜索。

    额外的
    要作为最后一个参数传递给筛选器的额外数据。
    显式

    指示是否显式获取的标志(布尔值) 应该使用。默认值为true。如果旗子是 是的,那么无论 搜索获取过程中遇到的包装器 层次结构是显式或隐式包装器。如果旗子是 false,则不搜索显式包装器的父级。

    如果要应用不带 重写显式包装器。

    默认值
    如果无法获取值,则返回默认值。
    安全壳
    指示搜索是否应限于 包含层次结构。

    此外,参数可以作为关键字提供。

    基地(目标)
    返回已移除所有包装的对象。
    aq_链(对象[,包含])
    返回包含对象及其获取的列表 父母。可选参数containment控制 使用包含或访问层次结构。
    aq-get(对象,名称[,默认值,包含])
    获取属性、名称。可以提供默认值,如 可以是将搜索限制为包含层次结构的标志。
    aq_内部(对象)
    返回除最内层包装外的所有对象 已删除。
    aq_父(对象)
    返回对象的获取父对象,如果对象 打开包装。
    aq_self(对象)
    返回移除一层包装的对象,除非 对象是展开的,在这种情况下返回对象。

    在大多数情况下,使用这些模块功能更方便 而不是直接获取属性和方法。

    采集和方法

    支持获取的对象的python方法可以使用 属性。当对以下对象调用python方法时 由获取包装器包装,包装器被传递给方法 作为第一个论点。此规则也适用于用户定义的方法 在类的纯混合中定义的类型和to c方法。

    不幸的是,在扩展基类中定义的c方法 他们自己的数据结构,不能在这里使用获取的属性 时间。这是因为包装器对象不符合数据 这些方法所期望的结构。实际上,你很少 发现这个问题。

    结论

    获取提供了动态共享信息的强大方法 在物体之间。Zope使用Acquisition来获取一些密钥 特性包括安全性、对象发布和DTML变量 查找。收购也提供了一个优雅的解决方案 许多类问题的循环引用。收购时 是强大的,在使用 应用。细节可能会变得复杂,尤其是 语境习得与语境习得的区别 控制。

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

    推荐PyPI第三方库


    热门话题
    java在未知属性上的PUT和POST失败会引发不同的行为   java无法使GWTRPC正常工作   java如何在安卓中更改一个特定视图的主题?   机器学习为什么改变了java中等式的两面?   java继承和重定向标准输出   java为什么Clojure中嵌套循环/重复速度慢?   使用JavaParser解析Java代码并查找父节点的语句类型   java读取类的方法并在arraylist中存储Web服务的路径名   java模板聚合匹配和投影一个没有id的字段   java为什么给定数组不返回false   java如何链接JLabel和JSpinner以调整大小   在java中,当过滤器只返回一个对象时,如何使用流和过滤器将值填充到对象中   java为什么使用getInstance   如何得到我的。运行java命令的bat文件