On Thu, 23 Jun 2016 08:21 pm, Antoon Pardon wrote: > Op 23-06-16 om 11:39 schreef Steven D'Aprano: [...] >> To decide on a branch, you don't need an actual bool, anything capable of >> acting like a bool will do. As a language design, ALL objects are capable >> of acting like a bool. Python has a specific protocol in place for >> deciding whether an object quacks like a bool: > > But an object acting like a bool, doesn't mean this bool behaviour makes > the disctinction you actually need.
Um... okay? I'm not really sure I understand the point you think your making. Lists and tuples can be exchanged in many duck-typing situations, but if you need something with an in-place sort method, you can't use a tuple. That's a given. If you need some feature that isn't offered by truthiness, you can't use truthiness to detect that feature. It seems hardly worth mentioning. > Python tempts people to rely on those > truthy values, because it saves typing is pythonic and it works for the > moment and then something unexpected gets passed through and you find > yourself chasing a very illusive bug. You keep saying that, but I've never seen it happen. I've seen cases where people have been surprised by the unexpected truthiness of an object ("I expected an exhausted iterator to be false, but it was true"), but that's not what you seem to be describing. To be honest, I'm not sure what you are describing. Your explanation is maddeningly vague. Since bools offer a *very small* API (beyond what they also offer as a subclass of int), I cannot imagine what unexpected thing you might get passed in that leads to "a very illusive bug". The bottom line is, bools offer only a single major API[1]: are they truthy, or falsey? What else can do you with them? Nothing. They support conditional branches, and boolean operators "or" and "and". That's all. They don't have methods to call, or attributes to set. You can use a bool to take the if branch, or the else branch, and that's effectively all. Since *all* objects support that same bool API, what can you *possibly* be passed in place of a bool that fails to work? I acknowledge, cheerfully, that there might be a mismatch between what you expect and what the object actually does. "I expect empty containers to be falsey, and non-empty ones to be truthy; but this RedBlackTree object is always false even if it has many items; and this SortedDict is always true even when it is empty." That's a nuisance and a pain when it happens, but it's arguably a bug in the object or at least a misfeature, and besides that's the risk when you duck-type. You're trusting the object that you get to behave like the object you expect, or it will break things. (An object with a misbehaving __bool__ is no better or worse than an object with a misbehaving sort() method, or __add__ method.) So I'm not really sure what you are trying to describe. I guess it might be something like this: def spam(alist): if alist: process(alist) else: print("empty list") If you pass 1 instead of an actual list, then you don't get an error until somewhere inside process(). Potentially far, far away. So you want to write: def spam(alist): if len(alist): process(alist) # requires an actual list else: print("empty list") and now calling spam(1) will raise immediately. Great. But that's not really anything to do with *bools* specifically. If you call spam() with a dict, or a set, or a tuple, or a RedBlackTree, any other object with a length, you're no better off. If you absolutely need a list, and nothing else, then you have to type-check. In practice, I don't see how truthy/falsey objects lead to more or worse bugs than any other form of dynamic typing. To me, your position is equivalent to saying that dynamic typing and duck-typing is really great, except for len(). len() should absolutely only work on lists, and nothing else, so any time you want to get the length of an object, you must work with real lists, not listy sequences: if len(list(mystring)) > 20: ... print(len(list(mydict.keys())), "items") etc. Substitute "bool" for "len" and you might understand how I feel about your position. [...] >> Somehow I doubt that you write three-state logic everywhere: > > Since I wrote above the I *sometimes* found this need. You may > safely assume I don't write it everywhere. Fair enough. [1] I exclude minor things like repr(True), and the fact that they are subclassed from int. -- Steven -- https://mail.python.org/mailman/listinfo/python-list