Re: [docs] [Tutor] special attributes naming confusion
I'm not sure where this comment belongs, but I want to share my perspective on the documentation of these special method names. In the following section there is an inconsistency which could be confusing to someone just learning Python (e.g., me). In the sentence on implementing custom mapping objects, the recommended method names are listed as the short calling names: eys(), values(), items(), etc. But, in contrast, in the sentence on implementing sequence types, the recommended method names are listed as the double underscore internal implementation names: __add__(), __radd__(), __iadd__(), __mul__(), etc. Here's the section of the documentation with this inconsistency. I think it would help to use one or the other of these pairs (calling name vs. internal implementation name) consistently in this section. 3.4.6. Emulating container types¶<http://docs.python.org/reference/datamodel.html#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. (For backwards compatibility, the method __getslice__()<http://docs.python.org/reference/datamodel.html#object.__getslice__>(see below) can also be defined to handle simple, but not extended slices.) It is also recommended that mappings provide the methods keys(), values(), items(), has_key(), get(), clear(), setdefault(), iterkeys(), itervalues(), iteritems(), pop(), popitem(), copy()<http://docs.python.org/library/copy.html#module-copy>, and update() behaving similar to those for Python’s standard dictionary objects. The UserDict<http://docs.python.org/library/userdict.html#module-UserDict>module provides a DictMixin class to help create those methods from a base set of __getitem__()<http://docs.python.org/reference/datamodel.html#object.__getitem__>, __setitem__()<http://docs.python.org/reference/datamodel.html#object.__setitem__>, __delitem__()<http://docs.python.org/reference/datamodel.html#object.__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__()<http://docs.python.org/reference/datamodel.html#object.__add__>, __radd__() <http://docs.python.org/reference/datamodel.html#object.__radd__>, __iadd__() <http://docs.python.org/reference/datamodel.html#object.__iadd__>, __mul__() <http://docs.python.org/reference/datamodel.html#object.__mul__>, __rmul__() <http://docs.python.org/reference/datamodel.html#object.__rmul__>and __imul__() <http://docs.python.org/reference/datamodel.html#object.__imul__>described below; they should not define __coerce__()<http://docs.python.org/reference/datamodel.html#object.__coerce__>or other numerical operators. It is recommended that both mappings and sequences implement the __contains__()<http://docs.python.org/reference/datamodel.html#object.__contains__>method to allow efficient use of the in operator; for mappings, in should be equivalent of has_key(); for sequences, it should search through the values. It is further recommended that both mappings and sequences implement the __iter__()<http://docs.python.org/reference/datamodel.html#object.__iter__>method to allow efficient iteration through the container; for mappings, __iter__() <http://docs.python.org/reference/datamodel.html#object.__iter__>should be the same as iterkeys(); for sequences, it should iterate through the values. This is in addition to some missing documentation regarding mention how some of the special method names should be conveniently called in code. (See below.) On Wed, Jun 6, 2012 at 3:59 PM, Dave <davestechshop@gmail.com> wrote:
On Wed, Jun 6, 2012 at 3:40 PM, Mark Lawrence <breamoreboy@yahoo.co.uk>wrote:
On 06/06/2012 20:19, Dave wrote:
I was reading some tutorial material on creating iterators. It shows the following example implementation of an iterator:
class Reverse: """Iterator for looping over a sequence backwards.""" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def next(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index]
My question is how was I supposed to kinow that the function I call using the name iter() is implemented using the name __iter__()?
Is there a rule that describes when I would implement an attribute name with leading and trailing double underscores, and then call it without those underscores? How many names like this exist in Python? Are these special cases or is there a general rule that leading and trailing double underscores get dropped when calling functions that were implemented with these names? I'm trying to understand the big picture as far as how Python works when it comes to this situation. Thanks.
Try this to start with http://docs.python.org/**reference/datamodel.html# **special-method-names<http://docs.python.org/reference/datamodel.html#special-method-names>. Note this is for Python 2.7.3, there may be differences in Python 3.x.
--
Actually, I think I'm getting it now... as I read more of this page I see that there is no single generalization. These are indeed all special cases.
But the documentation does appear to be incomplete. It leaves out the mapping to the name or symbol that should be used to call the special function in some cases. In particular, in the case of __iter(self), which is one of the first ones I looked at, it doesn't mention that this is usually called via iter(). It does mention how it would be called for mapping containers, however (i.e., iterkeys()). 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 iterkeys().
But as I read more, I see that much of the documentation does mention how these special method names are called. For example:
object.__lt__(*self*, *other*) object.__le__(*self*, *other*)¶<http://docs.python.org/reference/datamodel.html#object.__le__> object.__eq__(*self*, *other*) object.__ne__(*self*, *other*) object. __gt__(*self*, *other*) object.__ge__(*self*, *other*)
New in version 2.1.
These are the so-called “rich comparison” methods, and are called for comparison operators in preference to __cmp__()<http://docs.python.org/reference/datamodel.html#object.__cmp__>below. The correspondence between operator symbols and method names is as follows: x<y calls x.__lt__(y), x<=y calls x.__le__(y), x==y calls x.__eq__(y), x!=y and x<>y call x.__ne__(y), x>y calls x.__gt__(y), and x>=y calls x.__ge__(y). I think there is enough info at this page to answer my question as well as I need it answered right now. Thanks.
On Wed, Jun 6, 2012 at 4:32 PM, Dave <davestechshop@gmail.com> wrote:
I'm not sure where this comment belongs, but I want to share my perspective on the documentation of these special method names. In the following section there is an inconsistency which could be confusing to someone just learning Python (e.g., me).
In the sentence on implementing custom mapping objects, the recommended method names are listed as the short calling names: eys(), values(), items(), etc.
But, in contrast, in the sentence on implementing sequence types, the recommended method names are listed as the double underscore internal implementation names: __add__(), __radd__(), __iadd__(), __mul__(), etc.
Here's the section of the documentation with this inconsistency. I think it would help to use one or the other of these pairs (calling name vs. internal implementation name) consistently in this section.
Those aren't pairs, where you can implement either one. You have to implement ALL of those methods to correctly emulate one of the built in container classes. The difference is that the "normal" method names (the ones without double underscores) are meant to be called directly on an instance of your class. The double underscored names are called by the internals of python, often in a variety of different places. For instance, the __iter__() method is called by the iter() built-in. It can also called by any other piece of code that needs to acquire an iterator from a generic container object. There is no list of all such pieces of code that could ever call the __iter__() method of your object. Jerry
participants (2)
-
Dave
-
Jerry Hill