Python Tips & Tricks (Part II)

Intermediate Level

HolyPython.com

The list continues with slightly more complex Python concepts, tips and tricks.

36) A beautiful counter: (itertools / count)

count method from itertools is kind of a smart counter which will automatically update itself inside the same kernel.

Check out how it counts in this mini example:

from itertools import count

index = count()
print(next(index))
print(next(index))
print(next(index))
print(next(index))
print(next(index))
print(next(index))
0
1
2
3
4
5

You can also put it inside a loop like this:

from itertools import count

c = count()

for i in range(20):
    print(next(c), end="|")
0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|

37) A different kind of counter: (collections / counter)

Counter method from Collections library will count inside your data structures in a sophisticated approach. It will return a dictionary of the results.

It’s probably the one liner approach as far as counters go.

from collections import Counter

counter = Counter(['red', 'red', 'red', 'blue', 'yellow'])
print(counter)
Counter({'red': 3, 'blue': 1, 'yellow': 1})

There is more to collections’ counter.

If you pass values as a parameter it will actually form the dictionary for you. You can even construct lists from the counter in a smart way.

Check out this example:

from collections import Counter

counter = Counter(red=1, blue=3, yellow=2)
print(counter)
print(list(counter))
print(dict(counter))
Counter({'blue': 3, 'yellow': 2, 'red': 1})
['red', 'blue', 'yellow']
{'red': 1, 'blue': 3, 'yellow': 2}

38) Extracting nested data: (itertools)

You can also flatten nested data using chain method from itertools.

import itertools

a = [[1, 2, 3], [4, 5], [6]]
for i in (itertools.chain.from_iterable(a)):
    print(i)
    
print(list(itertools.chain.from_iterable(a)))
1
2
3
4
5
6
[1, 2, 3, 4, 5, 6]

39) Unpacking: (star notation method)

You can unpack collections with 1 star notation: *

You can unpack named collections with 2 star notation: **

So, if a function takes iterables as argument then you can pass iterables with star notation to such functions.

Here are some examples:

a = [1,1,1,2,3,75,4,5,6]

print(max(*a))
75
import itertools

def lister(*x):
    for i in x:
        print(i, end="|")

a = [1,1,1,2,3,75,4,5,6]
lister(*a)
1|1|1|2|3|75|4|5|6|

40) For loop + else: (for else)

For else construction confuses even the most seasoned Python programmers sometimes. But it’s actually not that complicated at all.

Else clause is executed after for loop completes. It can be difficult to know if the loop successfully completed especially if there is a break statement in the loop. Else statement here assures us that loop ran successfully throughout.

for i in range(5):
    print(i)
else:
    print("yes")
0
1
2
3
4
yes

So it seems redundant hence the confusion but see it this way. What if there was a break statement in the loop:

for i in range(5):
    print(i)
    if i == 2:
        break
else:
    print("yes")
0
1
2

Else clause in For Else structures are completion clauses. They are confused heavily because they resemble if / else structures where else triggers a conditional behavior rather than a completion behavior. This could probably be avoided with a slight twist like calling it else finish or something, but alright. Let’s love Python with its tiny imperfection and not forget the insane benefits it brings to the table. 🙂

41) Swapping Dictionary Key & Values: (zip method)

So, how hard is reversing values and keys in a dictionary? Not hard at all, not in Python at least.

Here  are some really sleek ways to manipulate Python dictionaries that makes one fall in love with Python once again.

Here is an example:

a = {1:11, 2:22, 3:33}

b = zip(a.values(), a.keys())
c = dict(b)

print(c)
{11: 1, 22: 2, 33: 3}

Here it is in a shortened version:

a = {1:11, 2:22, 3:33}
b = dict(zip(a.values(), a.keys()))

print(c)
{11: 1, 22: 2, 33: 3}

42) Swapping Dictionary Key & Values: (dict comprehension method)

Dictionary Comprehension is a great way to achieve some dictionary operations, here is a great example:

a = {1:11, 2:22, 3:33}

b = (a.items())
c = {i:j for j,i in b}

print(c)
{11: 1, 22: 2, 33: 3}

Or the same thing in a shorter way:

a = {1:11, 2:22, 3:33}

b = {i:j for j,i in a.items()}

print(c)
{11: 1, 22: 2, 33: 3}

43) Conditional Statements: (One-Liner)

One liners are a sweet aspect of Python and can be applied to many concepts.

(Also known as ternary operator or casually if-else statement)

a=10

c = True if a**2 > 100 else False
print(c)
False

44) Lambda: (One-Liner)

Lambda is like a user-defined one line mini function. When you have a function that’s not too complicated and that can be done as a lambda it just makes it much more convenient to type it in 1 simple line. Makes you realize how much Python is practicality oriented.

Lambda syntax can take some getting used to but we have great interactive lambda exercises to help you get moving.

Lambda is very useful for defining mini functions in 1 line:

a = lambda x: x**2
print(a(5))
25

45) Returning multiple values: (return statement)

You can have a python function return multiple values.

(Not to be confused with multiple return statements which is not possible as return statement terminates a function in Python.)

def loc_id(city, county, state):
    return city, county, state

a = loc_id("LA", "OC", "FL")

print(a)
("LA", "OC", "FL")

46) Function return assignments: (One-Liner)

One liners are huge in Python, which makes the syntax so attractive and practical sometimes. You can also assign values to multiple variables in one line:

def loc_id(city, county, state):
    return city, county, state

a,b,c = loc_id("LA", "OC", "FL")

print(a)
LA

47) Anagram Checker: (sorted function)

A simple way to approach this is to use Python’s sorted function. If 2 words are anagrams they should be the same when both are sorted alphabetically.
def anagram_checker(str1, str2):
    return sorted(str1) == sorted(str2)

print(anagram_checker('vases', 'saves'))
print(anagram_checker('cola', 'coal'))
print(anagram_checker('cake', 'take'))
True
True
False

48) Anagram Checker: (Counter)

We just saw counter method. Here is a creative application of it. Counter method of collections library can also be ideal for this task.

What collections.counter does is, it will return a subclass of dict object which has each element as a key and their counts as the value.

from collections import Counter 
def anagram_checker(str1, str2): 
    return Counter(str1) == Counter(str2)

print(anagram_checker('senator', 'treason'))
print(anagram_checker('section', 'notice'))
print(anagram_checker('relation', 'oriental'))
True
False
True

49) Enumerate: (Enumerated Iterables)

When you need to add counters to an iterable, enumerate is usually the most elegant approach. It will return the iterable (say list, tuple, range, string or dictionary etc.) with the counters and returned object will be an enumerate.

str="Whatsup"
l=enumerate(str)
print(list(l))
[(0, 'W'), (1, 'h'), (2, 'a'), (3, 't'), (4, 's'), (5, 'u'), (6, 'p')]

You can also tell enumerate what number to start from:

str=["sun", "moon", "mars", "venus"]
l=enumerate(str,100)
print(list(l))
[(100, 'sun'), (101, 'moon'), (102, 'mars'), (103, 'venus')]

50) Most Frequent Value: (max and set)

You can find most frequent elements in a list with this short application:

lst = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]
print(max(set(lst), key = lst.count))
4

51) Advanced Python function parameters: (Lambda, Comprehension, Conditionals)

Python is a power house with endless capabilities and twists. Here is more one-liner approach for you.

Instead of this:

result = 0
for i in range(10):
    if i % 2 == 0:
        result += i
print(result)

You can do this:

sum(i for i in range(10) if i % 2 == 0)

52) Creating Copies: (list copy method & dict copy method)

Next trio is for copying operations. Copying can be tedious. It can cause conflicts or confusion. It’s also extremely useful and something we do day in day out. Nevertheless it can be important to know some of the intricacies. Let’s start simply with the copy method:

lst1 = ["yellow", "gray", "brown"]
lst2 = lst1.copy()

dict1 = {'Fruit': 'Melon', 'Dessert': "Ice cream"};
dict2 = dict1.copy()

53) Creating Copies: (Slicing)

You can also use slicing to create copies. You may wonder why do I even have to slice it while I can just assign the whole variable. This would create identical objects in the memory which will create problems such as changing one object can change the other one etc.

Identical objects are checked by (is – is not) operators.

Thankfully Python slice notions are super cool:

lst1 = ["yellow", "gray", "brown"]
lst2 = lst1[:]

Please note that immutable objects such as string and tuples don’t have copy methods since they will always refer to the same memory ID as long as 2 strings or 2 tuples have the same exact values.

However, copy methods create a copy by reference which means copy points to the original.

If you’d like to create a completely different copy by creating new values in the memory this can be achieved by the next trick: deepcopy

54) Copy Library: (Deepcopy)

We have seen ways to create shallow copies now let’s see a way to create a deep copy:

import copy

lst1 = ["yellow", "gray", "brown"]
lst2 = copy.deepcopy(lst1)

55) Swap Values: (One-Liner)

Python has the most straightforward approach to swapping values out there.

a=10
b=20
a,b = b,a

56) Encoding: (utf-8)

29- encoding=’utf8′

Sometimes after opening a text file in Python you’ll get an error like: 

UnicodeDecodeError: ‘charmap’ codec can’t decode

That’s because decoding of the data defaults to system defaults and it can fail if you don’t specify the code when reading the file; just add the correct codec with encoding argument (usually utf8):

open(filename, encoding=’utf8′)

57) Ascii Conversions: (ord)

Ascii is a primitive (today) encoding standard that was dominantly popular through 60s 70s and 80s.

Before Ascii there was 6 bit encoding systems which is 2^6 (64 characters) and Ascii came as an expansion revision with 7 bit code enabling mapping of 2^7 (128 characters). It was always 1byte which is 8bit but the values from 128 to 256 weren’t defined initially.

Today, Ascii usually means 8bit which equals 2^8 (256) characters mapped. 8 bit also equals 1 byte and Ascii is a 1 byte or single byte encoding system.

So, after the background story here is what ord will do. 

  • ord function will tell the integer value (0 to 256) of a character
print(ord("K"))
75

58) Ascii Conversions: (chr)

Today, UTF-8 became the global standard encoding for data traveling on the internet. That stands for 8-bit Unicode Transformation Format.

  • chr function will tell the character of an integer value (0 to 256) based on Ascii mapping.
print(chr(111))
'o'

59) Identity Operators: (is & not is)

is – is not are identity operators and they will tell if objects are exactly the same object or not.

a=["Antarctica"]
b=["Antarctica"]
    
c=a
print(a is b)
print(a is c)
print(a is not b)
False
True
True

60) with open as: (work on open file)

You can use with open as to work on files in a more practical way. (This eliminates the need to open and close files in multiple steps).

Code would go something like:

with open('research.csv') as f:
    data = csv.reader(f)
    for i in data:
        print(i)

61) Bin for bits: (And a little bit of computer history)

So how did it all start? From one-upping the oil candle technology to the age of Netflix, Tinder, Instagram, face recognition, self-driving vehicles, going to Moon, going to Mars, global computer programming literacy movement, decentralized AI, autonomous drones… And even maybe soon Singularity!

As you are reading these letters they are literally traveling as ones and zeros possibly all the way accross Atlantic Ocean via fiber-optic cables to your home. Next 3 tips are for people who might be interested in bytes and bits which is a system representing these ones and zeros. 

This might sound trivial but it’s really not that trivial even for high level programmers or any human in that sense. This is where it all started as far as computers go. I think as a coder everyone should at least take a couple of minutes to understand “bits” just as much as it makes sense for a carpenter to understand what a tree is or something like that.

Also, if you watched imitation games, an incredible true story about Alan Turing the man who founded the first modern computer (Turing Machine – 1936) which was followed by first digital computers such as ABC computer (without CPU hence not programmable) and ENIAC computer (considered to be the first functional digital computer) in late 30s and 40s. These all had a common feature: vacuum tubes. These are like light bulbs which go on and off, on representing 1 and off representing 0. Add enough of these values together and you have digital data. Hurray!

Also ComputerHope has a really awesome article about Computer Development History that’s worth reading.

So, if that story doesn’t impress you I don’t know what will but one bit represents 1 value of 2 possibilities, 0 or 1. This whole idea literally is the foundation of all computation and electronics we have and use today.

1 byte on the other hand represents 8 bits which equals 2^8 = 256 possibilities.

Python function bin will tell you the bit equivalent of an integer (or amount of possibilities):

print(bin(256))
print(bin(5))
print(bin(1000000))
print(bin(65))
0b100000000
0b101
0b11110100001001000000
0b1000001

62) Bit Length: (How many bits do you need?)

Note that integer 4 actually represents 5 values including 0 hence 3 bits are needed.

00
01
10
11
100 –> 4
101 –> 5

a=4
b=a.bit_length()
print(b)

c=9999
d=c.bit_length()
print(d)
3
14

63) to_bytes: (Numbers to Bytes)

Finally, to_bytes method of integers will show the byte representation of an integer in hexadecimal base.

Hexadecimal base represents 16 values or 4 bits hence 2 hexadecimal values equal 1 byte or 8 bits. Hex is used in computer science since it much more convenient than 10 base numbers system when dealing with bits. 1byte can be represented in 2 hexadecimal values. Also conveniently, each memory address is 4bits which equals 1 nibble.

1 nibble = 1 hex = 4 bits = 2^4 values

1 byte = 2 nibbles = 8 bits = 2^8 values

a=15
b=a.to_bytes(2, byteorder="big")
print(b)

c=888
d=c.to_bytes(2, byteorder="big")
print(d)
b'\x00\x0f'
b'\x00\xde'

x00 means Null in hexadecimal base. Showing unused bytes. Remember we chose 2 bytes, 1 would be enough.

0-9 are used for values 0 to 9 and
a-f are used for values 10 to 15
making 16 values total.

That’s why 15 shows as x00\x0f (0000_1111) –> 0 for 0 and f for 15
200 shows as x00\xc8 (1010_1000) –> c is 11 and 8 is 8

Only second bytes are used (which is 2 nibbles which are 4 bits each)
Byteorder signifies byte representation in descending or ascending order respectively “big” or “little”

64) Vim: (coolest code editor)

Do you wanna feel like the hacker in Swordfish? Regardless of your answer VIM is addictively cool and useful. It lets you code Python from Command Prompt and will work even when there is no system installed in a highly restricted computer.

VIM is super fast, crash-free and powerful. But there is more than that, VIM is also highly customizable with many extension and plugin opportunities.

You can see all the tips regarding installation and usage of Vim in this Vim Tutorial we prepared to get you started. It’s open-source and free (or rather charityware).

To Start Running VIM:

  • Just type vim filename.py from a command prompt such as Anaconda Prompt.
  • If you see a new window filename at the top and “–INSERT–” at the bottom bar, you’ve successfully launched VIM.
  • Now, VIM has 2 main modes: Editor and Command mode.
    • Editor Mode: You can switch to editor mode by pressing “i
    • Command Mode: You can switch to command mode by pressing “Esc
  • While in Editor Mode you can type your code or anything
  • To save and/or quit you need to switch to command mode and type appropriate commands. Commands are written starting with colon “:
    • Here are some examples:
      • :q >>> Quits without saving
      • :w >>> Saves without quiting
      • :qw >>> Saves and quits

Note: Please note that you should install Vim as an Administrator otherwise Command Prompt will fail to recognize Vim. Vim installer options exist for most OS out there such as MacOS, Linux, Ubuntu, Windows 64Bit or 32 Bit.

65) Random Numbers: (import random)

Python’s default random library can be very handy when you need to create random numbers.

randint for an integer between lower and upper limits:

import random

a=random.randint(33, 333)
print(a)
263

randrange(start, stop, steps), will also give a value in the range but you can also specify a step.

import random

a=random.randrange(0, 50, 8)
print(a)
40

random() will return a float value between 0 and 1. This can also be used as a random percentage.

You can explore other methods of the random library by using dir(random) and help(random)

import random

a=random.random()
print(a)
0.7730286038945102

66) Opening a Web Page: (webbrowser library)

Here is an easy recipe to open web pages from within your Python terminal or code.

import webbrowser

f=r'https://www.google.com'
webbrowser.open(f)

67) Deque: (Sequences with double ends)

A deque or (Double ended queue) is a two ended Python object with which you can carry out certain operations from both ends.

It can be used when a collection is needed to be operated at both ends and can provide efficiency and simplicity over traditional data structures such as lists.

It also belongs to the standard collections library in Python.

Let’s check out some of the basic operations of deque:

import collections
a = collections.deque()

a.append(100)
a.appendleft(4)
print(a)

a.extend([200, 300, 400])
a.extendleft([3, 2, 1])
print(a)

a.pop()
a.popleft()
print(a)

a.rotate(3)
print(a)

a.rotate(-1)
print(a)
deque([4, 100])
deque([1, 2, 3, 4, 100, 200, 300, 400])
deque([2, 3, 4, 100, 200, 300])
deque([100, 200, 300, 2, 3, 4])
deque([200, 300, 2, 3, 4, 100])

68: Greatest common divisor: (math library)

Python’s standard math library has great methods that make almost any basic math calculation a breeze. Here is .gcd() method showing the greatest common divisor:

import math

print(math.gcd(65,780))
print(math.gcd(6,40))
print(math.gcd(12,40))
65
2
4

69) Play Audio: (os library)

Python’s native os library is also capable of playing audio files. If you have a default player like VLC it will automatically play the audio in that program.

This could easily be used to create scripts like a super cool personal alarm, sedentary warning, reminder, motivation programs etc.

import os
f="Track01.mp3"
os.system(f)

70) Jupyter Notebook (Shortcuts & Line Magic)

Jupyter Notebook can be fantastic for learning, teaching and experimenting. Here are some ways to make it even more fantastic: shortcuts.

Only the most common shortcuts are shared here.

Command Mode
Enter enter edit mode
Shift Enter run section, skip to next section
Ctrl Enter run section
↑ , ↓ or k , j selects cell above or below
a , b inserts cell above or below
x , c , v cut , copy , paste cell
Shift v paste cell above
z undo last cell deletion
dd delete selected cell
Shift m merge cell below
Ctrl s saves
Edit Mode
Tab code completion or indent
Shift Tab tooltip
Ctrl ] indent
Ctrl [ deindent
Ctrl a selects all
Ctrl z undo
Ctrl Shift z redo
Jupyter Notebook Magic
%matplotlib inline allows graphic output within notebook
%%timeit Tab to measure the performance of processes (explained in #78 also)
%cls clears the screen
%cd to change the directory
%paste pastes from the clipboard
%source displays the source code of an object

You can really step up your Jupyter game by taking a quick look at these shortcuts!

Recommended Posts