Prev: grailbrowser now running under python 2.5 (probably above too)
Next: Naming Conventions, Where's the Convention Waldo?
From: Steven D'Aprano on 12 Jul 2010 23:16 On Mon, 12 Jul 2010 19:28:28 -0600, Ian Kelly wrote: > On Mon, Jul 12, 2010 at 6:18 PM, Steven D'Aprano > <steve(a)remove-this-cybersource.com.au> wrote: >>> I prefere to explicitly write what I want to test: >>> >>> if myInt <> 0: >> >> I would argue against that. Why do you, the coder, care about the >> specific details of treating ints in a boolean context? The int type >> itself knows, leave the decision to it. > > I think you're missing the point. He's not using ints in a boolean > context. If it were a boolean context, he would be using bools in the > first place. Of course he is -- he's branching on an int (a boolean context), and explicitly writing out the test as myInt <> 0. In fact, that test could just as easily be written as bool(myInt), which has the benefit of being even more explicit that you want a bool. It's also silly. Explicitness is not always a virtue. Beginners sometimes write things like: s = "hello " t = "world" print str(s + t) and we rightly shake our heads at the sheer n00b-ness of it. Writing the explicit tests: if bool(myInt): or even: if myInt <> 0: are firmly in the same category. The only difference is that it is more familiar and therefore comfortable to those who are used to languages that don't have Python's truth-testing rules. > What he is objecting to is the practice of testing for > special cases of ints (i.e. 0) by treating them as bools. The specific > details of converting ints to bools are very much relevant here; as long > as 0 is false, it works. If -1 is false (a semantic I have actually > seen used), then it does not. You've seen -1 being used as false? Where? Are you still talking about Python builtins or language semantics? If you're about to say string.find(substring), no, absolutely not. find does not return a true/false flag, it returns an index, with -1 the sentinel for Not Found. This is not a flag! In fact, one of the motivations for adding bools to Python was to avoid people mistakenly thinking that cmp(a, b) returned a flag 0, 1 when it actually returns a three-state -1, 0, 1. This was a common source of errors before Python got bools. -- Steven
From: Paul Rubin on 12 Jul 2010 23:22 Steven D'Aprano <steve-REMOVE-THIS(a)cybersource.com.au> writes: > Writing the explicit tests: > if bool(myInt): > or even: > if myInt <> 0: > > are firmly in the same category. The only difference is that it is more > familiar and therefore comfortable to those who are used to languages > that don't have Python's truth-testing rules. It's like list.append returning None. It helps catch errors.
From: Steven D'Aprano on 12 Jul 2010 23:51 On Mon, 12 Jul 2010 17:36:38 -0700, Paul Rubin wrote: >> I would argue against that. Why do you, the coder, care about the >> specific details of treating ints in a boolean context? The int type >> itself knows, leave the decision to it. > > There is a horrible (IMO) thing that Perl, Lua, and Javascript all do, > which is automatically convert strings to numbers, so "12"+3 = 15. > Python has the good sense to throw a type error if you attempt such an > addition, but it goes and converts various types to bool automatically, No, what Python does is more subtle than that. An example using strings will (I hope!) make it clear. Or possibly muddy the waters even more. Compare converting strings to ints: the string "1" maps to the int 1, "2" to 2, and so forth. There's a one-to-one map of string to int (modulo unicode and whitespace issues), and since this is more or less a universal standard, it's enshrined in the language. Now consider converting strings to bools. Should "true" map to True? Or "yes", "ja", "vrai", "waar", or something else? That's an application- specific question, not a universal standard (not even a de facto standard), and Python rightly avoids it. What about "maybe" or "strawberry jam"? You can't convert "strawberry jam" into True or False any more than you can convert it into an int. What Python does instead is to accept *any* object in a context where other languages (such as Pascal) would insist on a boolean. In practice, that means branches (if) as well as the short-cut operators and, or, not. The semantics of this is well-defined, and I trust I don't need to go over it again. In an expression like: x and y unlike Pascal, there is no requirement that x and y be booleans. This is why I talk about x and y being used "in a boolean context", rather than converting it to a bool. [3,4,5] is not, by any stretch of the imagination, True converted into a list, and likewise [2,3,4] is a list and can't be converted to a flag any more than it can be converted to an int. But what I do say is that, according to Python's semantics, the list [3,4,5] is equivalent to True in a boolean context. Where Python muddies the water is to provide a bool() built-in which *does* convert any object to canonical boolean form. bool([2,3,4]) returns True, which contradicts what I said above about not converting the list into a flag. I accept this -- it's a triumph of practicality over purity. It would be silly to force people to write: # get the canonical form if any_old_object: flag = True else: flag = False when we can say flag = bool(any_old_object). One last thing -- we can see that Python does *not* convert objects to bools "in a boolean context". The Python virtual machine really does accept any object as an argument to and/or/not operators, as well as if: >>> import dis >>> dis.dis(compile('a or b', '', 'single')) 1 0 LOAD_NAME 0 (a) 3 JUMP_IF_TRUE 4 (to 10) 6 POP_TOP 7 LOAD_NAME 1 (b) >> 10 PRINT_EXPR 11 LOAD_CONST 0 (None) 14 RETURN_VALUE The JUMP_IF_TRUE opcode accepts any object, not just True or False. -- Steven
From: Ian Kelly on 12 Jul 2010 23:54 On Mon, Jul 12, 2010 at 9:16 PM, Steven D'Aprano <steve-REMOVE-THIS(a)cybersource.com.au> wrote: > You've seen -1 being used as false? Where? Are you still talking about > Python builtins or language semantics? Some of our database tables at work use 1 for true, -1 for false, and 0 for neither. Don't look at me, I didn't design it. Why they didn't just make the column nullable is beyond me, but that's the way it is.
From: Steven D'Aprano on 12 Jul 2010 23:55
On Mon, 12 Jul 2010 20:22:39 -0700, Paul Rubin wrote: > Steven D'Aprano <steve-REMOVE-THIS(a)cybersource.com.au> writes: >> Writing the explicit tests: >> if bool(myInt): >> or even: >> if myInt <> 0: >> >> are firmly in the same category. The only difference is that it is more >> familiar and therefore comfortable to those who are used to languages >> that don't have Python's truth-testing rules. > > It's like list.append returning None. It helps catch errors. How? >>> myInt = 'x' >>> if myInt <> 0: .... print "myInt is not zero, safe to divide" .... print 42/myInt .... myInt is not zero, safe to divide Traceback (most recent call last): File "<stdin>", line 3, in <module> TypeError: unsupported operand type(s) for /: 'int' and 'str' What error did this catch? -- Steven |