Python Tricks

A short Python code snippet

Posted by Chaoli Zhang on August 24, 2017

This is a short summary of Python tips that I learnt from Python developer Dan Bader. In particular, his Youtube playlists on Python training are inspiring. You should definitely check those out if you also want to become a developer.

Use enumerate

cities = ['Amsterdam', 'Beijing', 'Tokyo', 'Singapore']

for index, city in enumerate(cities):
    print (index, city)

print dict(enumerate(cities))

For dictionary print out

a = dict(c=3,b=65, h=9)

for index, value in a.iteritems():
    print (index,'-->',value)

Use zip to print 2 lists

x_list = [1,2,3]
y_list = [10,25,34]

# bad way
for i in range(len(x_list)):
    print (x_list[i],y_list[i])

# good way
for x,y in zip(x_list,y_list):
    print (x,y)

Variable swap

x = 1
y = -10

x, y = y, x

Dictionary get function

ages = dict(Mary=20,Anna=18)
# bad way
if 'viona' in ages:
    print ages['viona']
else:
    age = 'unknown'
    print 'Age unknown'

# good way

age = ages.get('Dick','Unknown')

Dictionary and zip

name = ['a','u','c','f']
value = [1,2,3,4]

dic = dict(zip(name,value))

Args and kwargs

point 1

def arrow(**kwargs):
    return ('[{x},{y},{z}]'.format(**kwargs))

arrow(**dict(y=2,x=3,z=4))

arrow(**dict(y=2,x=3,z=4,u=7,a=2,c=12))

##print_vector(a) # errors
#a = [2,3,4]
#print_vector(*a)

point 2

class GCs_Catalogue(object):
    def __init__(self, h=0.7, omega_m=0.3, omega_lambda=0.7):
        self.h = h
        self.omega_m = omega_m
        self.omega_lambda = omega_lambda

class GCs_simputfile(GCs_Catalogue):
    def __init__(self,emax=10, emin=2, *args, **kwargs):
        super(self.__class__,self).__init__(*args, **kwargs)
        self.emax = emax
        self.emin = emin

parent = GCs_Catalogue(h=0.7, omega_m=0.3, omega_lambda=0.7)

child = GCs_simputfile(h=0.7, omega_m=0.3, omega_lambda=0.7,
                       emax=15, emin=0.2)

Moral of today’s learning: Base class needs to have object in its parentheses. The child class needs to have Base class in its parentheses if you want to use *args and **kwargs, then pass it to both init and super super in py2.7 needs to have child class name (can be replaced by self.class) when call child class, simply input all the arguments like above.

is vs ==

a = [1,2,3]
b = a

c = list(a)

print a
print b
print '---For b---'
print b is a
print b == a

print '---For c : NOTE: c is not the same as a---'
print c is a
print c == a

# from wechat python
a = list(range(10))

# odd number
a[1::2]

b = a # duplicate i.e. b is c
c = a[:] # this copied version i.e. c is not a

dunder: str and repr

point 1

class Car():
    """
    Python class to distinguish str and repr
    """
    def __init__(self, color, mile):
        self.color = color
        self.mile = mile

a = Car('red',1000)

print 'A object information, which tells nothing:',a

class Car():
    """
    Python class to distinguish str and repr
    """
    def __init__(self, color, mile):
        self.color = color
        self.mile = mile

    def __str__(self):
        return 'a {self.color} car'.format(self=self)

a = Car('red',1000)

print 'A object information printed from __str__:',a

point 2

class Car():
    """
    Python class to distinguish str and repr
    """
    def __init__(self, color, mile):
        self.color = color
        self.mile = mile

    def __str__(self):
        return '__str__ for Car'

    def __repr__(self):
        return '__repr__ for Car'

a = Car('red',1000)

print "print a outputs:", a

print "Directly call a in terminal get repr"

point 3

import datetime

today = datetime.date.today()

print 'str(today):',str(today)
print 'repr(today):', repr(today)

str ==> easy to read, for human convenience repr ==> unambiguous

point 3

class Car():
    """
    Python class to distinguish str and repr
    """
    def __init__(self, color='red', mile=1000):
        self.color = color
        self.mile = mile

    def __repr__(self):

#        res1 = '[{self.color},{self.mile}]'.format(self=self)
        result = '{self.__class__.__name__}(color={self.color},mile={self.mile})'.format(self=self)
        return result

a = Car('blue',7777)

@classmethod @staticmethod and regular methods

class Myclass:
    def method(self):
        return 'instance method called', self

    @classmethod
    def classmethod_A1(cls):
        return 'class method called',cls

    @staticmethod
    def staticmethod_A1():
        return 'staticmethod called'


obj = Myclass()

Definitions

class Joe:
    pass

j = Joe()

Joe - a user-defined type. j is an instance of the class Joe.
In other words, it's an object and its type is Joe.

Not unlike the ambiguity between "class" and "type",
"instance" is synonymous to "object".
Think of it this way: objects are instances of types.
So, "42 is an instance of the type int" is equivalent to
"42 is an int object".


The arguments in __init__ are called attribute, whereas the function
defined in class are called method or instance method.

sympy

from sympy import *
import numpy as np

s=symbols('s')
x=symbols('x')
S_low = symbols('S_low')
S_up = symbols('S_up')
break_point=symbols('break_point')

integrate(s**4,(s,S_low,S_up))

integrate(s**4,(s,S_low,break_point))
integrate(-s**2+200,(s,break_point,S_up))


integrate(-s**2+200,(s,S_low,S_up))

integrate(-s**2+200,(s,5.0,6.0))

piece wise function

import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
import seaborn as sns
sns.set_style('dark')

# function one
def func1(s): return s**4
# function two
def func2(s): return -s**2+200
# define the piecewise function combing func1 and func2
def piecewise_func(S,break_point):
    S = np.asarray(S)
    y = np.zeros(S.shape)
    noramlization_factor = 1
#    noramlization_factor = func1(break_point)/func2(break_point)
    y += (S <= break_point)*(func1(S))
    y += (S > break_point)*(func2(S)*noramlization_factor)
    return y


# define your array and breaking point for the piecewise function
break_point = 4.0
S_low = 1
S_up  = 7
S = np.linspace(S_low,S_up,1000)*break_point/4
#
S_low_lim = 2.0
S_up_lim  = 6.0
S_lim = np.linspace(S_low_lim,S_up_lim,1000)*break_point/4


# verify the function:

plt.figure()
plt.plot(S,piecewise_func(S,break_point),'-',lw=3,color='blue')
plt.fill_between(S_lim, piecewise_func(S_lim,break_point),
                 facecolor='purple', alpha=0.4)
plt.axvline(break_point,ls='-.',c='red')
plt.axhline(0,ls='-',lw=2,c='black')
plt.xlabel('X')
plt.ylabel('Piecewise Y value')
plt.show()

open text file

with statement will open the file, and write the content and automatically save/close the file.

with open('text.txt','w') as f:
    f.write('Hello Anna')

Aboive code is equivalent to follwing:

f = open('text.txt','w')

try:
    f.write('Hello Anna')
finally:
    f.close()

point 2 context managers

class ManagedFile(object):
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        self.file = open(self.name,'w')
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
      if self.file:
          self.file.close()


with ManagedFile('text.txt') as f:
    f.write('Hello anna \n')
    f.write('Hello anna2 \n')
    f.write('Hello annad \nn')

# equivalence.

mf = ManagedFile('text.txt')

with mf as f:
    f.write('Hello anna')

one line condition

gender='male'

if gender == 'male':
    text = 'boy'
else:
    text = 'girl'

text = 'boy' if gender=='male' else 'girl'

Unicode introduction

Unicode topic

Computer transfers data through internet through characters, and it was originally based on ASCII chararcher encoding. ASCII is sufficient for most English specking countries, but it does not support any other language other than English, and therefore can not be used in European countries.

Unicode encoding solves the problem by integrate all the languange in the world, and can be efficiently communicate between countries.

UTF-8 is most popular Unicode format used on Internet.

Example, Chinese character 好, in unicode is 576D. In UTF-8, its encoding is therefore E5A5BD.

Extract files in directory

import glob
import itertools as it

files = glob.glob('*.py')

# grab multiple files
def grab_file_of_types(real_path=False,*patterns):
    file_names_result = it.chain.from_iterable(glob.glob(pattern) for pattern in patterns)

    if real_path:
        file_names = [os.path.realpath(f) for f in file_names_result]
    else:
        file_names = [f for f in file_names_result]

    return file_names

grab_file_of_types(True,'*.py')

Merge two EPS figures

import os
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from PIL import Image

##############################################################################
# main code
##############################################################################


I1 = Image.open('I1.EPS')
I2 = Image.open('I2.EPS')


new_image = Image.blend(I1, I2, 0.8)
new_image.save('Combined.EPS', 'EPS')

plt.figure()
plt.imshow(new_image)

plt.xlabel('x')
plt.ylabel('y')
plt.title(' ')
# plt.grid(True)
plt.savefig('Combined.EPS', transparent=False, dpi=80, bbox_inches="tight")
plt.show()