11thHeaven
11thHeaven

Reputation: 379

'if' not followed by conditional statement

I'm going through Zed's "Learn Python The Hard Way" and I'm on ex49. I'm quite confused by the following code he gives:

def peek(word_list):
    if word_list: # this gives me trouble
        word = word_list[0]
        return word[0]
    else:
        return None

The condition of the if statement is giving me trouble, as commented. I'm not sure what this means as word_list is an object, not a conditional statement. How can word_list, just by itself, follow if?

Upvotes: 5

Views: 1126

Answers (7)

Sнаđошƒаӽ
Sнаđошƒаӽ

Reputation: 17552

Take a look at this docs page for Truth Value Testing in python. You should get clear idea about your situation after reading this. Here is the relevant part for easy access.

5.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.

All other values are considered true — so objects of many types are always true.

Read the first sentence (bolded) again, and note the bolded parts in the fourth rule. This relates to your question.

So, according to the 4th rule, if your word_list is empty, the condition evaluates to False, otherwise it evaluates to True.


I know you trust in the docs, but here is a code snippet to actually test the truth values for yourself. (I know it is needless to do something like this, but I am always tempted to see things with my own eyes)

def test_truth_value(arg):
    # ANY object can be evaluated for truth or false in python
    if arg: # or to be more verbose "if arg is True"
        print("'{}' is True".format(arg))
    else:
        print("'{}' is False".format(arg))

class dummy_length_zero():
    def __len__(self):
        return 0
    def __str__(self):
        return 'instance of class: "dummy_length_zero"'

class dummy_bool_False():
    def __bool__(self):
        return False
    def __str__(self):
        return 'instance of class: "dummy_bool_False"'

obj_dummy_0 = dummy_length_zero()
obj_dummy_false = dummy_bool_False()

args = [None, False, 0, 0.0, 0j, '', (), [], {}, obj_dummy_0, obj_dummy_false]

for arg in args:
    test_truth_value(arg)

And lastly, to test that last statement so objects of many types are always true, just remove the implementation of __len__() or __bool__() method from dummy_length_zero or dummy_bool_False class respectively, and check for truth.

Upvotes: 3

0xcurb
0xcurb

Reputation: 126

In Python, every expression can be evaluated to a boolean value (i.e. either True or False).

The following, basic, expressions evaluate to False

  1. The keyword False (obviously!)
  2. The keyword None
  3. The number 0 (0, 0.0 ... )
  4. empty sequence (tuple, list, string)
  5. empty mapping (dictionary)

All other expressions evaluate to True.

So, what the if statement does is evaluating the expression that follows the if keyword to either True or False, then act accordingly.

So in your specific example, if word_list matches any of the above cases it will be considered False, otherwise, it will be considered True.

[#] reference

Upvotes: 2

Mad Physicist
Mad Physicist

Reputation: 114230

In python, everything has an implicit boolean value. Putting any object in an if statement directly is equivalent (but more Pythonic than) doing if bool(word_list):. None, empty sequences, empty sets, empty dicts, 0, False, 0.0 all evaluate to False. Most other objects evaluate to True. That makes if word_list: the most Pythonic way of ensuring that the list is not None or empty before accessing the first element. The long way of expressing the same thing would be if word_list is not None and len(word_list) > 0:.

Upvotes: 2

zondo
zondo

Reputation: 20336

What is required for an if block is just something that can be evaluated either to True or to False. A conditional evaluates directly to one of those, but there are other objects that can be converted. To see what any given object is, you can use bool:

>>> mylist = []
>>> bool(mylist)
False
>>> mylist = [4, 3, 6]
>>> bool(mylist)
True

You see, a list is False if it is empty, but True otherwise. Therefore, the if word_list: block will be evaluated if word_list is nonempty. Strings also are False if they are empty, but True otherwise. Same thing with tuples, dictionaries, sets. With numbers, 0 and 0.0 are False, but any other number is True. A fairly common argument to give to indicate to the function to come up with its own value is None which evaluates to False, so the if not mylist: block will be executed if mylist is empty or if mylist is None. (It would also be executed if mylist is 0, (), {}, etc.; but it's unlikely that mylist would be given those)

Upvotes: 5

gtlambert
gtlambert

Reputation: 11961

The if statement applies the built-in bool() function to the expression which follows. In your case, the code-block inside the if statement only runs if bool(word_list) is True.

Different objects in Python evaluate to either True or False in a Boolean context. These objects are considered to be 'Truthy' or 'Falsy'. For example:

In [180]: bool('abc')
Out[180]: True

In [181]: bool('')
Out[181]: False

In [182]: bool([1, 2, 4])
Out[182]: True

In [183]: bool([])
Out[183]: False

In [184]: bool(None)
Out[184]: False

The above are examples of the fact that:

  • strings of length >= 1 are Truthy.
  • empty strings are Falsy.
  • lists of length >= 1 are Truthy.
  • empty lists are Falsy.
  • None is Falsy.

So: if word_list will evaluate to True if it is a non-empty list. However, if it is an empty list or None it will evaluate to False.

Upvotes: 7

ᴀʀᴍᴀɴ
ᴀʀᴍᴀɴ

Reputation: 4528

word_list is a list and when you use it for an if statement condition you check word_list is empty or not :

word_list = []
bool(word_list)   #  False
if word_list :
    print "I'm not empty"  # would not printed
word_list = ['a']
bool(word_list)  # True
if word_list :
    print word_list[0] # 'a'

as Mad Physicist said even None elements in a list means that it's not empty:

word_list = [None]
bool(word_list) # True

Upvotes: 5

krato
krato

Reputation: 1246

He is checking if word_list is empty or not. If a list is empty and it is used in a conditional statement, it is evaluated to False. Otherwise, it is evaluated to True.

word_list = ['some value']
if word_list:
    # list is not empty do some stuff
    print "I WILL PRINT"


word_list = []
if word_list:
    # list is empty
    print "I WILL NOT PRINT"

In the above code, only the first snippet will print.

See the following reference: https://docs.python.org/2/library/stdtypes.html#truth-value-testing

Upvotes: 6

Related Questions