bool(container) [was bool(iter([])) changed between 2.3 and 2.4]
Python doesn't worry about a precise boolean object, it distinguishes between something and nothing. Is there anything left?" is a pretty good analogy for iterators. It isn't always cheaply available, and having might encourage poor style -- so iterators are going back to the default for non-containers of always True. How general strong is this default-to-true rule? If I submit a documentation patch, should I say that numbers, lists, strings, dictionaries, and tuples are a special case, or should I just warn that some container-like objects (including iterators) are always True? More specific question: A Queue.Queue is always true. Should I submit a bug patch or add it as a beware of custom classes example? def __nonzero__(self): return not self.empty()
On 9/30/05, Jim Jewett <jimjjewett@gmail.com> wrote:
If I submit a documentation patch, should I say that numbers, lists, strings, dictionaries, and tuples are a special case, or should I just warn that some container-like objects (including iterators) are always True?
You seem to be going at this from the wrong direction. Boolean value are defined by calling __nonzero__ or __len__, whichever exists; if neither exists the answer is true (except for None which is special-cased only for historical reasons -- there's no reason why it couldn't have a __nonzero__ method. __nonzero__ is intended for object types that either want to have number-like behavior or have a special reason for wanting to act like a Boolean. __len__ is for sequences and mappings specifically -- everything that supports __getitem__ should have __len__ and everything that has __len__ should have __getitem__. (This is what broke for iterators in 2.4.) So if anything's an "exception", it's numbers -- strings, lists, tuples are sequences and dicts are mappings, and that's where they get their definition of Booleanness from. Always remember, user-defined classes can define __nonzero__ any way they wish, and they get what they deserve. Library designers however should try to follow established patterns. Testing for Queue emptiness via __nonzero__ seems unwarranted since a Queue doesn't have any other sequence behavior. "Containerish" behavior isn't enough to warrant empty <--> false; in some sense every object is a container (at least every object with a __dict__ attribute) and you sure don't want to map __len__ to self.__dict__.__len__... -- --Guido van Rossum (home page: http://www.python.org/~guido/)
[Guido van Rossum]
__len__ is for sequences and mappings specifically -- everything that supports __getitem__ should have __len__ and everything that has __len__ should have __getitem__.
That's going a bit far. Unordered collections (like sets and bags) are a good counter-example. Raymond
On 9/30/05, Raymond Hettinger <raymond.hettinger@verizon.net> wrote:
[Guido van Rossum]
__len__ is for sequences and mappings specifically -- everything that supports __getitem__ should have __len__ and everything that has __len__ should have __getitem__.
That's going a bit far. Unordered collections (like sets and bags) are a good counter-example.
I've implemented many extension types in C, always to interface external libraries (the main examples, MPI and PETSc). In those libraries, some object are invalid (MPI_COMM_NULL) or can get deallocated in the C side. I always implement a __nonzero__ method for testing those situations. It sounds a bit bizarre to me to have to implement a number method for a object that is far from being a number, and of course __len__ do not make any sense. Perhaps Py3k could have a more explicit mechanism for definig the truth value of an object? Something like __bool__ method to be filled in type object? Any opinions? Lisandro DalcĂn
Guido van Rossum wrote:
"Containerish" behavior isn't enough to warrant empty <--> false; in some sense every object is a container (at least every object with a __dict__ attribute) and you sure don't want to map __len__ to self.__dict__.__len__...
the ElementTree experience shows that doing def __getitem__(self, index): return self.items[index] def __len__(self): return len(self.items) def __nonzero__(self): return True is sometimes a good idea, even for objects that are mostly sequences. (ET 1.2.X lacks the __nonzero__ method, and accidentally treating elements with no subelements as if the element itself doesn't exist is by far the most common gotcha in ET code). </F>
participants (5)
-
Fredrik Lundh -
Guido van Rossum -
Jim Jewett -
Lisandro Dalcin -
Raymond Hettinger