5 Weird Python Tricks Everyone Should Know

(Number Four Will Blow Your Mind)



Will Weatherford

















1. Tuple Unpacking



In [1]:
tup = ('a', 'b', 'c')
a, b, c = tup

print(a)
print(b)
print(c)


a
b
c

It's actually "sequence unpacking..."


In [2]:
print('Unpacking a list...')
a_list = ['a', 'b', 'c']
a, b, c = a_list

print(a)
print(b)
print(c)


Unpacking a list...
a
b
c

In [3]:
print('Unpacking a string...')
a_string = 'abc'
a, b, c = a_string

print(a)
print(b)
print(c)


Unpacking a string...
a
b
c

Example: you expect a certain number of items from str.split()


In [4]:
def parse_request(request):
    try:
        method, uri, protocol = request.split(' ')  # expect list of length 3
        return('200 OK')

    except ValueError:
        return('400 Bad Request')

print(parse_request('GET /login.html HTTP/1.1'))
print(parse_request('GET /login.htmlHTTP/1.1'))


200 OK
400 Bad Request

2. Iterating over indexes and values


Iterating over a dictionary


In [5]:
dictionary = {'a': 0, 'b': 1, 'c': 2, 'd': 3}

Not So Good:


In [6]:
for key in dictionary:
    value = dictionary[key]
    print('{}: {}'.format(key, value))


c: 2
d: 3
b: 1
a: 0

Much Better


In [7]:
for key, value in dictionary.items():
    print('{}: {}'.format(key, value))


c: 2
d: 3
b: 1
a: 0

Iterating over a list, you need the indexes AND the items


In [8]:
a_list = [5, 2, ('x', 'y'), 7.7, 9, 'c', 10, 2, 'a']

Really Bad:


In [9]:
for index in range(len(a_list)):
    item = a_list[index]
    print('Item at index {} is {}'.format(index, item))


Item at index 0 is 5
Item at index 1 is 2
Item at index 2 is ('x', 'y')
Item at index 3 is 7.7
Item at index 4 is 9
Item at index 5 is c
Item at index 6 is 10
Item at index 7 is 2
Item at index 8 is a

Best Ever:


In [10]:
for index, item in enumerate(a_list):
    print('Item at index {} is {}'.format(index, item))


Item at index 0 is 5
Item at index 1 is 2
Item at index 2 is ('x', 'y')
Item at index 3 is 7.7
Item at index 4 is 9
Item at index 5 is c
Item at index 6 is 10
Item at index 7 is 2
Item at index 8 is a


3. Using the 'or' operator to set default



In [11]:
print(True or False)


True

In [12]:
print(False or True)


True

In [13]:
print(False or 0 or '' or [] or {} or 'Finally, something Truthy!')


Finally, something Truthy!

Example: setting the right False-y value


In [14]:
def get_a_string():
    """
    Return a useful string if you're lucky.
    Return empty string for no result.
    """
    return ''

Not so good:


In [15]:
result = get_a_string()

if not result:
    result = 'No results found.'

Better:


In [16]:
result = get_a_string() or 'No results found'

Example: setting the right TYPE of False-y value


In [17]:
def get_a_string_usually():
    """Return a string if you're lucky, return None for no result."""
    return None


value = get_a_string_usually() or ''

4. Multi-Assignment


How could you swap these values so a = 'b' and b = 'a'?


In [18]:
a = 'a'
b = 'b'

Use an intermediate, c?


In [19]:
c = a
a = b
b = c

print('a = {}'.format(a))
print('b = {}'.format(b))


a = b
b = a

But why use 3 lines when you can use only one?


In [21]:
a, b = b, a

print('a = {}'.format(a))
print('b = {}'.format(b))


a = b
b = a

Useful for swapping items in a list in on line:


In [22]:
a_list = [1, 2, 3, 4]

a_list[0], a_list[1] = a_list[1], a_list[0]

print(a_list)


[2, 1, 3, 4]

Or even reversing a Linked List in one line!


In [ ]:
def reverse_linked_list(linked_list):
    """Reverse a Linked List and return it."""
    node1 = linked_list.head
    node2 = linked_list.head.next
    
    while node2.next: 
        node2.next, node2, node1 = node1, node2.next, node2

    return node2


5. Bools are Ints are Bools


You probably know this will not work:


In [23]:
try:
    print('a string' + 2)
except TypeError:
    print('Not OK!')


Not OK!

But this will work:


In [24]:
print(' a string' * 2)


 a string a string

What about bools?


In [25]:
print(1 + False)
print(1 + True)


1
2

record scratch Whaaaaat?


In [26]:
print(10 * True)
print(10 * False)


10
0

Bools are ints are bools are ints!


In [27]:
print(True == 1)
print(False == 0)


True
True

Example: counting things based on a boolean property


In [28]:
list_of_nums = [7, 2, 0, 3, 99, 11]
insert_num = 10

insertion_index = sum(num < insert_num for num in list_of_nums)

print(insertion_index)


4

Adding some string


In [29]:
for n in range(16):
    divides_by_3 = n % 3 == 0  # Boolean statement
    divides_by_5 = n % 5 == 0  # Boolean statement

    fizz = 'Fizz' * divides_by_3  # str * bool
    buzz = 'Buzz' * divides_by_5  # str * bool

    fizzbuzz = fizz + buzz
    print(fizzbuzz or n)


FizzBuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

One line for your mind:


In [30]:
for n in range(16):
    print('Fizz' * (n % 3 == 0) + 'Buzz' * (n % 5 == 0) or n)


FizzBuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz


Thank You!