文章来自《Python cookbook》. 翻译仅仅是为了个人学习,其它商业版权纠纷与此无关!
-- 61.182.251.99 [DateTime(2004-10-09T23:27:13Z)] TableOfContents
描述
Overriding a Built-In Method
覆盖内建方法
Credit: Dave Haynes
问题 Problem
You need to wrap (or, in Python 2.2, inherit from) a list or tuple, delegating several operations to it, and want to provide proper slicing (i.e., through the special method _ _getitem_ _).
需要包装(或者在python 2.2 中使用继承)list或tuple,代理它们的一些操作, 同时提供正确的slice切片分块行为(使用方法 getitem).
解决 Solution
In most cases, overriding special methods of built-in objects when you inherit from those objects (or wrap them with automatic delegation, which is not technically an override) poses no special challenge. When inheriting in Python 2.2, you can call the special method of the superclass with the usual unbound-method syntax. When wrapping, use the syntax that is specific to the operation, such as self.data[someindex] for indexing.
多数情形下, 运用继承或者封装代理操作(技术上这样不是覆盖)来覆盖内建对象的特定方法没有什么挑战。 在python 2.2中运用继承方法,可以调用基类的具有各种方法签名的特定方法。运用封装的方法,应该使用对应于操作的具有特定方法签名的函数,例如,索引操作应具有如下形式: self.data[someindex]。
Slicing is harder, because while slicing should go through the same special method _ _getitem_ _ as indexing (since Python 2.0), lists and tuples still implement an older approach: the more limited special method _ _getslice_ _ (and similarly for _ _setitem_ _ versus _ _setslice_ _ and _ _delitem_ _ versus _ _delslice_ _). So, you must provide a remedy, normally with a try/except:
实现切片分块困难些, 正常情况下切片分块应该使用与索引操作相同的方法getitem(python 2.0以后)。不过,由于 list和tuple仍然保留了slice的旧方法:受限制的特别的getslice方法(相对于setitem是setslice,相对于delitem是delslice ), 因此, 必须提供一个措施来解析方法调用,一般使用 try/except:
讨论 Discussion
When a user-defined class wraps (or, in Python 2.2, inherits from) a list or tuple, it often needs to define the _ _set*_ _ and _ _get*_ _ special methods and delegate part or all of their operation to the wrapped (or inherited) built-in object to provide the correct access to the data.
当封装(python2.2中,用继承)list或者tuple,生成自定义类型时, 一般需要定义特殊的set*和get*方法,代理一些(全部)此类操作到被封装的内置对象, 由被封装对象提供对底层数据的正确访问。
The documentation for Python 2.0 and later deprecates the use of _ _getslice_ _ and _ _setslice_ _. Instead, it suggests providing suitably extended versions of _ _getitem_ _ and _ _setitem_ _. This is a truly excellent idea because it enables the use of the extended-form slicing approaches (including step, ellipsis, and so on) that Numeric Python has made so deservedly popular among its regular users. Unfortunately, if you try to pass a slice object to the item-oriented special methods of a list or tuple object, you get a TypeError; the underlying C API still insists on receiving integer parameters, not slice objects in all their glory, whatever the documentation may say.
python 2.0和更高版本文档中,废除了函数getslice he setslice。建议提供getitem和setitem的功能扩展版本来代替。这个想法真不错,这样可以获得类似模块Numeric Python提供的功能。现在可以自己实现虔诚的Numeric Python用户使用的功能:扩展形式(包括步长、缺省值等)的分块操作。
Fortunately, working around this problem isn't as dramatic as all that. You just need to trap the TypeError you get from trying to index an old-fashioned sequence with a slice, and remedy it suitably. Here's the typical self-test code that you can append to the recipe's module and execute when it is run as a main script:
幸运的是,实现这个功能不是太复杂。实现仅需要使用旧版本形式的分块操作,获取TypeError异常,进行合适异常处理。
下面是自测试代码
In the recipe's SliceTester example class, the remedy is pretty minimal; it's just an attempt to use start and stop attributes of the noninteger index (presumably an instance of the slice built-in type). You may want to do a lot more (implement step, ellipsis, and so on).
食谱中类SliceTester的异常处理很简单;仅仅使用了非整数的索引(假设是内置的slice类型)的start和stop属性。可以做更多处理(包括步长、缺省值等)。
Note that this recipe doesn't cover all of the cases in which slices can be used. There is a third argument to the slice operator that defines the step, or stride, of the slicing. For example, if data is a Numeric Python array (the only widely used software that supports slicing in all its glory), data[0:101:10] returns the sequence data[0], data[10], data[20]梪p to data[100]. Similarly, data[::-1] returns a sequence containing the contents of data reversed. The third argument to the slice operator is stored in the step attribute of slice objects and is set to None if a step isn't specified (as in list[start:end]). Given this, it shouldn't be a surprise that the recipe shown earlier will not magically add support for steps to objects that don't support new-style slices.
食谱并未覆盖分块操作可能应用的所有场景。 分块索引运算可以有第三个参数:定义步长(步幅)。比如,在Numeric Python
The point of this recipe is that you must be aware of these limitations and take precautionary measures. Also, don't type-test for an index of type slice. If normal indexing refuses the index, you are better off catching the TypeError in an except clause and entering another try/except in which you try to use the index as the slice you now expect it to be. This lets client code pass you objects that are polymorphic to slice objects.
参考 See Also
The section of the Language Reference on slicing; the description of the slice built-in function in the Library Reference.