17xie > Python 语言参考手册 > 3.3.6 模拟有序类型的其它方法
背景:                 
[本书目录] [图书首页] [本书讨论区]  
链接地址:http://www.17xie.com/read-37429.html    注册17xie 一起来写书 实现您的出书梦想!


3.3.6 模拟有序类型的其它方法 Additional methods for emulation of sequence types

The following optional methods can be defined to further emulate sequence objects. Immutable sequences methods should at most only define __getslice__(); mutable sequences might define all three methods.

定义以下方法可以进一步模拟有序类型对象; 不可变的有序类型应该只定义方法__getslice__(); 可变类型应该以下所有的方法.

__getslice__( self, i, j)
Deprecated since release 2.0. Support slice objects as parameters to the __getitem__() method.

从2.0版本开始, 这个函数不再推荐使用. 现在可以使用方法__getitem__()来实现它的功能.

Called to implement evaluation of self[i:j]. The returned object should be of the same type as self. Note that missing i or j in the slice expression are replaced by zero or sys.maxint, respectively. If negative indexes are used in the slice, the length of the sequence is added to that index. If the instance does not implement the __len__() method, an AttributeError is raised. No guarantee is made that indexes adjusted this way are not still negative. Indexes which are greater than the length of the sequence are not modified. If no __getslice__() is found, a slice object is created instead, and passed to __getitem__() instead.

在对self[i:j]求值时调用本方法. 返回的对象应该与self的类型相同. 注意如果片断中缺少i或j, 它们就是分别替换成0或sys.maxint. 如果在片断中使用了负数, 运算时就是它加上有序类型对象的长度. 如果实例未实现__len__(), 则抛出AttributeError异常. 不能保证这样调整后的索引就是正数. 对于大于有序类型对象长度的索引是不做修改的. 如果没有找到__getslice__(), 就创建一个片断对象, 然后传递给__getitem__().

__setslice__( self, i, j, sequence)
Called to implement assignment to self[i:j]. Same notes for i and j as for __getslice__().

在对self[i:j]赋值时调用, 在__getslice__()中对于i和j的注意也适用于本方法.

This method is deprecated. If no __setslice__() is found, or for extended slicing of the form self[i:j:k], a slice object is created, and passed to __setitem__(), instead of __setslice__() being called.

本方法已经过时了. 如果没有找到__setslice__(), 就创建一个片断对象, 然后传递给__setitem__().

__delslice__( self, i, j)
Called to implement deletion of self[i:j]. Same notes for i and j as for __getslice__(). This method is deprecated. If no __delslice__() is found, or for extended slicing of the form self[i:j:k], a slice object is created, and passed to __delitem__(), instead of __delslice__() being called.

在删除self[i:j]时调用本方法.在__getslice__()中对i和j的注意也适用于本方法.本方法已经过时了. 如果没有找到__delslice__(), 就创建一个片断对象, 然后传递给__delitem__().

Notice that these methods are only invoked when a single slice with a single colon is used, and the slice method is available. For slice operations involving extended slice notation, or in absence of the slice methods, __getitem__(), __setitem__() or __delitem__() is called with a slice object as argument.

注意这些方法只在使用单冒号的片断语法时调用.对于扩展的片断记法或者缺少这些片断方法的情况下, 就调用__getitem__(), __setitem__() 或 __delitem__() , 以一个片断对象为参数,

The following example demonstrate how to make your program or module compatible with earlier versions of Python (assuming that methods __getitem__(), __setitem__() and __delitem__() support slice objects as arguments):

以下程序对如何你的程序兼容以前版本的Python做了一个示范(假定__getitem__(), __setitem__() 和 __delitem__()支持以片断对参数.)

class MyClass:
    ...
    def __getitem__(self, index):
        ...
    def __setitem__(self, index, value):
        ...
    def __delitem__(self, index):
        ...

    if sys.version_info < (2, 0):
        # They won't be defined if version is at least 2.0 final

        def __getslice__(self, i, j):
            return self[max(0, i):max(0, j):]
        def __setslice__(self, i, j, seq):
            self[max(0, i):max(0, j):] = seq
        def __delslice__(self, i, j):
            del self[max(0, i):max(0, j):]
    ...

Note the calls to max(); these are necessary because of the handling of negative indices before the __*slice__() methods are called. When negative indexes are used, the __*item__() methods receive them as provided, but the __*slice__() methods get a ``cooked'' form of the index values. For each negative index value, the length of the sequence is added to the index before calling the method (which may still result in a negative index); this is the customary handling of negative indexes by the built-in sequence types, and the __*item__() methods are expected to do this as well. However, since they should already be doing that, negative indexes cannot be passed in; they must be constrained to the bounds of the sequence before being passed to the __*item__() methods. Calling max(0, i) conveniently returns the proper value.

注意调用max()的代码; 它是必要的, 因为在调用__*slice__()之前要对负数片断进行控制.在使用负数索引后,方法__*item__()会获得和在提供该参数时的形式相同的数据. 但__*slice__()方法会得到一个包装过的索引值参数.对于每个负数索引值, 在调用这个方法前会加上该有序类型的长度(结果仍然可能是负数). 这个特征可以用来对内建有序类型的负数索引进行定制处理, 并且__*item__()系列方法是可以用于完成这个工作.但是由于负数索引应该已经被处理过了, 因此负数索引是不可能传进来的; 它们应该在传递进__*item__()方法之前就被限制在有该有序类型的长度范围之内, 通常用调用max(0,i)返回适当的值.



3.3.7 模拟数值类型 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.

以下方法用于模拟数值类型.其中,对于有些种类数值所不支持的操作对应的方法未定义(如, 对非整数值的位运算).

__add__( self, other)
__sub__( self, other)
__mul__( self, other)
__floordiv__( self, other)
__mod__( self, other)
__divmod__( self, other)
__pow__( self, other[, modulo])
__lshift__( self, other)
__rshift__( self, other)
__and__( self, other)
__xor__( self, other)
__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__() (described below). 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.

这些方法用于实现二元算术运算(+,-,*,/,

__div__( self, other)
__truediv__( self, other)
The division operator (/) is implemented by these methods. The __truediv__() method is used when __future__.division is in effect, otherwise __div__() is used. If only one of these two methods is defined, the object will not support division in the alternate context; TypeError will be raised instead.

这些方法用于支持除法运算符. __truediv__()方法在__future__.division有效时使用,否则就使用__div__(), 如果只定义了其中一个方法, 那么这个对象在哪种情况下都是不支持除法运算的,此时会有一个TypeError异常抛出.

__radd__( self, other)
__rsub__( self, other)
__rmul__( self, other)
__rdiv__( self, other)
__rtruediv__( self, other)
__rfloordiv__( self, other)
__rmod__( self, other)
__rdivmod__( self, other)
__rpow__( self, other)
__rlshift__( self, other)
__rrshift__( self, other)
__rand__( self, other)
__rxor__( self, other)
__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. 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. Note that ternary pow() will not try calling __rpow__() (the coercion rules would become too complicated).

这些方法用于实现二元算术运算(+,-,*,/,

__iadd__( self, other)
__isub__( self, other)
__imul__( self, other)
__idiv__( self, other)
__itruediv__( self, other)
__ifloordiv__( self, other)
__imod__( self, other)
__ipow__( self, other[, modulo])
__ilshift__( self, other)
__irshift__( self, other)
__iand__( self, other)
__ixor__( self, other)
__ior__( self, other)
These methods are called to implement the augmented arithmetic operations (+=, -=, *=, /=, %=, **=, <<=, >>=, &=, ^=, |=). 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 operation falls back to the normal methods. For instance, to evaluate the expression 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.

这些方法用于实现赋值运算符(+=, -=,*=,/=,

__neg__( self)
__pos__( self)
__abs__( self)
__invert__( self)
Called to implement the unary arithmetic operations (-, +, abs() and ~).

实现一元运算符(-,+,abs(), )

__complex__( self)
__int__( self)
__long__( self)
__float__( self)
Called to implement the built-in functions complex(), int(), long(), and float(). Should return a value of the appropriate type.

在自定义类上实现内建函数complex(), int(), long()和float()的功能, 应该返回适当的类型.

__oct__( self)
__hex__( self)
Called to implement the built-in functions oct() and hex(). Should return a string value.

在自定义类上实现内建函数oct()和hex()的功能, 应该返回适当的串值.

__coerce__( self, other)
Called to implement ``mixed-mode'' numeric arithmetic. Should either return a 2-tuple containing self and other converted to a common numeric type, or None if conversion is impossible. When the common type would be the type of other, it is sufficient to return None, since the interpreter will also ask the other object to attempt a coercion (but sometimes, if the implementation of the other type cannot be changed, it is useful to do the conversion to the other type here). A return value of NotImplemented is equivalent to returning None.

实现混合式数值运算, 返回值要么是一个包括已经转换到一般数值类型的数据的self和other的二元组,或者当转换无效时返回None. 当转换后的类型可能是其它类型时, 可以返回None, 因为解释器会试着强制地转换为其它类型(但有的情况下,如果其它的类型的实现不能改变, 那么就应该在这将其转换为该类型).



3.3.8 强制规则: Coercion rules

This section used to document the rules for coercion. As the language has evolved, the coercion rules have become hard to document precisely; documenting what one version of one particular implementation does is undesirable. Instead, here are some informal guidelines regarding coercion. In Python 3.0, coercion will not be supported.

  • If the left operand of a % operator is a string or Unicode object, no coercion takes place and the string formatting operation is invoked instead.

  • It is no longer recommended to define a coercion operation. Mixed-mode operations on types that don't define coercion pass the original arguments to the operation.

  • New-style classes (those derived from object) never invoke the __coerce__() method in response to a binary operator; the only time __coerce__() is invoked is when the built-in function coerce() is called.

  • For most intents and purposes, an operator that returns NotImplemented is treated the same as one that is not implemented at all.

  • Below, __op__() and __rop__() are used to signify the generic method names corresponding to an operator; __iop__ is used for the corresponding in-place operator. For example, for the operator `+', __add__() and __radd__() are used for the left and right variant of the binary operator, and __iadd__ for the in-place variant.

  • For objects x and y, first x.__op__(y) is tried. If this is not implemented or returns NotImplemented, y.__rop__(x) is tried. If this is also not implemented or returns NotImplemented, a TypeError exception is raised. But see the following exception:

  • Exception to the previous item: if the left operand is an instance of a built-in type or a new-style class, and the right operand is an instance of a proper subclass of that type or class, the right operand's __rop__() method is tried before the left operand's __op__() method. This is done so that a subclass can completely override binary operators. Otherwise, the left operand's __op__ method would always accept the right operand: when an instance of a given class is expected, an instance of a subclass of that class is always acceptable.

  • When either operand type defines a coercion, this coercion is called before that type's __op__() or __rop__() method is called, but no sooner. If the coercion returns an object of a different type for the operand whose coercion is invoked, part of the process is redone using the new object.

  • When an in-place operator (like `+=') is used, if the left operand implements __iop__(), it is invoked without any coercion. When the operation falls back to __op__() and/or __rop__(), the normal coercion rules apply.

  • In x+y, if x is a sequence that implements sequence concatenation, sequence concatenation is invoked.

  • In x*y, if one operator is a sequence that implements sequence repetition, and the other is an integer (int or long), sequence repetition is invoked.

  • Rich comparisons (implemented by methods __eq__() and so on) never use coercion. Three-way comparison (implemented by __cmp__()) does use coercion under the same conditions as other binary operations use it.

  • In the current implementation, the built-in numeric types int, long and float do not use coercion; the type complex however does use it. The difference can become apparent when subclassing these types. Over time, the type complex may be fixed to avoid coercion. All these types implement a __coerce__() method, for use by the built-in coerce() function.

0. 如果x是串对象,并且op是取模运算符(

1. 如果x是一个类实例:

1a. 如果x有__coerce__()方法:就用x.__coerce__(y)返回的二元组的值替换x和y. 如果它返回None则跳过步骤2.

1b. 如果x或y在强制转换后都不是类实例了, 转到步骤3.

1c. 如果x有方法__op__(), 返回x.__op__(y);否则恢复步骤1a之前的x和y的值.

2.

2a. 如果y有__coerce__()方法:就用y.__coerce__(x)返回的二元组的值替换y和x. 如果它返回None则跳过步骤2.

2b. 如果x或y在强制转换后都不是类实例了, 转到步骤3.

2b. 如果y有方法__rop__(), 返回y.__rop__(x);否则恢复步骤2a之前的x和y的值.

3. 仅仅在x和y都不是类实例时, 才会执行到这一步.

3a. 如果op为+并且x是一个有序类型, 那么就执行有序类型的连接操作.

3b. 如果op为*并且一个操作数为有序类型, 另一个是整数, 就执行有序类型重复操作.

3c. 否则, 两个操作数必须是数值型的; 它们尽可能地强制转换成通用类型, 并且为该类型调用数值运算符.


字数:14074    最后更新:8个月以前 [03-15 20:42]月落晨星 修改
本页编辑者:月落晨星  
[前一页]:3.3.3 Customizing cl…  [后一页]:4.1 !!! 代码块, 运行…
[在本页中加入书签] [收藏本书] [推荐本书]
  17xie论坛 > 本书讨论区 > 本页评论   (共0条)
发表评论

用户名称 匿名发表
评论内容
验证码

关于我们 | 版权声明 | 免责声明 | 诚聘英才 | 联系我们 | 合作伙伴 | 友情链接 | 广告合作 | 提交意见
Copyright © 2007 17xie.com 互联网协同写书平台 京ICP备08002671号