Equivalent code to the bool() built-in function

C

candide

Consider the following code :

# --------------------------------------
def bool_equivalent(x):
return True if x else False


# testing ...

def foo(x):
return 10*x

class C:
pass

for x in [42, ("my","baby"), "baobab", max, foo, C] + [None, 0, "", [],
{},()]:
print bool(x)==bool_equivalent(x)
# --------------------------------------


Is the bool_equivalent() function really equivalent to the bool()
built-in function ?
 
C

Chris Rebert

Consider the following code :

# --------------------------------------
def bool_equivalent(x):
   return True if x else False


# testing ...

def foo(x):
   return 10*x

class C:
   pass

for x in [42, ("my","baby"), "baobab", max, foo, C] + [None, 0, "", [],
{},()]:
   print bool(x)==bool_equivalent(x)
# --------------------------------------


Is the bool_equivalent() function really equivalent to the bool() built-in
function ?

The ternary operator, if-statement, and `while` all do the equivalent
of an implicit bool() on their condition, so bool_equivalent() will
always give the same result as bool() because it's indeed using the
moral equivalent of bool() behind the scenes.
That is, `True if x else False` conceptually gets compiled down to
`True if bool(x) == 1 else False` (but without doing a run-time lookup
of "bool").

Cheers,
Chris
 
C

candide

Le 16/04/2011 23:38, Ben Finney a écrit :
So the answer to the OP's question is no: the function isn't equivalent
to the type,


Can bool() type and bool_equivalent() function return different values ?

because the OP's ‘bool_equivalent’ function necessarily
uses the built-in ‘bool’ type, while the reverse is not true.


The documentation doesn't seem to state it performs this call. I'm
referring to
-- §5.10 Boolean operations in Document Reference Python 2.7
-- bool()'s description in Library Reference
-- §5.1 Truth Value Testing in Library Reference
 
C

candide

Le 16/04/2011 23:13, Ben Finney a écrit :
The ‘bool’ built-in is not a function.

<type 'type'>


Oops, unfortunate confusion!! but built-in types and built-in functions
are sometimes so similar from the user's point of view ;)

All the same, you can notice that the official documentation describes
bool() as a built-in function, cf.
http://docs.python.org/library/functions.html
 
C

Chris Rebert

Le 16/04/2011 23:38, Ben Finney a écrit :


Can bool() type and bool_equivalent() function return different values ?

No. The distinction being drawn is rather pedantic, IMO.
The documentation doesn't seem to state it performs this call.

This is why I used the qualifiers "the equivalent of" and "conceptually".
I'm referring to
-- §5.10 Boolean operations in Document Reference Python 2.7
-- bool()'s description in Library Reference

"bool([x]) Convert a value to a Boolean, using the standard truth
testing procedure."
-- §5.1 Truth Value Testing in Library Reference

This describes "the standard truth testing procedure". Ideally, this
section would be linked to in bool()'s docs.

Cheers,
Chris
 
C

candide

Le 17/04/2011 04:39, Ben Finney a écrit :
Why do you need to know? (I should have asked that question earlier.)


First because I was doubting the true interest of the bool() type. In
fact, it appears that it's _semantically_ a shortcut for
True if x else False. I could't imagine a builtin function having a so
trivial implementation. Compare with float() or int(). I also try to
consider how essential the bool() type is. Again compare with int() or
str() types.

In the orther hand, I'm builting a sort of documentation for learning
Python. In order to spell out the purposes of the bool() type, I guessed
that giving an equivalence code could help.
 
C

Chris Angelico

I also try to consider how essential the bool() type is.
Again compare with int() or str() types.

Well, of course you can always implement bool as an int; C has done
this for decades, and it hasn't killed it. You can also implement
integers as strings - REXX manages quite well, and gets some
advantages therefrom. But having an explicit bool type has its
benefits too. Essential? No. Useful? Certainly.

Chris Angelico
 
D

Daniel Kluev

I could't imagine a builtin function having a so trivial implementation.

As it was pointed out, its not function, its type,
SETBUILTIN("bool", &PyBool_Type);

While its __new__ is indeed trivial (in essence, it just calls
PyObject_IsTrue), it also provides needed comparison ops, repr and
other magic methods for the type.
You can check Objects/boolobject.c in python repository if its
implementation is interesting for you.
 
C

candide

Le 17/04/2011 11:46, Ben Finney a écrit :
That bends my brain. Both ‘True’ and ‘False’ are instances of the ‘bool’
type. So of course the ‘bool’ constructor will return them.

A user of the Python programming language can sensibly handle boolean
values and write a lot of good code and at the same time completely
ignore all the object oriented stuff behind the True and False instances.
What is the
“shortcut†you refer to?

bool(x) is nothing more than a shortcut for the following expression :
True if x else False.
Compare for instance with the str() type whose implementation is far
more complicated. When learning Python, you early and communly use str()
type but use sparingly the bool() type. On the other hand, the learner
cannot replace himself the service str() provide (hard to write an
equivalent code). It's not the case for the bool() type : True if foo
else False.


Remember, the point of a type is to encapsulate both behaviour and an
exclusive domain of possible values. The Boolean type is particularly
simple, so I don't see why you would be surprised that the behaviour of
the ‘bool’ constructor is simple – that's a feature of that type.

In fact, bool() is so simple that at first glance I didn't see any use
for it.

Something different from<URL:http://docs.python.org/tutorial/>.


More : something _opposite_ to the official Python tutorial ;) I found
this tutorial very unfriendly and very unsmooth, poorly structured,
providing overloaded examples, unable to distinguish essential from
incidental, full of bad explanations, etc. OOP presentation is terribly
verbose and speculative, chapter on error handling is very hard to
follow if you are not aware of the exception mechanism, etc

This is not a surprise, as the abstract explains :

"This tutorial does not attempt to be comprehensive and cover every
single feature, or even every commonly used feature."

The nice graphical aspect of the tutorial (thanks to Sphinx) doesn't
compensate the many weaknesses of the content.
 
D

Daniel Kluev

It won't look up the *name* ‘bool’, but it will use that object. Any
boolean expression is going to be calling the built-in ‘bool’ type
constructor.

So the answer to the OP's question is no: the function isn't equivalent
to the type, because the OP's ‘bool_equivalent’ function necessarily
uses the built-in ‘bool’ type, while the reverse is not true.

Actually, as I was curious myself, I've checked sources and found that
`True if x else False` will _not_ call bool(), it calls
PyObject_IsTrue() pretty much directly..... return True if x else False
....2 0 LOAD_FAST 0 (x)
3 POP_JUMP_IF_FALSE 10
6 LOAD_GLOBAL 0 (True)
9 RETURN_VALUE13 RETURN_VALUE


case POP_JUMP_IF_FALSE:
w = POP();
if (w == Py_True) {
Py_DECREF(w);
goto fast_next_opcode;
}
if (w == Py_False) {
Py_DECREF(w);
JUMPTO(oparg);
goto fast_next_opcode;
}
err = PyObject_IsTrue(w);
Py_DECREF(w);
if (err > 0)
err = 0;
else if (err == 0)
JUMPTO(oparg);
else
break;
continue;

So technically these implementations are equivalent besides the fact
that bool() is type rather than function.
 
G

Gregory Ewing

candide said:
bool(x) is nothing more than a shortcut for the following expression :
True if x else False.

It's a much shorter and easier-to-read shortcut.

Also keep in mind that if-else expressions are quite a recent
addition to the language.

Before that, we had 'not not x' as another equivalent
 
G

Gregory Ewing

Chris said:
Well, of course you can always implement bool as an int;

Which Python used to do once upon a time -- and still does
in a way, because bool is a subclass of int.

The bool type was added mainly to provide a type that prints
out as 'True' or 'False' rather than 1 or 0. This can be
a considerable help for debugging and keeping the conceptual
meaning of one's data clear.
 
S

Steven D'Aprano

bool(x) is nothing more than a shortcut for the following expression :
True if x else False.

"Nothing more"? That's completely incorrect. bool is a type object, not
an expression, so you can do things like these:
False
False
types = [str, complex, float, bool]
[f(x) for f, x in zip(types, (1, 2, 3, 4))]
['1', (2+0j), 3.0, True]


For that reason alone, bool is useful.


Compare for instance with the str() type whose implementation is far
more complicated.

So what? What's your point? Types and functions don't exist because
they're *complicated*, but because they're *useful*. bool is useful:
in order for True and False to print as True and False, they need to
belong to a type that has that behaviour. bool is that type.

Consequently, calling bool(x) returns a canonical True/False from any
arbitrary object, but that's not the primary purpose for bool existing.


When learning Python, you early and communly use str()
type but use sparingly the bool() type.

So what? What's your point?


A little bit of history may make things more clear to you.

Up to version 2.1, Python had no built-in True and False values. This
*almost always* worked fine, since you can always say (e.g.):

if x:
do_something()
elif y or z:
do_something_else()

for any objects x, y and z. But it wasn't quite ideal, because:

* if flags are written 0 and 1, that frequently fools people into
thinking they are meant to be understood as *integer* values rather
than boolean values, and they will do arithmetic on those flags;
* people coming from other languages were confused and worried by
the lack of bools and found it difficult to get used to the
Python truth-testing idiom;
* people would define a standard pair of True/False values at the
top of each module, so they could refer to flags by name rather
than value;
* there was never any consistency, people would write any of:

true = 1; false = 0
FALSE = 0; TRUE = not FALSE
True = -1; False = not True

or whatever other idiom they preferred, or they'd write custom
classes that printed as true/TRUE/True etc.


So in Python 2.2, Python introduced two new built-in names, True and
False, with values 1 and 0 respectively:

[steve@sylar ~]$ python2.2
Python 2.2.3 (#1, Aug 12 2010, 01:08:27)
[GCC 4.1.2 20070925 (Red Hat 4.1.2-27)] on linux2
Type "help", "copyright", "credits" or "license" for more information.<type 'int'>


Then in Python 2.3, Python introduced the bool type, which gave True and
False an independent type ("bool") with a prettier display. For backwards
compatibility reasons, bool is actually a subclass of int, so that code
that does arithmetic on flags continues to work.

The ternary if operator `true-value if flag else false-value` wasn't
introduced until version 2.5.

So as you can see, while you are correct *today* that the function call
"bool(x)" is equivalent to "True if x else False", for at least seven
versions of Python (1.4, 1.5, 1.6, 2.0 through 2.4) that was not correct.

Furthermore, why would you write "True if x else False" (twenty
characters) instead of "bool(x)" (seven characters)? bool is the
canonical way to get an explicit boolean value. It's even shorter than
"not not x" (nine characters), and far more obvious than either of the
alternatives.

You're also correct that there very rarely is a need to explicitly
convert arbitrary objects to booleans. That's okay. That's not why bool
exists, that's just an occasionally useful side-effect.
 
C

Chris Angelico

types = [str, complex, float, bool]
[f(x) for f, x in zip(types, (1, 2, 3, 4))]
['1', (2+0j), 3.0, True]

I believe this one would work fine with a function defined as per OP -
zip takes callables, which could be types or functions.
* if flags are written 0 and 1, that frequently fools people into
 thinking they are meant to be understood as *integer* values rather
 than boolean values, and they will do arithmetic on those flags;

Depending on what you mean by arithmetic, that can be a good thing.
I've frequently, in various languages, used booleans as though they
were integers - for instance, indexing a list with an integer plus a
condition. Contrived example:

mode = 2
....
print ("default", "default-root",
"modeA","modeA-root",
"modeB","modeB-root",
) [mode+mode+(uid==0)]

For debugging output, where I want to keep it as self-contained as
possible, constructs like these are very handy - especially as they
can be embedded inside other expressions.

Every language I've used except BASIC has used True == 1, False == 0,
but I'm sure there are some which use other values. If True == -1,
then you simply subtract the bool from the int instead of adding them.
If it's something else, you arrange the array accordingly.
* there was never any consistency, people would write any of:

 true = 1; false = 0
 FALSE = 0; TRUE = not FALSE
 True = -1; False = not True

Just as long as someone doesn't use:
true = 1; false = -1
which results in the annoying situation that:
if x == false:
is different from:
if x:
But on the plus side, TheDailyWTF.com is never short of publishable material...

Chris Angelico
 
D

Dave Angel

Actually, as I was curious myself, I've checked sources and found that
`True if x else False` will _not_ call bool(), it calls
PyObject_IsTrue() pretty much directly.

You miss Ben's point, and got it backwards.

He didn't say that the function will call the bool() type (constructor),
but that it will use the bool type; in other words, it will return True
or False. The one that may not is the function bool().
143

Once bool has been reassigned, calling it may not return True or False
any more.

DaveA
 
C

Chris Angelico

Any language that allows you to do this is either awesome or
terrifying. Come to think of it, there's not a lot of difference.

Chris Angelico
 
D

Daniel Kluev

He didn't say that the function will call the bool() type (constructor), but
that it will use the bool type;

Actually, he did say exactly that
Any boolean expression is going to be _calling the built-in ‘bool’ type constructor_
(underscores are mine)
The one that may not is the function bool().
Its not function, its type. There is no wrapper, bool(x) is direct
constructor call.
Once bool has been reassigned, calling it may not return True or False any more.
Not sure what did you want to show with this example. You just
assigned name in locals() namespace. Boolean type itself didn't change
because of that and would still call PyObject_IsTrue() and return
according constant. Sure, python allows to change namespaces in very
flexible way, but we are talking about specific objects (PyBool_Type)
rather than pointers to them.
in other words, it will return True or False.
Well, his code explicitly returns True or False, so this was not doubted.

Although I agree with Ben that this doesn't have any practical
meaning. bool() is more readable and implementation-independent way to
do explicit casting to boolean than the hack in OP.
 
N

Ned Deily

Chris Angelico:
Dave Angel:
Any language that allows you to do this is either awesome or
terrifying. Come to think of it, there's not a lot of difference.

Even better:
$ python2.7 -c 'False = True; print False'
True

Alas:
$ python3 -c 'False = True; print(False)'
File "<string>", line 1
SyntaxError: assignment to keyword
 
C

Chris Rebert

Someone in Python3 dev thinks it's a bad idea to shoot yourself in the foot.

Remind me some day to finish work on my "ultimate programming
language", which starts out with a clean slate and lets the programmer
define his own operators and everything.

Pro: The expression evaluator can be taught to interpret Dungeons &
Dragons notation - 2d6 means "random(1,6)+random(1,6)".
Con: The same expression might mean something completely different in
another program.

Pro: You can do anything.
Con: You can do anything.

I think someone already beat you to it. They call their invention "Lisp". :p

Cheers,
Chris
 
C

Chris Angelico

I think someone already beat you to it. They call their invention "Lisp". :p

Bah! Lisp comes, out of the box, with far too many features! No no no.
If you want the + operator to add two numbers, you have to say so!
(Obviously there'll be extensive use of #include or equivalent.)

It started out as a serious idea - a really clean language that would,
like Lua or Python, be nicely embeddable in larger programs - and
specifically, I wanted an expression evaluator that could have
d-notation added to it. But the realisation that such a language
consisted of a foot, a machine gun, and a belt of ammunition kinda led
to it being dropped.

ChrisA
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,150
Members
46,696
Latest member
BarbraOLog

Latest Threads

Top