will call A.__nonzero__() (see Special method names documentation) and use the return value of that function. Here’s the summary:
object.__nonzero__(self)
Called to implement truth value testing and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1. When this method is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__() nor __nonzero__(), all its instances are considered true.
On the other hand,
if A is not None:
compares only the reference A with None to see whether it is the same or not.
Comparisons to singletons like Noneshould always be done with
‘is’ or ‘is not’, never the equality operators.
Also, beware of writing “if x” when you really mean “if x is not None”
— e.g. when testing whether a variable or argument that defaults to
None was set to some other value. The other value might have a type
(such as a container) that could be false in a boolean context!
回答 2
if x:#x is treated True except for all empty data types [],{},(),'',0 False, and None
A lot of functions return None if there are no appropriate results. For example, an SQLAlchemy query’s .first() method returns None if there were no rows in the result. Suppose you were selecting a value that might return 0 and need to know whether it’s actually 0 or whether the query had no results at all.
A common idiom is to give a function or method’s optional argument the default value of None, and then to test that value being None to see if it was specified. For example:
def spam(eggs=None):
if eggs is None:
eggs = retrievefromconfigfile()
compare that to:
def spam(eggs=None):
if not eggs:
eggs = retrievefromconfigfile()
In the latter, what happens if you call spam(0) or spam([])? The function would (incorrectly) detect that you hadn’t passed in a value for eggs and would compute a default value for you. That’s probably not what you want.
Or imagine a method like “return the list of transactions for a given account”. If the account does not exist, it might return None. This is different than returning an empty list (which would mean “this account exists but has not recorded transactions).
Finally, back to database stuff. There’s a big difference between NULL and an empty string. An empty string typically says “there’s a value here, and that value is nothing at all”. NULL says “this value hasn’t been entered.”
In each of those cases, you’d want to use if A is None. You’re checking for a specific value – None – not just “any value that happens to cast to False”.
The below checks if A has anything except the values False, [], None, '' and 0. It checks the value of A.
if A:
The below checks if A is a different object than None. It checks and compares the reference (memory address) of A and None.
if A is not None:
UPDATE: Further explanation
Many times the two seem to do the same thing so a lot of people use them interchangeably. The reason the two give the same results is many times by pure coincidence due to optimizations of the interpreter/compiler like interning or something else.
With those optimizations in mind, integers and strings of the same value end up using the same memory space. That probably explains why two separate strings act as if they are the same.
> a = 'test'
> b = 'test'
> a is b
True
> a == b
True
Other things don’t behave the same though..
> a = []
> b = []
> a is b
False
> a == b
True
The two lists clearly have their own memory. Surprisingly tuples behave like strings.
> a = ()
> b = ()
> a is b
True
> a == b
True
Probably this is because tuples are guaranteed to not change, thus it makes sense to reuse the same memory.
This shows that you should be extra vigilant on what comparison operator you use. Use is and == depending on what you really want to check. These things can be hard to debug since is reads like prose that we often just skim over it.
回答 5
if A: 如果A为0,False,空字符串,空列表或None,则将证明为false,这可能导致不良结果。
There are some slight differences. There are values other than None that return False, for example empty lists, or 0, so have a think about what it is you’re really testing for.
None is a special value in Python which usually designates an uninitialized variable. To test whether A does not have this particular value you use:
if A is not None
Falsey values are a special class of objects in Python (e.g. false, []). To test whether A is falsey use:
if not A
Thus, the two expressions are not the same And you’d better not treat them as synonyms.
P.S. None is also falsey, so the first expression implies the second. But the second covers other falsey values besides None. Now… if you can be sure that you can’t have other falsey values besides None in A, then you can replace the first expression with the second.
I use if A: when I’m expecting A to be some sort of collection, and I only want to execute the block if the collection isn’t empty. This allows the caller to pass any well-behaved collection, empty or not, and have it do what I expect. It also allows None and False to suppress execution of the block, which is occasionally convenient to calling code.
OTOH, if I expect A to be some completely arbitrary object but it could have been defaulted to None, then I always use if A is not None, as calling code could have deliberately passed a reference to an empty collection, empty string, or a 0-valued numeric type, or boolean False, or some class instance that happens to be false in boolean context.
And on the other other hand, if I expect A to be some more-specific thing (e.g. instance of a class I’m going to call methods of), but it could have been defaulted to None, and I consider default boolean conversion to be a property of the class I don’t mind enforcing on all subclasses, then I’ll just use if A: to save my fingers the terrible burden of typing an extra 12 characters.
I created a file called test.py and ran it on the interpreter. You may change what you want to, to test for sure how things is going on behind the scenes.
import dis
def func1():
matchesIterator = None
if matchesIterator:
print( "On if." );
def func2():
matchesIterator = None
if matchesIterator is not None:
print( "On if." );
print( "\nFunction 1" );
dis.dis(func1)
print( "\nFunction 2" );
dis.dis(func2)