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


  • 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 list
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:

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

Σχόλια

Δημοφιλείς αναρτήσεις