Expression can be simplified on list

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Sep 29 04:14:32 EDT 2016


On Thursday 29 September 2016 16:47, Rustom Mody wrote:

> On Thursday, September 15, 2016 at 1:43:05 AM UTC+5:30, Terry Reedy wrote:
[...]
>> Python make no such nonsense claim.  By default, Python objects are truthy.
>> 
>>  >>> bool(object())
>> True
>> 
>> Because True is the default, object need not and at least in CPython
>> does not have a __bool__ (or __len__) method.  Classes with no falsey
>> objects, such as functions, generators, and codes, need not do anything
>> either.  In the absence of an override function, the internal bool code
>> returns True.
>> 
> Not sure what you are trying to say Terry...
> Your English suggests you disagree with me
> Your example is exactly what I am saying; if a type has a behavior in which
> all values are always True (true-ish) its a rather strange kind of
> bool-nature.

In what way do you think it is "rather strange"?

This suggests that you believe that all types must have distinct truthy values 
and falsey values, or else that type's values shouldn't be usable in a truth 
context at all. Is that what you mean?

My view is somewhat different. I see truthiness as an abstraction. Like all 
abstractions, it may leak -- I make no apologies for the fact that Python 
doesn't have syntactic support for Keene three-value logic or other multi-
valued logics, nor do I make any apologies for the (hypothetical, rare) object 
which doesn't fit well into this truthy abstraction. All abstractions leak 
somewhere, and this abstraction is proven to work well in practice, not 
withstanding the rare glitch.

What is this truthiness abstraction? It is the difference between "something" 
and "nothing".

Values which represent nothing, e.g.:

- None
- numeric zero: 0, 0.0, 0j, Decimal(0) etc
- empty strings u'', ''
- empty containers [], (), {} etc.

are treated as falsey. And values that represent something, e.g.:

- numbers other than zero
- strings other than the empty string
- non-empty containers

are treated as truthy. On this basis, by default objects should be considered 
truthy: objects represent something rather than nothing:

- a module object is something;
- a function object is something;
- a HTTPServer object is something;

and so all of these things -- modules, functions, HTTPServers -- should default 
to always truthy unless the programmer specifically programs them otherwise.



A few pre-emptive responses to possible objections:

Objection: There's only one sort of nothing.

Response: There are different kinds of nothing. "I have no shoes" is not the 
same as "I have no feet". The hole in a donut is not the same as a hole in the 
ground or an electron hole in a crystal lattice. The set of ideas held by 
somebody who has no idea is not the same kind of nothingness as the nothingness 
in a vacuum.

Objection: But nothing isn't nothing, it's something!

Response: You are committing the fallacy of reification. Just because you can 
give a name to a concept doesn't make the concept a thing. "Cold" is not a 
thing, it is just the absence of heat, "death" is the absence of life, 
"stillness" is the absence of motion, and "nothing" is the absence of things, 
not a thing itself. That's why there are different kinds of nothing -- it 
depends which things get counted.

Objection: Even the vacuum is not empty! It is filled with a sea of virtual 
particles and anti-particles and zero-point energy.

Response: I've studied quantum mechanics and particle physics too. You're very 
clever. Do I really have to answer this one?

Objection: Yes.

Response: Okay.

The existence of zero-point energy is very interesting, but it has no relevance 
to the topic we're discussing. In practical terms, most "zeroes" are relative 
measures, not absolute. For an electrical analogy, think of electrical 
potential: what matters is the potential difference, not the actual potential. 
There's no current flowing between two points both at the same potential 
energy. Similarly, we don't usually care about the *absolute* presence or 
absence of things, but relative to some quantity or substance. A hole in the 
ground is filled with air, or sometimes water, but we care only about the lack 
of soil in the hole.

Objections: Empty containers aren't nothing, they are themselves a thing. An 
empty egg carton is still an empty carton, even if there are no eggs in it.

Response: Indeed.

Nevertheless, the language designer gets to choose the specific model of 
truthiness the language uses. In the opinion of the Python designer GvR, it is 
more useful to care about the *content* of the container than the container 
itself in a truth context. Some languages make other choices. If you don't like 
Python's choice, you are free to:

- suck it up and live with it;
- fork Python and give the fork your preferred semantics;
- use another language which is a closer fit to your preferences;
- use your own container types with your preferred semantics;
- complain bitterly about it on your blog, Facebook wall, mailing lists etc.;
- buy an automatic weapon and make GvR pay for disagreeing with you;

etc. although some of these choices are better than others.


[...]
> Sure one can always (ok usually) avoid a bug in a system by not using the
> feature that calls up the bug. Are you suggesting that that makes the bug
> non-exist?

You haven't demonstrated that the existence of a feature is a bug.

> In more detail:
> - If user/programmer defines a new type
> - Which has no dunder bool
> - Which has no dunder len
> - Which has no ... (all the other things like len that can make for a
> non-trivial bool behavior)
> - And then uses a value of that type in a non-trivial bool-consuming position
> such as the condition of an if/while etc

then they get the default behaviour, just as they get the default behaviour if 
they call str() or repr() on their object without defining their own __str__ or 
__repr__ methods, or if you call == without providing a custom __eq__ method.


> There's a very good chance that bool-usage is buggy

I doubt it.


> In more mundane terms, dunder bool defaulting to true is about as useful
> as if it defaulted to
> 2*random.random()

No, not all. There is a consistent model and predicable effects from defaulting 
to true. There is no consistent model from defaulting to 2*random().

(Although, since that is **nearly always** a truthy value, it probably makes no 
practical difference: the object will be falsey only about 1 time in 2**60 or 
2**61).


> Why not default it in the way that AttributeError/NameError/TypeError etc
> are raised?

Because that would be less useful and more annoying.

There are a set of behaviours which nearly all objects should define, and which 
are nearly always the same (or at least have a sensible default):

__getattribute__
__getattr__
__setattr__
__delattr__
__str__
__repr__
__eq__
__ne__
__hash__
__bool__

etc. Since the behaviour is nearly always the same, it makes sense to move that 
behaviour into the base class object(), and let the exceptional cases be 
exceptional, rather than require everybody to write the same piece of code over 
and over and over again.



-- 
Steven
git gets easier once you get the basic idea that branches are homeomorphic 
endofunctors mapping submanifolds of a Hilbert space.




More information about the Python-list mailing list