I was somewhat confused until I found the bug in my code. I had to change
a.matched_images.count #True when variable is 0
to
a.matched_images.count > 0 #False when variable is 0
Since I quickly wanted to know whether an object had any images, the first code will appear like the photo has images since the expression evaluates to True when the meaning really is false ("no images" / 0 images)
Did I understand this correctly and can you please answer or comment if these expressions should evaluate to different values.
What is the nature of count? If it's a basic Python number, then if count is the same as if count != 0. On the other hand, if count is a custom class then it needs to implement either __nonzero__ or __len__ for Python 2.x, or __bool__ or __len__ for Python 3.x. If those methods are not defined, then every instance of that class is considered True.
Without knowing what count is, it's hard to answer, but this excerpt may be of use to you:.
The following values are considered false:
None
False
zero of any numeric type, for example, 0, 0L, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a
__nonzero__() or __len__() method, when that method returns the
integer zero or bool value False. [1]
All other values are considered true — so objects of many types are
always true.
>>> bool(0)
False
So.. no, if it were an int that wouldn't matter. Please do some tracing, print out what count actually is.
Related
Background: I was going to answer this question, starting with something like "The documentation specifies that non-empty lists are true and [...]". But then I realized that it doesn't specify that anymore. At least not obviously, which it used to.
Up to Python 3.5, the documentation still said (emphasis mine):
4.1. Truth Value Testing
Any object can be tested for truth value, for use in an if or while
condition or as operand of the Boolean operations below. The following
values are considered false:
None
False
zero of any numeric type, for example, 0, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a __bool__() or __len__() method, when that method returns the integer zero or bool
value False. [1]
All other values are considered true — so objects of many types are always true.
Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)
A non-empty list like [5] doesn't fall under anything in the above list, so the "All other" specifies that it's true.
But since Python 3.6, that is gone. That section now says:
Truth Value Testing
Any object can be tested for truth value, for use in an if or while
condition or as operand of the Boolean operations below.
By default, an object is considered true unless its class defines
either a __bool__() method that returns False or a __len__() method
that returns zero, when called with the object. [1] Here are most of the
built-in objects considered false:
constants defined to be false: None and False.
zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
empty sequences and collections: '', (), [], {}, set(), range(0)
Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)
Now [5] could have a __bool__() method that returns False, and thus it would be false. Is there a new place in the current documentation that somehow specifies that non-empty lists are true?
The documentation of all the built-in classes list all the special methods that they implement. If a method isn't listed, you can assume it isn't implemented.
Since the documentation of list doesn't say anything about overriding the __bool__ method, it inherits the default behavior.
To find all the list operations, start here. However, it also points out that lists implement all the common and mutable sequence operations, so you'll need to read that documentation for the complete list.
Just found a place, in the reference (emphasis mine):
6.11. Boolean operations
[...]
In the context of Boolean operations, and also when expressions are
used by control flow statements, the following values are interpreted
as false: False, None, numeric zero of all types, and empty strings
and containers (including strings, tuples, lists, dictionaries, sets
and frozensets). All other values are interpreted as true.
User-defined objects can customize their truth value by providing a
__bool__() method.
It bothers me a little that that's right away contradicted by the very next sentence, about user-defined objects, but I'll take it.
[5] is a list object. Unless you have specifically overridden the built-in __bool__ method, you get the default method. As the documentation already implied, this is Truthy.
The update doesn't change things so much as widen the explanation to cover derived types and other augmentations of the built-in types.
Sorry if this hasn't been asked before because it's obvious to anyone with any form of training in Python. I spent most of my days programming in Java and I was wondering about this thing I take to be an idiosyncrasy in Python. I was messing around with
this=bool
if(this==True):this="big"
print(this)
Not surprisingly, I received a generic type declaration as output because that would indeed be big if True.
<class 'bool'>
Then I used my limited Java comprehension to determine that I could simplify the expression more, it's a conditional, right? Those are made for Boolean types.
this=bool
if(this):this="big"
print(this)
Then I almost laughed out loud but it was mirth tinged with terror
big
It makes sense that "this" is "less falsy" than "this==True", which is False with a capital F, but I still didn't think it should evaluate as True. Besides, truthy and falsy seem to be good enough in other cases to produce the expected result. So what makes an empty Boolean truthy?
My first thought was it must be just checking to see if "this" exists. So I removed the declaration in the first line, expecting to find "if([something that doesn't exist]):" would be skipped. Instead it threw an error. If the simple fact of its existence evaluates as True, shouldn't its nonexistence simply evaluate to False? What's the point of a functionality in which an initialized (empty) value evaluates to true if an uninitialized value doesn't return false?
I thought I understood after reading this answer and indeed my first thought was, "Oh, it must just be checking to see if 'this' exists at all." Then I typed
if(this is not None):
as well as
if(this!=None):
and got "big" as the output again, suggesting that "this" is None.
Then, almost in a fit of panic, I typed
this=bool
if(this==None):this="big"
if(this==True):this="big"
if(this==False):this="big"
print(this)
and, as you may have guessed, failed
<class 'bool'>
Surely a Boolean must be one of these "three"? Please don't tell me I've discovered a "fourth" Boolean value, I couldn't handle that kind of notoriety.
The problem (I think) I have with all this is that removing the initialization of 'this' in the first line causes an error, and not a false case in the if statement. If "if(x):" is executed when x exists, then shouldn't a non-existent "x" pass and just skip over that statement? Why not leave the Boolean if functionality from Java and just force us to check if x is not null in that case?
bool isn't a boolean, it's a class (just like int, str etc.). Classes are always truthy.
I think you meant to write this = bool() (which is the same as this = False - there's no such thing as an "empty" boolean).
I don't understand what you're doing here. You're taking the class bool and checking if it is exactly equal to True. Well, no of course it isn't, True is an instance of bool, a class isn't exactly equal to its instances. It's not equal to False or None either. But that doesn't stop it from being true in a Boolean context, because it's not empty.
Simply put, in general, you cannot say that if x has the same meaning as if x == True in Python. Their result depends on how x's methods __bool__ and __eq__ are defined, respectively.
For classes themselves, like bool or int (i.e. the type, not an object of that class), __bool__ is defined to always return True; while the comparison against True returns False.
Therefore:
if int == True: print("NOT printed")
if int: print("printed")
if bool(int): print("printed") # equivalent to the previous one
bool is a builtin class. You are assigning this to the bool class, making it never equal True. When you type if(this), this is being automatically converted to a boolean so it can be evaluated in the if statement. Classes are always converted to True rather than False, which is why the if statement executes.
I recently found out that python has a special value NotImpemented to be used with respect to binary special methods to indicate that some operation has not been implemented.
The peculiar about this is that when checked in a binary situation it is always equivalent to True.
For example using io.BytesIO (which is a case where __eq__ in not implemented for example) for two objects in comparison will virtually return True. As in this example (encoded_jpg_io1 and encoded_jpg_io2 are objects of the io.BytesIO class):
if encoded_jpg_io1.__ne__(encoded_jpg_io2):
print('Equal')
else:
print('Unequal')
Equal
if encoded_jpg_io1.__eq__(encoded_jpg_io2) == True:
print('Equal')
else:
print('Unequal')
Unequal
Since the second style is a bit too verbose and normally not prefered (even my pyCharm suggests to remove the explicit comparison with True) isn't a bit tricky behavior? I wouldn't have noticed it if I haven't explicitly print the result of the Boolean operation (which is not Boolean in this case at all).
I guess suggesting to be considered False would cause the same problem with __ne__ so we arew back to step one.
So, the only way to check out for these cases is by doing an exact comparison with True or False in the opposite case.
I know that NotImpemented is preferred over NotImplementedError for various reasons so I am not asking for any explanation over why this matter.
Per convention, objects that do not define a __bool__ method are considered truthy. From the docs:
By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero
This means that most classes, functions, and other builtin singletons are considered true, since they don't go out of their way to specify different behavior. (An exception is None, which is one of the few built-in singletons that does specifically signal it should be considered false):
>>> bool(int) # the class, not an integer object
True
>>> bool(min)
True
>>> bool(object())
True
>>> bool(...) # that's the Ellipsis object
True
>>> bool(NotImplemented)
True
There is no real reason for the NotImplemented object to break this convention. The problem with your code isn't that NotImplemented is considered truthy; the real problem is that x.__eq__(y) is not equivalent to x == y.
If you want to compare two objects for equality, doing it with x.__eq__(y) is incorrect. Using x.__eq__(y) == True instead is still incorrect.
The correct solution is to do comparison with the == operator. If, for whatever reason, you can't use the == operator directly, you should use the operator.eq function instead.
From what I have researched most operators and methods can be overridden when creating a class in python. By using __add__(self, other) and others for example.
My "problem" (more like I don't quite understand how it is done) is for verifying is something is in my class I have to obviously use __contains__(self, theThing).
Alas I thought this should return a boolean value in the code itself, but from example code I have seen, like this:
def __contains__(self, posORname):
return [node.getId() for node in self.tree if node.getId() == posORname or node.getName() == posORname]
What I am returning is therefore a tuple containing the Id of where said item is.
Could someone explain why this is done instead of returning True or False? And if so, shouldn't it be implicitly possible to get the index of an item in a structure by just using in?
Thanks :D
For python2 __contains__ or python3 __contains__ both should return true or false. And now the question is what is True and what is False. Truth value testing.
The following values are considered false:
None
False
zero of any numeric type, for example, 0, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a bool() or len() method, when that method returns the integer zero or bool value False.
__contains__() is expected to return a boolean value. In your case, __contains__() is returning a list with any tree nodes that match posORname. Thus, it's basically just a lazy way of implementing __contains__(), because in a boolean context:
An empty list is equivalent to False.
A non-empty list is equivalent to True.
While you could potentially have __contains__() return a data structure with the index or ID of the matching tree node, the in operator doesn't care; it only exists to check whether or not an item is contained by an object. Also, __contains__() is not intended to be called directly, so relying on it to return such information would be an abuse of the __contains__() method.
Instead, you would be better off implementing an separate method for getting the index/id of a node.
The result of __contains__ is converted to a boolean according to the usual rules, so that, e.g., empty lists count as False while lists with something in them count as True. So for your example, if the list has anything in it --- that is, any items match the criteria in that list comprehension --- then the in test will be True.
This auto-conversion-to-bool behavior does not appear to be explicitly documented, and is different from other operators (like < and >), which return what they return without converting to bool. There is some discussion of the behavior here.
For one of my sites, I need to check if several class attributes are defined and not empty. So far, I've happily used if self.attr:, which in my mind is the shorthand for if self.attr is not None and self.attr is not '':, or whatever the undefined value of the attribute is.
This works fine, but yields to surprising behavior when checking multiple string attributes. '' and '' is not False (as I expected), but ''.
This begs the question: are there other types for which the and operator does not force a typecast to bool?
I can't come up with an example where this difference in behavior would cause an actual different outcome for the if-clause (after all, '' still evaluates to False), but am left with the gut feeling that there's edge cases that could be a trap.
Lastly, I'd be keen to know if anybody knows why it was implemented that way? I thought the Zen of Python encourages one way and one way only, and the + operator already seems to bethe intuitive way for string concatenation.
and never typecasts to bool. Rather, if calls bool() on the result of expressions.
An expression using and (and or, for that matter), short-circuits when it can determine that the expression will not evaluate to True or False based on the first operand, and returns the last evaluated value:
>>> 0 and 'string'
0
>>> 1 and 'string'
'string'
>>> 'string' or 10
'string'
>>> '' or 10
10
This 'side-effect' is often used in python code. Note that not does return a boolean value. See the python documentation on boolean operators for the details.
The documentation also explains what constitutes a True or False equivalent for various types, such as None, 0, '' and empty containers being False, while most everything else is equivalent to True.
For custom classes, you need to define the .__nonzero__() method (returns True or False) or a .__len__() method (returns an int, where 0 is False and everything else is True), to influence their boolean equivalent, otherwise they'll always default to True.