Become awesome in Python!!
Hello and welcome to my series of Python tips and tricks. I am going to list every single advice that I find interesting so that I can create a reference list.
The advice will make our Python code
1. Refactor (Extract) complex if clauses to variables to improve readibility.
e.g.
can become the more readable:
2. Refactor (Extract) variables into classes to improve testability.
e.g.
Lets create our class:
Lets call our class
So now it is very easy to test our code
3. Refactor classes with a lot of properties by Splitting Classes.
Create a parent class and subclass.
Use @Property decorator
4. Exit Loops fast
e.g.
5. Open and Write Files uniformly for Python 2 and Python 3
We add 'wb' type to indicate 'Binary mode', otherwise in Python 3 opening a file defaults to reading or writing UTF-8 strings.
6. Use get method to access dictionary values
e.g. In this way we can get a default value in case dictionary key doesn't exist
7. Reverse a Sequence
You can use sequence slicing [start:end:stride] with stride -1
e.g.
Be aware though that this will not work as expected for UTF-8 strings
8. Prefer Generators for Large Comprehensions
as they have minimum memory footprint
e.g.
9. Use enumerate() if you need index in looping or begin counting from specific index:
e.g.
10. Use zip() to process iterators in parallel.
e.g.
If you need to iterate to the longest list then use: zip_longest
In Python 3 zip() is a generator function. In Python 2 it creates a new list of tuples. For python 2 we can use izip() to be more efficient.
11. Python can return Multiple Values
This gives extreme freedom and flexibility to return a Value and a Status of execution.
for example following code returns result of division as long the status of execution. The returned is a tuple:
12. Return Generators instead of Lists
Using the keyword 'yield' we can return Generators instead of Lists so that we can maximize performance and memory consumption
The transformation of code from Lists to Generators is easy:
e.g.
13. User repr for Classes for easier debugging
14. Use namedtuples
Instead of
you can use namedtuples and make it much more readable
References
1. https://www.youtube.com/watch?v=D_6ybDcU5gc
2. https://www.youtube.com/watch?v=wf-BqAjZb8M
The advice will make our Python code
- Beautiful (Beautiful is always good -- also it makes it easy maintainable)
- Fast (Fast in processing, less in memory)
- Pythonic (A lot of us come with different programming background, To master a language we have to go its way along)
- Testable
1. Refactor (Extract) complex if clauses to variables to improve readibility.
e.g.
if str.lower().endswith('r'):
print ('{0} ends with r'.format(str)
can become the more readable:
str_ends_with_r = str.lower().endswith('r')
if str_ends_with_r:
print ('{0} ends with r'.format(str)
2. Refactor (Extract) variables into classes to improve testability.
e.g.
Lets create our class:
class EndsWithR(object):
def __init__(self,str):
self.str = str
self.r = str.lower().endswith('r')
self.result = str.lower().endswith('r')
def __bool__(self): # __nonzero__
return self.result
Lets call our class
str_ends_with_r = EndsWitR(str)
if str_ends_with_r:
print ('{0} ends with r'.format(str)
So now it is very easy to test our code
test = EndsWithR('some Example string that ends with r')
assert test
assert test.r
3. Refactor classes with a lot of properties by Splitting Classes.
Create a parent class and subclass.
Use @Property decorator
4. Exit Loops fast
e.g.
def search_fast(haystack, needle):
for item in haystack:
if item == needle:
return True
return False
def search_slow(haystack, needle):
return_value = False
for item in haystack:
if item == needle:
return_value = True
return return_value
5. Open and Write Files uniformly for Python 2 and Python 3
We add 'wb' type to indicate 'Binary mode', otherwise in Python 3 opening a file defaults to reading or writing UTF-8 strings.
with open(‘/tmp/random.bin’, ‘wb’) as f:
f.write(os.urandom(10))
6. Use get method to access dictionary values
e.g. In this way we can get a default value in case dictionary key doesn't exist
dict = {'Name': 'Zabra', 'Age': 7} print "Value : %s" % dict.get('Age') print "Value : %s" % dict.get('Education', "Never")
Value : 7
Value : Never
7. Reverse a Sequence
You can use sequence slicing [start:end:stride] with stride -1
e.g.
x = b’mongoose’
y = x[::-1]
print(y)
b’esoognom’
Be aware though that this will not work as expected for UTF-8 strings
8. Prefer Generators for Large Comprehensions
as they have minimum memory footprint
e.g.
it = (len(x) for x in open(‘/tmp/my_file.txt’))
print(it)
<generator object <genexpr> at 0x102b81480>
9. Use enumerate() if you need index in looping or begin counting from specific index:
e.g.
for idx, flavor in enumerate(flavor_list, 2):
print(‘%d: %s’ % (idx, flavor))
10. Use zip() to process iterators in parallel.
e.g.
for name, count in zip(names, letters):
if count > max_letters:
longest_name = name
max_letters = count
Actually zip creates a tuple for the smallest listIf you need to iterate to the longest list then use: zip_longest
In Python 3 zip() is a generator function. In Python 2 it creates a new list of tuples. For python 2 we can use izip() to be more efficient.
11. Python can return Multiple Values
This gives extreme freedom and flexibility to return a Value and a Status of execution.
for example following code returns result of division as long the status of execution. The returned is a tuple:
def divide(a, b):
try:
return True, a / b
except ZeroDivisionError:
return False, None
# And we can use them as following
success, result = divide(x, y)
if not success:
print(‘Invalid inputs’)
12. Return Generators instead of Lists
Using the keyword 'yield' we can return Generators instead of Lists so that we can maximize performance and memory consumption
The transformation of code from Lists to Generators is easy:
e.g.
def index_words(text):
result = []
if text:
result.append(0)
for index, letter in enumerate(text):
if letter == ‘ ‘:
result.append(index + 1)
return result
# The same code Can Become
def index_words_iter(text):
if text:
yield 0
for index, letter in enumerate(text):
if letter == ‘ ‘:
yield index + 1
13. User repr for Classes for easier debugging
def __repr__(self):
return '{0}'.format(self.__class__.__name__)
14. Use namedtuples
Instead of
p = (170, 0.5, 0.6)
you can use namedtuples and make it much more readable
from collections import namedtuple
Color = namedtuple('Color',['hue', 'saturation', 'luminosity'])
p = Color(170, 0.5, 0.6)
if p.saturation >0.5:
print ('That is bright')
References
1. https://www.youtube.com/watch?v=D_6ybDcU5gc
2. https://www.youtube.com/watch?v=wf-BqAjZb8M
Σχόλια