免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3516 | 回复: 0
打印 上一主题 下一主题

Python 3.1.1 中英文对照版语言参考手册 - 数据模型(下) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-29 17:15 |只看该作者 |倒序浏览
3.3.2. 对访问属性的定制(Customizing attribute access)

The following methods can be defined to customize the meaning of attribute
access (use of, assignment to, or deletion of x.name) for class instances.
以下方法可以用于定制访问类实例属性的含义(例如,赋值、或删除 x.name )
object.__getattr__(self, name)

Called when an attribute lookup has not found the attribute in the usual places
(i.e. it is not an instance attribute nor is it found in the class tree for
self).  name is the attribute name. This method should return the
(computed) attribute value or raise an
AttributeError
exception.
在正常方式访问属性无法成功时(就是说,属性既不是实例的属性,在其类树结构中找不到)使用。 name 是属性名。应该返回一个计算好的属性值,或抛出一个
AttributeError
异常。
Note that if the attribute is found through the normal mechanism,
__getattr__()
is not called.  (This is an intentional asymmetry between
__getattr__()
and
__setattr__()
.) This is done both for efficiency
reasons and because otherwise
__getattr__()
would have no way to access
other attributes of the instance.  Note that at least for instance variables,
you can fake total control by not inserting any values in the instance attribute
dictionary (but instead inserting them in another object).  See the
__getattribute__()
method below for a way to actually get total control
over attribute access.
注意如果属性可以通过正常方法访问,
__getattr__()
是不会被调用的(是有意将
__getattr__()

__setattr__()
设计成不对称的)。这样做的原因是基于效率的考虑,并且这样也不会让
__getattr__()
干涉正常属性。注意,至少对于类实例而言,不必非要更新实例字典伪装属性(但可以将它们插入到其它对象中)。需要全面控制属性访问,可以参考以下
__getattribute__()
的介绍。
object.__getattribute__(self, name)

Called unconditionally to implement attribute accesses for instances of the
class. If the class also defines
__getattr__()
, the latter will not be
called unless
__getattribute__()
either calls it explicitly or raises an
AttributeError
. This method should return the (computed) attribute value
or raise an
AttributeError
exception. In order to avoid infinite
recursion in this method, its implementation should always call the base class
method with the same name to access any attributes it needs, for example,
object.__getattribute__(self, name).
在访问类实例的属性时无条件调用这个方法。如果类也定义了方法
__getattr__()
,那么除非
__getattribute__()
显式地调用了它,或者抛出了
AttributeError
异常,否则它就不会被调用。这个方法应该返回一个计算好的属性值,或者抛出异常  
AttributeError
  。为了避免无穷递归,对于任何它需要访问的属性,这个方法应该调用基类的同名方法,例如, object.__getattribute__(self, name) 。
Note
This method may still be bypassed when looking up special methods as the
result of implicit invocation via language syntax or built-in functions.
See
搜索特殊方法(Special method lookup)
.
但是,在通过某些语法,或者内置函数时仍然可能导致在搜索特殊方法跳过这个方法,参见
搜索特殊方法(Special method lookup)

object.__setattr__(self, name, value)

Called when an attribute assignment is attempted.  This is called instead of
the normal mechanism (i.e. store the value in the instance dictionary).
name is the attribute name, value is the value to be assigned to it.
在属性要被赋值时调用。这会替代正常机制(即把值保存在实例字典中)。 name 是属性名, vaule 是要赋的值。
If
__setattr__()
wants to assign to an instance attribute, it should
call the base class method with the same name, for example,
object.__setattr__(self, name, value).
如果在
__setattr__()
里要一个实例属性赋值,它应该调用父类的同名方法,例如, object.__setattr__(self, name, value) 。
object.__delattr__(self, name)

Like
__setattr__()
but for attribute deletion instead of assignment.  This
should only be implemented if del obj.name is meaningful for the object.

__setattr__()
类似,但它的功能是删除属性。当 del obj.name 对对象有意义时,才需要实现它。
object.__dir__(self)

Called when
dir()
is called on the object.  A list must be returned.
在对象上调用
dir()
时调用,它需要返回一个列表。
3.3.2.1. 实现描述符(Implementing Descriptors)

The following methods only apply when an instance of the class containing the
method (a so-called descriptor class) appears in the class dictionary of
another class, known as the owner class.  In the examples below, “the
attribute” refers to the attribute whose name is the key of the property in the
owner class’ __dict__.
一个类(称为“描述子类”)的实例可能出现在其他类(称为“所有者类”)的字典中。以下方法只使用在描述符类中。在下面的例子里,“属性”专指在所有者类字典中的属性。 【译注:注意是出现所有类的字典中,不是所有类实例的字典。】
object.__get__(self, instance, owner)

Called to get the attribute of the owner class (class attribute access) or of an
instance of that class (instance attribute access). owner is always the owner
class, while instance is the instance that the attribute was accessed through,
or None when the attribute is accessed through the owner.  This method
should return the (computed) attribute value or raise an
AttributeError
exception.
在获取类属性或实例属性时调用这个方法。 owner 是所有者类, instance 用于访问的所有者类的实例,如果是通过 owner 访问的话,这个参数为 None 。这个方法应该返回一个计算好的属性值,或者抛出异常
AttributeError

object.__set__(self, instance, value)

Called to set the attribute on an instance instance of the owner class to a
new value, value.
在通过所有者类的一个实例 instance 设置属性时调用这个方法, value 代表新值。
object.__delete__(self, instance)

Called to delete the attribute on an instance instance of the owner class.
删除所有者类实例 instance 的属性时调用这个方法。
3.3.2.2. 调用描述符(Invoking Descriptors)

In general, a descriptor is an object attribute with “binding behavior”, one
whose attribute access has been overridden by methods in the descriptor
protocol:  
__get__()
,
__set__()
, and
__delete__()
. If any of
those methods are defined for an object, it is said to be a descriptor.
一般来说,描述符就是一个有“绑定行为”的对象属性,这种属性的访问操作会以描述符协议的方式替代,即方法
__get__()

__set__()

__delete__()
。如果一个对象定义了任何以上方法之一,就称它为“描述符”。
The default behavior for attribute access is to get, set, or delete the
attribute from an object’s dictionary. For instance, a.x has a lookup chain
starting with a.__dict__['x'], then type(a).__dict__['x'], and
continuing through the base classes of type(a) excluding metaclasses.
属性访问的默认行为是从对象字典中获取、设置、删除。例如, a.x 会在导致以下的搜索链:先 a.__dict__['x'] 后 type(a).__dict__['x'] ,之后再从 type(a) 的父类中搜索,但不搜索元类(metaclass)。
However, if the looked-up value is an object defining one of the descriptor
methods, then Python may override the default behavior and invoke the descriptor
method instead.  Where this occurs in the precedence chain depends on which
descriptor methods were defined and how they were called.
但是,如果搜索的是一个定义了描述符方法的对象,Python会放弃默认方案转而调用描述符方法。这个调用发生以上搜索上的那个位置取决于定义了什么描述符方法,及描述符是如何被调用的。
The starting point for descriptor invocation is a binding, a.x. How the
arguments are assembled depends on a:
描述符调用的起点是一个绑定, a.x ,方法参数的组织取决于 a :
Direct CallThe simplest and least common call is when user code directly invokes a
descriptor method:    x.__get__(a).
直接调用。这是最简单但也是最不常用的方法,用户直接调用一个描述符方法,例如 x.__get__(a) 。
Instance BindingIf binding to an object instance, a.x is transformed into the call:
type(a).__dict__['x'].__get__(a, type(a)).
实例绑定。如果与实例绑定, a.x 会转换为以下调用:  type(a).__dict__['x'].__get__(a, type(a)) 。
Class BindingIf binding to a class, A.x is transformed into the call:
A.__dict__['x'].__get__(None, A).
类绑定。如果与类绑定, A.x 会转换为以下调用: A.__dict__['x'].__get__(None, A) 。
Super BindingIf a is an instance of
super
, then the binding super(B,
obj).m() searches obj.__class__.__mro__ for the base class A
immediately preceding B and then invokes the descriptor with the call:
A.__dict__['m'].__get__(obj, A).
超级绑定。如果 a 是类
super
的一个实例,那么绑定 super(B, obj).m() 会在 obj.__class__.__mro__ 里直接搜索基类 A ,而不是 B ,并调用 A.__dict__['m'].__get__(obj, A) 。
For instance bindings, the precedence of descriptor invocation depends on the
which descriptor methods are defined.  Normally, data descriptors define both
__get__()
and
__set__()
, while non-data descriptors have just the
__get__()
method.  Data descriptors always override a redefinition in an
instance dictionary.  In contrast, non-data descriptors can be overridden by
instances.
[2]
对于实例绑定,描述符调用的优先顺序依赖于定义了什么描述符方法。正常情况下,数据描述符会定义两个方法
__get__()

__set__()
,而非数据描述符只会定义
__get__()
。数据描述符不会被实例的字典重写破坏,而非数据描述符可以因为重写实例字典而失效。[2]
Python methods (including
staticmethod()
and
classmethod()
) are
implemented as non-data descriptors.  Accordingly, instances can redefine and
override methods.  This allows individual instances to acquire behaviors that
differ from other instances of the same class.
Python方法(包括
staticmethod()

classmethod()
)是以非数据描述符实现。因此,实例可以重新定义或者说覆盖方法。这允许同一个类的不同实例可以有不同的行为。
The
property()
function is implemented as a data descriptor. Accordingly,
instances cannot override the behavior of a property.
函数
property()
是用数据描述符实现的,因此,实例不能覆写特性(property)的行为。
3.3.2.3. __slots__

By default, instances of classes have a dictionary for attribute storage.  This
wastes space for objects having very few instance variables.  The space
consumption can become acute when creating large numbers of instances.
默认情况下,类实例使用字典管理属性。在对象只有少量实例变量时这就会占用不少空间,当有大量实例时,空间消耗会变得更为严重。
The default can be overridden by defining __slots__ in a class definition.
The __slots__ declaration takes a sequence of instance variables and reserves
just enough space in each instance to hold a value for each variable.  Space is
saved because __dict__ is not created for each instance.
这个默认行为可以通过在类定义中定义 __slots__ 修改。 __slots__ 声明只为该类的所有实例预留刚刚够用的空间。因为不会为每个实例创建 __dict__ ,因此空间节省下来了。
object.__slots__

This class variable can be assigned a string, iterable, or sequence of
strings with variable names used by instances.  If defined in a
class, __slots__ reserves space for the declared variables and prevents the
automatic creation of __dict__ and __weakref__ for each instance.
这个类变量可以赋值为一个字符串,一个可迭代对象,或者一个字符串序列(每个字符串表示实例所用的变量名)。如果定义了 __slots__ ,Python就会为实例预留出存储声明变量的空间,并且不会为每个实例自动创建 __dict__ 和 __weakref__ 。
3.3.2.3.1. 使用 __slots__ 的注意事项(Notes on using __slots__ )

  • When inheriting from a class without __slots__, the __dict__ attribute of
    that class will always be accessible, so a __slots__ definition in the
    subclass is meaningless.
    如果从一个没有定义 __slots__ 的基类继承,子类一定存在 __dict__ 属性。所以,在这种子类中定义 __slots__ 是没有意义的。
  • Without a __dict__ variable, instances cannot be assigned new variables not
    listed in the __slots__ definition.  Attempts to assign to an unlisted
    variable name raises
    AttributeError
    . If dynamic assignment of new
    variables is desired, then add '__dict__' to the sequence of strings in
    the __slots__ declaration.
    没有定义 __dict__ 的实例不支持对不在 __slot__ 中的属性赋值。如果需要支持这个功能,可以把 '__dict__' 放到 __slots__ 声明中。
  • Without a __weakref__ variable for each instance, classes defining
    __slots__ do not support weak references to its instances. If weak reference
    support is needed, then add '__weakref__' to the sequence of strings in the
    __slots__ declaration.
    没有定义 __weakref__ 的,使用 __slot__ 的实例不支持对它的“弱引用”。如果需要支持弱引用,可以把 '__weakref__' 放到 __slots__ 声明中。
  • __slots__ are implemented at the class level by creating descriptors
    (
    实现描述符(Implementing Descriptors)
    ) for each variable name.  As a result, class attributes
    cannot be used to set default values for instance variables defined by
    __slots__; otherwise, the class attribute would overwrite the descriptor
    assignment.
    __slots__ 是在类这一级实现的,通过为每个实例创建描述符(
    实现描述符(Implementing Descriptors)
    )。因此,不能使用类属性为实例的 __slots__ 中定义的属性设置默认值 。否则,类属性会覆盖描述符的赋值操作。
  • If a class defines a slot also defined in a base class, the instance variable
    defined by the base class slot is inaccessible (except by retrieving its
    descriptor directly from the base class). This renders the meaning of the
    program undefined.  In the future, a check may be added to prevent this.
    如果类定义的slot与父类中的相同,那么父类slot中的变量将成为不可访问的(除非直接从基类中获取描述符)。这使得程序行为变得有一点模糊,以后可能会增加一个防止出现这种情况的检查。
  • The action of a __slots__ declaration is limited to the class where it is
    defined.  As a result, subclasses will have a __dict__ unless they also define
    __slots__.
    __slots__ 声明的行为只限于其定义所在的类。因此,子类仍然会使用 __dict__ (如果它没有定义自己的 __slots__ 的话)。
  • Nonempty __slots__ does not work for classes derived from “variable-length”
    built-in types such as
    int
    ,
    str
    and
    tuple
    .
    从”变长”内置类型,例如
    int

    str

    tuple
    继承的子类的能使用 __slots__ 只能为空。
  • Any non-string iterable may be assigned to __slots__. Mappings may also be
    used; however, in the future, special meaning may be assigned to the values
    corresponding to each key.
    任何非字符串可迭代对象都可以赋给 __slots__ 。映射类型也是允许的,但是,以后版本的Python可能给“键”赋予特殊意义。
  • __class__ assignment works only if both classes have the same __slots__.
    只有在两个类的 __slots__ 相同时, __class__ 赋值才会正常工作。

3.3.3. 类创建的定制Customizing class creation

By default, classes are constructed using
type()
. A class definition is
read into a separate namespace and the value of class name is bound to the
result of type(name, bases, dict).
默认情况下,类是由
type()
构造的。类的定义会读入一个独立的名字空间,并且类名称的值会与  type(name, bases, dict) 的返回结果绑定。
When the class definition is read, if a callable metaclass keyword argument
is passed after the bases in the class definition, the callable given will be
called instead of
type()
.  If other keyword arguments are passed, they
will also be passed to the metaclass.  This allows classes or functions to be
written which monitor or alter the class creation process:
在读取类定义时,如果在基类名之后给出了可调用类型的关键字参数 metaclass (元类),这时就不再调用
type()
转而使用这个可调用对象。如果有其它关键字参数,它们也会传递给 metaclass 。这就允许我们使用类或者函数来监视或修改类创建过程:
  • Modifying the class dictionary prior to the class being created.
    在类创建之前修改类的字典。
  • Returning an instance of another class – essentially performing the role of a
    factory function.
    返回其它类的实例 – 基本上这里执行的就是工厂方法。

These steps will have to be performed in the metaclass’s
__new__()
method
– type.__new__() can then be called from this method to create a class
with different properties.  This example adds a new element to the class
dictionary before creating the class:
以上步骤必须在元类的
__new__()
方法内完成 – 然后从这个方法中调用 type.__new__() 创建具有不同特性(properties)的新类。 下面的例子会在创建类之前在类字典中增加一个新元素
class metacls(type):
    def __new__(mcs, name, bases, dict):
        dict['foo'] = 'metacls was here'
        return type.__new__(mcs, name, bases, dict)
You can of course also override other class methods (or add new methods); for
example defining a custom
__call__()
method in the metaclass allows custom
behavior when the class is called, e.g. not always creating a new instance.
你当然也可以覆盖其它类方法(或是增加新方法),例如,在元类中定制
__call__()
方法就可以控制类在调用时的行为,例如,不会每次调用都返回一个实例。
If the metaclass has a __prepare__() attribute (usually implemented as a
class or static method), it is called before the class body is evaluated with
the name of the class and a tuple of its bases for arguments.  It should return
an object that supports the mapping interface that will be used to store the
namespace of the class.  The default is a plain dictionary.  This could be used,
for example, to keep track of the order that class attributes are declared in by
returning an ordered dictionary.
如果元类具有 __prepare__() 属性(一般是用类或者静态方法实现的),它会在处理类定义(结合类名和参数)之前调用。这个方法应该返回一个支持映射接口的对象,这个对象用于存储类的名字空间。默认是一个普通字典。例如,可以通过返回一个有序字典跟踪类属性的声明顺序。
The appropriate metaclass is determined by the following precedence rules:
使用的元类是按以下优先顺序确定的:
  • If the metaclass keyword argument is based with the bases, it is used.
    使用从基类的 metaclass 继承来的 metaclass 关键字参数,如果有的话。
  • Otherwise, if there is at least one base class, its metaclass is used.
    否则,如果至少只有一个基类,就用基类的元类。
  • Otherwise, the default metaclass (
    type
    ) is used.
    否则,使用默认的元类
    type


The potential uses for metaclasses are boundless. Some ideas that have been
explored including logging, interface checking, automatic delegation, automatic
property creation, proxies, frameworks, and automatic resource
locking/synchronization.
元类的用途非常广泛,目前已知的用法有记录日志、接口检查、自动委托、特性(property)自动创建、代理、框架、自动资源锁定及同步。
Here is an example of a metaclass that uses an
collections.OrderedDict
to remember the order that class members were defined:
这里是一个使用
collections.OrderedDict
的元类例子,它可以记住类成员的定义顺序
class OrderedClass(type):
     @classmethod
     def __prepare__(metacls, name, bases, **kwds):
        return collections.OrderedDict()
     def __new__(cls, name, bases, classdict):
        result = type.__new__(cls, name, bases, dict(classdict))
        result.members = tuple(classdict)
        return result
class A(metaclass=OrderedClass):
    def one(self): pass
    def two(self): pass
    def three(self): pass
    def four(self): pass
>>> A.members
('__module__', 'one', 'two', 'three', 'four')
When the class definition for A gets executed, the process begins with
calling the metaclass’s __prepare__() method which returns an empty
collections.OrderedDict
.  That mapping records the methods and
attributes of A as they are defined within the body of the class statement.
Once those definitions are executed, the ordered dictionary is fully populated
and the metaclass’s
__new__()
method gets invoked.  That method builds
the new type and it saves the ordered dictionary keys in an attribute
called members.
在类定义 A 执行时,进程开始于调用元类的 __prepare__() 方法并返回一个空
collections.OrderedDict
,这个映射会记录在 class 语句中定义的 A 的方法和属性。一旦执行完这个定义,有序的字典就已经设置好了,并会调用元类的
__new__()
方法,这个方法会创建新的类型,并把这个有序字典保存在属性 members 中。
3.3.4. 模拟可调用对象(Emulating callable objects)

object.__call__(self[, args...])

Called when the instance is “called” as a function; if this method is defined,
x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...).
当实例作为函数使用时调用本方法。如果定义了这个方法, x(arg1, arg2, ...) 就相当于 x.__call__(arg1, arg2, ...) 。
3.3.5. 模拟容器对象(Emulating container types)

The following methods can be defined to implement container objects.  Containers
usually are sequences (such as lists or tuples) or mappings (like dictionaries),
but can represent other containers as well.  The first set of methods is used
either to emulate a sequence or to emulate a mapping; the difference is that for
a sequence, the allowable keys should be the integers k for which 0  k
N where N is the length of the sequence, or slice objects, which define a
range of items.  It is also recommended that mappings provide the methods
keys(), values(), items(), get(), clear(),
setdefault(), pop(), popitem(), copy(), and
update() behaving similar to those for Python’s standard dictionary
objects.  The
collections
module provides a MutableMapping
abstract base class to help create those methods from a base set of
__getitem__()
,
__setitem__()
,
__delitem__()
, and keys().
Mutable sequences should provide methods append(), count(),
index(), extend(), insert(), pop(), remove(),
reverse() and sort(), like Python standard list objects.  Finally,
sequence types should implement addition (meaning concatenation) and
multiplication (meaning repetition) by defining the methods
__add__()
,
__radd__()
,
__iadd__()
,
__mul__()
,
__rmul__()
and
__imul__()
described below; they should not define other numerical
operators.  It is recommended that both mappings and sequences implement the
__contains__()
method to allow efficient use of the in operator; for
mappings, in should search the mapping’s keys; for sequences, it should
search through the values.  It is further recommended that both mappings and
sequences implement the
__iter__()
method to allow efficient iteration
through the container; for mappings,
__iter__()
should be the same as
keys(); for sequences, it should iterate through the values.
通过定义以下方法可以实现容器对象。容器通常指有序类型(如列表或元组)或映射类型(如字典),不过也可以表示其它容器。第一个方法集用于模拟有序类型或映射:有序类型的区别在于,键只能是整数 k ( 0  k  N , N 是有序类型的长度)或者是定义了处在一个范围内的项的片断对象。另外,也推荐模拟映射类型时实现方法 keys() 、 values() 、 items() 、 get() 、 clear() 、 setdefault() 、 pop() 、 popitem() 、 copy() 和 update() ,这使得模拟出来的行为与Python标准字典对象类似。模块
collections
提供了 MutableMapping 抽象基类可用于帮助从基本方法
__getitem__()

__setitem__()

__delitem__()
和 keys() 中创建这些方法。可变有序类型应该提供方法 append() 、 count() 、 index() 、  extend() 、 insert() 、 pop() 、 remove() 、 reverse() 和 sort() ,就像Python标准列表对象那样。最后,有序类型应该用下述的方法  
__add__()

__radd__()

__iadd__()

__mul__()

__rmul__()

__imul__()
实现“加”操作(即连接)和“乘”操作(即重复)。它们也可以实现其它算术运算符。推荐映射和有序类型实现
__contains__()
方法以实现 in 操作符的有效使用,对于映射类型, in 应该搜索映射的键,对于有序类型,它应该搜索值 。进一步的建议是映射和有序类型实现
__iter__()
方法,以支持在容器中有效地进行迭代。对于映射,
__iter__()
应该与 keys() 相同,对于有序类型,它应该在值里面迭代。
object.__len__(self)

Called to implement the built-in function
len()
.  Should return the length
of the object, an integer >= 0.  Also, an object that doesn’t define a
__bool__()
method and whose
__len__()
method returns zero is
considered to be false in a Boolean context.
实现内置函数
len()
相仿的功能。应该返回对象的长度,一个大于等于0的整数。另外,如果对象没有定义
__bool__()
方法,那么在布尔上下文中,
__len__()
返回的 0 将被看作是“假”。
Note
Slicing is done exclusively with the following three methods.  A call like :
片断独立于下面介绍的三个方法,类似于下面的调用:
a[1:2] = b
is translated to :
会转换为
a[slice(1, 2, None)] = b
and so forth.  Missing slice items are always filled in with None.
以此类推。缺少的片断项会被替代为 None 。
object.__getitem__(self, key)

Called to implement evaluation of self[key]. For sequence types, the
accepted keys should be integers and slice objects.  Note that the special
interpretation of negative indexes (if the class wishes to emulate a sequence
type) is up to the
__getitem__()
method. If key is of an inappropriate
type,
TypeError
may be raised; if of a value outside the set of indexes
for the sequence (after any special interpretation of negative values),
IndexError
should be raised. For mapping types, if key is missing (not
in the container),
KeyError
should be raised.
用于实现 self[key] 。对于有序类型,可接受的 key 应该有整数和片断对象。注意对负数索引(如果类希望模拟有序类型)的特殊解释也依赖于
__getitem__()
方法。如果 key 的类型不合适,可以抛出异常
TypeError
。如果 key 的值在有序类型的索引集合之外(在任何负值索引的特殊解释也行不通的情况下),可以抛出
IndexError
异常。对于映射类型,如果没有给出 key (或者不在容器之内),应该抛出异常
KeyError

Note
for
loops expect that an
IndexError
will be raised for illegal
indexes to allow proper detection of the end of the sequence.
for
循环根据由于无效索引导致的
IndexError
异常检测有序类型的结尾。
object.__setitem__(self, key, value)

Called to implement assignment to self[key].  Same note as for
__getitem__()
.  This should only be implemented for mappings if the
objects support changes to the values for keys, or if new keys can be added, or
for sequences if elements can be replaced.  The same exceptions should be raised
for improper key values as for the
__getitem__()
method.
在对 self[key] 赋值时调用。与
__getitem__()
有着相同的注意事项。如果映射类型对象要支持改变键的值或者增加新键,或者有序类型要支持可替换元素时,应该实现这个方法。在使用无效的 key 值时,会抛出与
__getitem__()
相同的异常。
object.__delitem__(self, key)

Called to implement deletion of self[key].  Same note as for
__getitem__()
.  This should only be implemented for mappings if the
objects support removal of keys, or for sequences if elements can be removed
from the sequence.  The same exceptions should be raised for improper key
values as for the
__getitem__()
method.
在删除 self[key] 时调用,与
__getitem__()
有相同的注意事项。如果映射对象要支持删除键,或者有序类型对象要支持元素的删除,就应该实现这个方法。在使用无效的 key 值时,会抛出与
__getitem__()
相同的异常。
object.__iter__(self)

This method is called when an iterator is required for a container. This method
should return a new iterator object that can iterate over all the objects in the
container.  For mappings, it should iterate over the keys of the container, and
should also be made available as the method keys().
在使用容器的迭代器时会调用这个方法。本方法应该返回一个可以遍历容器内所有对象的迭代器对象。对于映射类型,应该在容器的键上迭代,并且也应该定义 keys() 方法。
Iterator objects also need to implement this method; they are required to return
themselves.  For more information on iterator objects, see
Iterator Types
.
迭代器对象也需要实现这个方法,它们应该返回它自身。关于迭代器对象的更多信息,可以参考  
Iterator Types

object.__reversed__(self)

Called (if present) by the
reversed()
built-in to implement
reverse iteration.  It should return a new iterator object that iterates
over all the objects in the container in reverse order.
在使用内置函数
reversed()
实现反向迭代时调用这个方法。它应该返回一个以相反顺序在容器内迭代所有对象的新迭代器对象。
If the
__reversed__()
method is not provided, the
reversed()
built-in will fall back to using the sequence protocol (
__len__()
and
__getitem__()
).  Objects that support the sequence protocol should
only provide
__reversed__()
if they can provide an implementation
that is more efficient than the one provided by
reversed()
.
如果没有定义方法
__reversed__()
,内置函数
reversed()
会切换到备用方案:使用序列协议 (
__len__()
和  
__getitem__()
)。支持序列协议的对象只在有更高效的  
reversed()
实现方法时,才有必要实现  
__reversed__()

The membership test operators (
in
and
not in
) are normally
implemented as an iteration through a sequence.  However, container objects can
supply the following special method with a more efficient implementation, which
also does not require the object be a sequence.
成员测试运算符(
in

not in
)一般是在对有序类型进行迭代实现的。但是容器也可以实现方法提供更高效率的实现,并不要求对象一定是有序类型。
object.__contains__(self, item)

Called to implement membership test operators.  Should return true if item is
in self, false otherwise.  For mapping objects, this should consider the keys
of the mapping rather than the values or the key-item pairs.
在成员测试时调用这个方法。如果 item 在 self 之内应该返回真,否则返回假。对于映射类型的对象,测试应该是针对键的,而不是值,或者键值对。
3.3.6. 模拟数值类型(Emulating numeric types)

The following methods can be defined to emulate numeric objects. Methods
corresponding to operations that are not supported by the particular kind of
number implemented (e.g., bitwise operations for non-integral numbers) should be
left undefined.
以下方法用于模拟数值类型。不同数值类型所支持的操作符并不完全相同,如果一个类型不支持某些操作符(例如非整数值上的位运算),只需不定义对应的方法就行了。
object.__add__(self, other)

object.__sub__(self, other)

object.__mul__(self, other)

object.__truediv__(self, other)

object.__floordiv__(self, other)

object.__mod__(self, other)

object.__divmod__(self, other)

object.__pow__(self, other[, modulo])

object.__lshift__(self, other)

object.__rshift__(self, other)

object.__and__(self, other)

object.__xor__(self, other)

object.__or__(self, other)

These methods are called to implement the binary arithmetic operations (+,
-, *, /, //, %,
divmod()
,
pow()
, **, ,
>>, &, ^, |).  For instance, to evaluate the expression
x + y, where x is an instance of a class that has an
__add__()
method, x.__add__(y) is called.  The
__divmod__()
method should be the
equivalent to using
__floordiv__()
and
__mod__()
; it should not be
related to
__truediv__()
.  Note that
__pow__()
should be defined
to accept an optional third argument if the ternary version of the built-in
pow()
function is to be supported.
这些方法用于二元算术操作( + 、 - 、 * 、 / 、 // 、 % ,
divmod()

pow()
、 ** 、  、 >> 、 & 、 ^ 、 | )。例如,在计算表达式 x + y 时, x 是一个定义了
__add__()
的类的实例,那么就会调用  x.__add__(y) 。方法
__divmod__()
应该与使用
__floordiv__()

__mod__()
的结果相同,但应该与
__truediv__()
无关。注意如果要支持三参数版本的内置函数
pow()
的话,方法
__pow__()
应该被定义成可以接受第三个可选参数的。
If one of those methods does not support the operation with the supplied
arguments, it should return NotImplemented.
如果以上任何方法无法处理参数的类型,它就应该返回 NotImplemented 。
object.__radd__(self, other)

object.__rsub__(self, other)

object.__rmul__(self, other)

object.__rtruediv__(self, other)

object.__rfloordiv__(self, other)

object.__rmod__(self, other)

object.__rdivmod__(self, other)

object.__rpow__(self, other)

object.__rlshift__(self, other)

object.__rrshift__(self, other)

object.__rand__(self, other)

object.__rxor__(self, other)

object.__ror__(self, other)

These methods are called to implement the binary arithmetic operations (+,
-, *, /, //, %,
divmod()
,
pow()
, **,
, >>, &, ^, |) with reflected (swapped) operands.
These functions are only called if the left operand does not support the
corresponding operation and the operands are of different types.
[3]
  For
instance, to evaluate the expression x - y, where y is an instance of
a class that has an
__rsub__()
method, y.__rsub__(x) is called if
x.__sub__(y) returns NotImplemented.
这些方法用于实现二元算术操作(``+`` 、 - 、 * 、 / 、 // 、 % 、
divmod()

pow()
、 ** 、   、 >> 、 & 、 ^ 、 | ),但用于操作数反射(即参数顺序是相反的)。这些函数只有在左操作数不支持相应操作,并且是不同类型时才会被使用。[3] 例如,计算表达式 x - y , y 是一个定义了方法
__rsub__()
的类实例,那么在 x.__sub__(y) 返回 NotImplemented 时才会调用 y.__rsub__(x) 。
Note that ternary
pow()
will not try calling
__rpow__()
(the
coercion rules would become too complicated).
注意三参数版本的
pow()
不会试图调用
__rpow__()
。(这会导致类型自动转换规则过于复杂)
Note
If the right operand’s type is a subclass of the left operand’s type and that
subclass provides the reflected method for the operation, this method will be
called before the left operand’s non-reflected method.  This behavior allows
subclasses to override their ancestors’ operations.
注意:如果右操作数的类型是左操作数的一个子类,并且这个子类提供了操作数反射版本的方法。那么,子类的操作数反射方法将在左操作数的非反射方法之前调用。这个行为允许了子类可以覆盖祖先类的操作。
object.__iadd__(self, other)

object.__isub__(self, other)

object.__imul__(self, other)

object.__itruediv__(self, other)

object.__ifloordiv__(self, other)

object.__imod__(self, other)

object.__ipow__(self, other[, modulo])

object.__ilshift__(self, other)

object.__irshift__(self, other)

object.__iand__(self, other)

object.__ixor__(self, other)

object.__ior__(self, other)

These methods are called to implement the augmented arithmetic assignments
(+=, -=, *=, /=, //=, %=, **=, , >>=,
&=, ^=, |=).  These methods should attempt to do the operation
in-place (modifying self) and return the result (which could be, but does
not have to be, self).  If a specific method is not defined, the augmented
assignment falls back to the normal methods.  For instance, to execute the
statement x += y, where x is an instance of a class that has an
__iadd__()
method, x.__iadd__(y) is called.  If x is an instance
of a class that does not define a
__iadd__()
method, x.__add__(y)
and y.__radd__(x) are considered, as with the evaluation of x + y.
这些方法用于实现参数化算术赋值操作( += 、 -= 、 *= 、 /= 、 //= 、 %= 、 **= 、  、 >>= 、  &= 、 ^= 、 |=))。这些方法应该是就地操作的(即直接修改 self )并返回结果(一般来讲,这里应该是对 self 直接操作,但并不是一定要求如此)。如果没有实现某个对应方法的话,参数化赋值会蜕化为正常方法。例如,执行语句 x += y 时, x 是一个实现了
__iadd__()
方法的实例, x.__iadd__(y) 就会被调用。如果 x 没有定义
__iadd__()
,就会选择 x.__add__(y) 或者  y.__radd__(x) ,与 x + y 类似。
object.__neg__(self)

object.__pos__(self)

object.__abs__(self)

object.__invert__(self)

Called to implement the unary arithmetic operations (-, +,
abs()
and ~).
用于实现一元算术操作( - 、 + 、
abs()
和 ~ )。
object.__complex__(self)

object.__int__(self)

object.__float__(self)

object.__round__(self[, n])

Called to implement the built-in functions
complex()
,
int()
,
float()
and
round()
.  Should return a value
of the appropriate type.
用于实现内置函数
complex()

int()

float()

round()
。应该返回对应的类型值。
object.__index__(self)

Called to implement
operator.index()
.  Also called whenever Python needs
an integer object (such as in slicing, or in the built-in
bin()
,
hex()
and
oct()
functions). Must return an integer.
用于实现函数
operator.index()
,或者在Python需要一个整数对象时调用(例如在分片时(slicing),或者在内置函数函数
bin()
、  
hex()

oct()
中)。这个方法必须返回一个整数。
3.3.7. with语句的上下文管理器(With Statement Context Managers)

A context manager is an object that defines the runtime context to be
established when executing a
with
statement. The context manager
handles the entry into, and the exit from, the desired runtime context for the
execution of the block of code.  Context managers are normally invoked using the
with
statement (described in section
The with statement
), but can also be
used by directly invoking their methods.
上下文管理器( context manager )是一个对象,这个对象定义了执行
with
语句时要建立的运行时上下文。上下文管理器负责处理执行某代码块时对应的运行时上下文进入和退出。运行时上下文的使用一般通过
with
语句(参见
The with statement
),但也可以直接调用它的方法。
Typical uses of context managers include saving and restoring various kinds of
global state, locking and unlocking resources, closing opened files, etc.
上下文管理器的典型用途包括保存和恢复各种全局状态,锁定和解锁资源,关闭打开的文件等等。
For more information on context managers, see
Context Manager Types
.
关于上下文管理的更多信息,可以参考
Context Manager Types

object.__enter__(self)

Enter the runtime context related to this object. The
with
statement
will bind this method’s return value to the target(s) specified in the
as
clause of the statement, if any.
进入与这个对象关联的运行时上下文。
with
语句会把这个方法的返回值与
as
子句指定的目标绑定在一起(如果指定了的话)。
object.__exit__(self, exc_type, exc_value, traceback)

Exit the runtime context related to this object. The parameters describe the
exception that caused the context to be exited. If the context was exited
without an exception, all three arguments will be
None
.
退出与这个对象相关的运行时上下文。参数描述了引出上下文退出的异常,如果是无异常退出,则这三个参数都为
None

If an exception is supplied, and the method wishes to suppress the exception
(i.e., prevent it from being propagated), it should return a true value.
Otherwise, the exception will be processed normally upon exit from this method.
如果给出了一个异常,而这个方法决定要压制它(即防止它把传播出去),那么它应该返回真。否则,在退出这个方法时,这个异常会按正常方式处理。
Note that
__exit__()
methods should not reraise the passed-in exception;
this is the caller’s responsibility.
注意方法
__exit__()
不应该把传入的异常重新抛出,这是调用者的责任。
See also
PEP 0343
- The “with” statement (”with” 语句)The specification, background, and examples for the Python
with
statement.
Python
with
语句的规范、背景和例子。
3.3.8. 搜索特殊方法(Special method lookup)

For custom classes, implicit invocations of special methods are only guaranteed
to work correctly if defined on an object’s type, not in the object’s instance
dictionary.  That behaviour is the reason why the following code raises an
exception:
对于定制类,只有在对象类型的字典里定义好,才能保证成功调用特殊方法。这是以下代码发生异常的原因:
>>> class C(object):
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "", line 1, in
TypeError: object of type 'C' has no len()
The rationale behind this behaviour lies with a number of special methods such
as
__hash__()
and
__repr__()
that are implemented by all objects,
including type objects. If the implicit lookup of these methods used the
conventional lookup process, they would fail when invoked on the type object
itself:
这个行为的原因在于,有不少特殊方法在所有对象中都得到了实现,例如
__hash__()

__repr__()
。如果按照常规的搜索过程搜索这些方法,在涉及到类型对象时就会出错:
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
  File "", line 1, in
TypeError: descriptor '__hash__' of 'int' object needs an argument
Incorrectly attempting to invoke an unbound method of a class in this way is
sometimes referred to as ‘metaclass confusion’, and is avoided by bypassing
the instance when looking up special methods:
试图以这种错误方式调用一个类的未绑定方法有时叫作“元类含混”,可以通过在搜索特殊方法时跳过实例避免:
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
In addition to bypassing any instance attributes in the interest of
correctness, implicit special method lookup generally also bypasses the
__getattribute__()
method even of the object’s metaclass:
除了因为正确性的原因而跳过实例属外之外,特殊方法搜索也会跳过
__getattribute__()
方法,甚至是元类中的:
>>> class Meta(type):
...    def __getattribute__(*args):
...       print("Metaclass getattribute invoked")
...       return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
...     def __len__(self):
...         return 10
...     def __getattribute__(*args):
...         print("Class getattribute invoked")
...         return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__()                 # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c)          # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c)                      # Implicit lookup
10
Bypassing the
__getattribute__()
machinery in this fashion
provides significant scope for speed optimisations within the
interpreter, at the cost of some flexibility in the handling of
special methods (the special method must be set on the class
object itself in order to be consistently invoked by the interpreter).
这种跳过
__getattribute__()
的机制为解释器的时间性能优化提供了充分的余地,代价是牺牲了处理特殊方法时的部分灵活性(为了保持与解释器的一致,特殊方法必须在类对象中定义)。
Footnotes
[1]
It is possible in some cases to change an object’s type, under certain
controlled conditions. It generally isn’t a good idea though, since it can
lead to some very strange behaviour if it is handled incorrectly.
是在某些受控制的条件下,修改对象类型是有可能的。但一般这不是个好做法,因为一旦处理不周,就有可能导致一些非常奇怪的行为。
[2]
A descriptor can define any combination of
__get__()
,
__set__()
and
__delete__()
.  If it does not define
__get__()
,
then accessing the attribute even on an instance will return the descriptor
object itself.  If the descriptor defines
__set__()
and/or
__delete__()
, it is a data descriptor; if it defines neither, it is a
non-data descriptor.
一个描述符可以定义
__get__()

__set__()

__delete__()
的任意组合。如果它没有定义
__get__()
,那么访问该属性(甚至通过实例)就直接会返回该描述符本身。如果描述符定义了
__set__()
和(或)
__delete__()
,它就是一个数据描述符。如果两者都没有定义,它就是非数据描述符。
[3]
For operands of the same type, it is assumed that if the non-reflected method
(such as
__add__()
) fails the operation is not supported, which is why the
reflected method is not called.
对于相同类型的操作数,假定如果非反射方法失败就意味着并不支持这个运算符。这就是没有调用反射方法的原因。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/42957/showart_2106785.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP