Important Python tips to me

Vu Quang Hoa
4 min readAug 8, 2016

--

Debugging

This is the most important thing to learn and understand deeply a particular language, a developer must understand how the code works, how the library is implemented by using debugging tool to inspect function call, variables and logic.

>>> def hanoi_population(list_populations):
import pdb; pdb.set_trace()
big_city_populations = [population for population in list_populations if population > 1000]
return round(sum(big_city_populations), 2)
>>> hanoi_population([10000, 20000, 100])
> <ipython-input-7-1e8b6f117387>(3)hanoi_population()
-> big_city_populations = [population for population in list_populations if population > 1000]
(Pdb) h
Documented commands (type help <topic>):
========================================EOF bt cont enable jump pp run unta c continue exit l q s untilalias cl d h list quit step upargs clear debug help n r tbreak wb commands disable ignore next restart u whatisbreak condition down j p return unalias whereMiscellaneous help topics:==========================exec pdbUndocumented commands:======================retval rv

Show all commands by press h or help after (Pdb)

  • One favourite command for debugging is DIR command (show all attributes and methods related to the object)
>>> numbers = [1, 2, 3, 4, 1, 2]
>>> dir(numbers)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

*args and **kwargs

Those arguments lists are not common in your code but they are used a lot in library and framework

1. *args

  • arguments list (ex: 1, ‘hello Joe’, object, 1.23)
  • How to get content of *args: accessing by index (ex: args[0], args[1])
>>> def print_my_arguments(*args):
for arg in args:
print arg
>>> print_my_arguments(1, 'Hello Joe', 3)
1
Hello Joe
3

2. **kwargs

  • keyworded arugments(ex: message=’Hello Joe’, is_developer=True, member=member_object)
  • How to get content of **kwargs: kwargs works like a dict (ex: kwargs.get(‘message’) or kwargs[‘message’]
>>> def print_my_keyworded_arguments(**kwargs):
for key, value in kwargs.items():
print key, ":", value
>>> print_my_keyworded_arguments(message='Hello Joe', age=27)
message : Hello Joe
age : 27

3. Using both *args and **kwargs

  • Mostly *args and **kwargs are used for function decorators
  • Monkey patching (using to modify some code in runtime) is also a good way to use this
  • When you want to have an enough flexibility for your function arguments (both arguments list and keyworded arguments)

Dictionary

This is my favourite of trick, dictionary is powerful and easy to use

  • If there are too many if/else clauses => using dictionary
  • If there should be a default value for a key => use setdefault
>>> def count_duplicates(numbers):
result = {}
for number in numbers:
if number not in result: # No need for if here
result[key] = 0
result[number] += 1
return result
We can rewrite the function with setdefault>>> def count_duplicates(numbers):
result = {}
for number in numbers:
result.setdefault(number, 0) # this is clearer
result[number] += 1
return result
  • Dictionary to list: items()
>>> a_dict = {'a': 1, 'b': 2}
>>> a_dict.items()
[('a', 1), ('b', 2)]
  • List to dictionary
>>> a_list = [['a', 1], ['b', 2], ['c', 3]]
>>> dict(a_list)
{'a': 1, 'b': 2, 'c': 3}
  • Inverting dictionary
>>> a_dict = {'a': 1, 'b': 2, 'c': 3}>>> invert_a_dict = {v: k for k, v in a_dict.iteritems()}
>>> invert_a_dict
{1: 'a', 2: 'b', 3: 'c'}
  • Avoid KeyError on dictionary => Using defaultdict of collections
>>> a_dict = {'a': 1}
>>> a_dict['b']
KeyError: 'b'
>>> from collections import defaultdict
>>> a_default_dict = defaultdict(list)
>>> a_default_dict['a']
[]
>>> from collections import defaultdict
>>> a_default_dict

Function

  • Any time you find yourself writing the same/similar code repeatedly, you’re working too hard => use template function
  • Wrapper function (and decorators) is one of the best magic tricks
>>> def update_phone_number(member, phone):
member.phone = phone
member.save()
This is a simple function that update the phone number for a member. However, I realise that
* I want to check if them member has permission to change phone or not
* and I also want to keep the permission function out of my method above.
@permission
def update_phone_number(member, phone):
member.phone = phone
member.save()
def permission(func):
def validate(*args, **kwargs):
if not member.has_permission()
raise Exception('Not permitted to change phone')
return func(*args, **kwargs)
return validate

UnitTest

  • Write unit test for success/fail/exception will ensure your program working correctly as expected.
  • Ex: Save the content to a file name test_python.py, and run python test_python.py on terminal.
import unittest

def crease_one(x):
return x + 1

class MyTest(unittest.TestCase):
def test(self):
self.assertEqual(increase_one(3), 4)
if __name__ == '__main__':
unittest.main()

Collections

  • This is an useful Python package that we might use a lot
  • defaultdict/deque/namedtuple/counter/OrderedDict
>>> from collections import Counter
>>> numbers = [1, 2, 3, 4, 1, 2]
>>> counter = Counter(number for number in numbers)
>>> print counter
Counter({1: 2, 2: 2, 3: 1, 4: 1})

--

--

Vu Quang Hoa
Vu Quang Hoa

Written by Vu Quang Hoa

Developing is automating processes

No responses yet