Python @ DjangoSpin

50+ Tips & Tricks for Python Developers

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon
Reading Time: 31 minutes

Page #8


Storing keyword arguments dynamically

We can utilize the builtin dictionary of keyword arguments of each object (stored in __dict__ attribute of the object) to store the keyword arguments supplied to it during its creation.

>>> class Person(object):
    def __init__(self, **kwargs):
        for argument in kwargs.keys():
            self.__setattr__(argument, kwargs[argument])
 
             
>>> ethan = Person(name = 'Ethan', age = 23, height = 170)
>>> ethan.__dict__
{'age': 23, 'name': 'Ethan', 'height': 170}

FTP using ftplib module

Python's standard library module ftplib enables users to carry out operations on a remote system using File Transfer Protocol. You can transfer files, fetch directory listing, create directories etc. on the connected system. Expand the following snippet for a few chosen operations you can perform, you can view the complete list of functionality that the ftplib offers by visiting its documentation

## CREATING AN FTP CONNECTION
>>> import ftplib
>>> ftpConnection = ftplib.FTP()
>>> ftpConnection.connect('ftp.yourDomainHere.com')		
>>> ftpConnection.login('yourUsername', 'yourPassword')		

# The connect() method returns a welcome message from FTP server with status code 220 if connection successful. If unsuccessful, it raises socket.gaierror saying '[Errno 11001] getaddrinfo failed'.
# The login() method returns a success message with status code 230 if credentials are correct. If unsuccessful, it raises ftplib.error_perm saying '530 Login incorrect' 

# Alternatively, you can provide this information to the constructor of the FTP class, in order to reduce method calls.
>>> ftpConnection3 = ftplib.FTP('ftp.yourDomainHere.com', 'yourUsername', 'yourPassword')




## GETTING PRESENT WORKING DIRECTORY
>>> ftpConnection.pwd()



## RETRIEVING DIRECTORY LISTING
>>> ftpConnection.dir()
# The dir() method gives long form of constituents of the current directory with information such as file permissions, created by, creation date & time etc.

# Alternatively, you can use th nlst() method.
>>> ftpConnection.nlst()
# The nlst() method returns a list of directories & files in the current directory. To view contents of a subdirectory, enter the name of subdirectory as an argument e.g. ftpConnection.nlst('subDirectoryOne').

# Alternatively, you can use the retrlines() method. The retrlines() method lists directories with either 'NLST' or 'LIST' as its argument. 
>>> ftpConnection.retrlines('LIST')         # output similar to dir()
>>> ftpConnection.retrlines('NLST')         # output similar to nlst()




## CHANGING CURRENT WORKING DIRECTORY
>>> ftpConnection.cwd('subDirectoryOne')

# To move up a directory, enter two dots in the arguments.
>>> ftpConnection.cwd('..')



## DELETING A FILE
>>> ftpConnection.delete('fileName')



## CREATING A DIRECTORY
>>> ftpConnection.mkd('subDirectoryOneUnderSubDirectoryOne')



## REMOVING A DIRECTORY
ftpConnection.rmd('subDirectoryOneUnderSubDirectoryOne')

# The above works fine if the directory is empty. If it is not empty, you will receive an error saying the directory is not empty. In such a case, use the following code snippet to remove a non-empty directory.




## EMPTYING A NON-EMPTY DIRECTORY

# Navigate to the directory containing the non-empty directory, then call the following function.
def removeNonEmptyDirectory():
	files = ftpConnection.nlst()
	
	for file in files:
		try:										# If file is not a directory
			ftpConnection.delete(file)
		except:										# If file is a directory 
			try:									# if directory is empty
				ftpConnection.rmd(file)
			except:									# if directory is not empty
				ftpConnection.cwd(file)
				removeNonEmptyDirectory()
				ftpConnection.cwd('..')
				ftpConnection.rmd(file)
				
# Now that the directory is empty, call the rmd() method on it to delete it.



## RENAMING A FILE/DIRECTORY
>>> ftpConnection.rename('subDirectoryOne', 'subDirectoryTwo')




## DOWNLOADING A FILE
# Navigate to directory on remote system where you file is placed. Then, execute the following to download the file.
>>> ftpConnection.retrbinary('RETR fileNameOnRemoteSystem.txt', open(r'fullPathToNewFileOnLocalSystemIncludingNewFileName', 'wb'))




## UPLOADING A FILE
# Navigate to directory where you want to place the file. Then execute the following.
>>> ftpConnection.storbinary('STOR fileNameOnRemoteSystem', open(r'fullPathToFileOnLocalSystemIncludingFileName', 'rb'))




## UPLOADING A FOLDER
# Contents of dirOne
|subDirOne
|--subDirOneFileOne.txt
|--subDirOneFileTwo.txt
|subDirTwo
|fileOne.txt
|fileTwo.txt


directoryToMove = r'pathToDirectoryOnLocalSystem'

def uploadDirectory(pathOfDirectoryToMove):
	import os
    files = os.listdir(pathOfDirectoryToMove)				# ['fileOne.txt', 'fileTwo.txt', 'subDirOne', 'subDirTwo']
    os.chdir(pathOfDirectoryToMove)											# changes current working directory to pathTo_dirOne
	
    for file in files:
		# if file is not a directory, then transfer it.
        if os.path.isfile(pathOfDirectoryToMove + r'\{}'.format(file)):		
            fileHandler = open(file, 'rb')
            ftpConnection.storbinary('STOR {}'.format(file), fileHandler)
            fileHandler.close()			
		# if file is a directory, make a directory by the same name on the remote system, access it, and call uploadDirectory() again to process its contents.
        elif os.path.isdir(pathOfDirectoryToMove + r'\{}'.format(file)):
            ftpConnection.mkd(file)
            ftpConnection.cwd(file)
            uploadDirectory(pathOfDirectoryToMove + r'\{}'.format(file))
			
    ftpConnection.cwd('..')
    os.chdir('..')											# go back to parent directory
	
uploadDirectory(directoryToMove) 





## EXECUTING FTP COMMANDS
# The sendcmd() method allows you to execute FTP commands and receive a response string from the server. A list of valid FTP commands can be viewed from https://en.wikipedia.org/wiki/List_of_FTP_commands or by executing ftpConnection.sendcmd('HELP'). A couple of usage examples:
>>> ftpConnection.sendcmd('PWD')
>>> ftpConnection.sendcmd('CDUP')
>>> ftpConnection.sendcmd('QUIT')





## CLOSING AN FTP CONNECTION
>>> ftpConnection.close()

Variable Swapping

Python makes it really easy to swap values of two or more variables. Example:

>>> x = 10
>>> y = 20
>>> x, y = y, x
>>> y
10
>>> x
20



>>> x = 1
>>> y = 2
>>> z = 3
>>> z, y, x = x, y, z
>>> z
1
>>> y
2
>>> x
3

The way this works is that the expression on the right hand side creates a new tuple. This is one of the ways that tuples can be created. The tuple thus formed gets unpacked into variables on the left hand side.


pass keyword

Code-blocks in Python are separated by indents and not by curly braces ( {} ). In cases where you don't want to populate the body of a function or a class, you cannot leave it completely empty. In fact, Python won't allow you to leave it fully vacant. For this purpose, Python has the pass keyword. This keyword is convenient to draft a high-level design of a complicated solution. The user can code on the functionality of the function of the later, he can emphasize solely on the structure of the program.

def functionalityOne():
    pass
 
def functionalityTwo():
    pass

Installing external modules using pip

Python comes with many useful modules out-of-the-box. In addition to these modules, there is a large library of third-party modules which Python developers have distributed for fellow developers to use. These modules are listed in Python Package Index (PyPI), also known as the Cheese Shop, with a reference to Monty Python's Flying Circus, the TV show after which the language was named. These external modules come in wheel files (.whl) or executables (.exe). Wheel files can be installed using pip.

pip is Python's package management system, and is shipped with the installation in versions 2.7.9+ & 3.4+. This decision of including a package manager with the standard installation was welcome graciously by the Python community, as it spared them the hassles of setting up a package manager themselves. This puts Python in a bracket of programming languages which ship their package manager with standard installations, such as Haskell, Ruby, Node.js. The word pip is a recursive acronym that is interpreted to mean either "Pip installs Python" or "Pip installs Packages".

For Python versions 2 - 2.7.8 & 3 - 3.3, you will have to save this page as get-pip.py in your system, and then run it using command-prompt (in Administrator mode) i.e. $ python get-pip.py, ensuring you are in the current directory.

Before pip, a builtin Python module called easy_install was used to install third-party modules. In fact, in versions mentioned above, it is still used to install third-party modules.

# Installing a .whl using pip
# Command Prompt/Terminal
$ pip install file_name.whl

# Installing an external module directly using pip. The mentioned module must be present in the Cheese Shop.
$ pip install cx_Oracle


# In case you get a .exe file from PyPI instead of a .whl file, you can execute the .exe files directly without using Python.
If pip is not working, it might be due to the fact that it is not in your path environment variable. One workaround for this issue is to run pip as a script by using the -m flag of python command line.

$ python -m pip install cx_Oracle

There are chances that you might receive an error while installing these modules. This could either be due to the 32/64 bit operating system issue, or the language version incompatibility or some other reason. In these events, Google the error, since it is very likely that the same error could have been encountered by fellow Python developers.


Lambda Expressions (Anonymous functions)

Lambda expressions(a.k.a. lambda forms) in Python are used to create anonymous functions. In a nutshell, these functions do not have the def keyword, instead have a lambda keyword, take any number of arguments and return a single value in the form of an expression.

# Syntax of a lambda expression:
lambda [arg1 [,arg2,.....argn]]:expression
 
# Example
>>> myLambdaExpr = lambda x: x + 2
>>> myLambdaExpr(5)
7
 
>>> myLambdaExpr
<function <lambda> at 0x02D21978>
 
>>> def myNormalFunc():
    print()
     
>>> myNormalFunc
<function myNormalFunc at 0x02D219C0>
 
# Example
>>> add = lambda num1, num2: num1 + num2
>>> add(3,4)
7

Lambda expressions may not necessarily enhance readability, but they help in making the code compact, as they replace elementary functions which return a single expression.

In actuality, lambda is the basic form of a function definition. Any function, in principle, is a lambda assigned to a variable. The expression "lambda arguments: expression" yields a function object. The unnamed object behaves like a function object defined with

def (arguments):
return expression

Keep in mind that:

  • Lambda expressions cannot contain statements.
  • Lambda expressions have their own local namespace and cannot access variables other than those in their parameter list and those in the global namespace.
  • Lambda expression are extremely useful in GUI Programming. They serve as callback functions.
  • In a broad sense, anything you can do with a lambdas, you can achieve the same with named functions, or lists. However, it’s up to you to choose whether to use lambdas or not. You could decide based on the readability of your code.
  • l = lambda x: x + 2 is the same as def l(x): return x + 2

Using filter()

The builtin filter class does what you expect it to. It filters out the elements which do not match a criteria and creates an iterator out of the elements which match it. The constructor of the filter class accepts a function and an iterable object. The function either returns True or False for an input, and the input which gives a True value gets populated in the iterator returned by the filter class.

>>> help(filter)
...
class filter(object)
 |  filter(function or None, iterable) --> filter object
 |  
 |  Return an iterator yielding those items of iterable for which function(item)
 |  is true. If function is None, return the items that are true.
...

Say you wanted to filter out the multiples of 7 lying in the first 30 numbers. You can achieve this using a for loop as well, but the filter class makes for cleaner code.

>>> def multiplesOfSeven(number):
	return number % 7 == 0

>>> aFilterObject = filter( multiplesOfSeven, range(31) )
>>> for element in aFilterObject:
	print(element)

0
7
14
21
28




>>> aFilterObject = filter( lambda x: x % 7 == 0, range(30) )
>>> next(aFilterObject)
0
>>> next(aFilterObject)
7




>>> for element in filter( lambda x: x % 7 == 0, range(31) ):
	print(element)

0
7
14
21
28

If the function provided is None, it creates an iterator only out of true elements of the supplied iterable object i.e. elements which are not 0 and are not empty strings ( '' ).

>>> for number in range(5): print(number)

0
1
2
3
4

>>> aFilterObject = filter( None, range(5) )
>>> next(aFilterObject)
1									# Not 0

Here's another example where the filter class extracts words beginning with the letter 'a' out of a list of words.

>>> listOfWords = ['aardvark', 'apple', 'ball', 'cat']
>>> wordsBeginningWithA = filter( lambda x: x.startswith('a'), listOfWords )
>>> for word in wordsBeginningWithA:
	print(word)

aardvark
apple

The filter class, like map class, is designed to be used in conjunction with Lambda Expressions for tighter code. Lambda Expressions are used to create anonymous functions. In a nutshell, these functions do not have the def keyword, instead have a lambda keyword, take any number of arguments and return a single value in the form of an expression. Click here to know more about Lambda Expressions.

Like with the map class, you can cast the returned iterator into a list using the builtin list() function. However, as the documentation says, rather than converting an iterator into a list, it is better to just use a list comprehension especially when lambda expressions are being used to generate the resultant elements.

>>> multiplesOfSeven = list( filter( lambda x: x % 7 == 0, range(30) ) )
>>> multiplesOfSeven
[0, 7, 14, 21, 28]

In Python 2, filter is a builtin function instead of a class. Just like map, its usage is same as in Python 3, except for the fact that in Python 2, it returns a list instead of an iterator.


Using reduce()

There are times when you have a sequence of values and you want to reduce it to a single value. The reduce() function in module functools applies a function which operates on 2 elements at a time, to the elements of an iterable object, going from left to right.

>>> import functools
>>> help(functools.reduce)
Help on built-in function reduce in module _functools:

reduce(...)
    reduce(function, sequence[, initial]) -> value
    
    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.

Say you have a list of numbers [1, 2, 3, 4, 5] and an anonymous function lambda x, y: x + y. It is a lambda expression which takes two arguments and returns their sum. The reduce() function functools.reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]) will evaluate ((((1 + 2) + 3) + 4) + 5) and return a single value 15.

>>> import functools
>>> functools.reduce( lambda x, y: x + y, [1, 2, 3, 4, 5] )
15

>>> functools.reduce( lambda x, y: x + y, range(6) )
15

# OTHER EXAMPLES
# reducing a list of numbers into their product.
>>> def product(a, b):
	return a * b

>>> functools.reduce( product, [1, 2, 3, 4, 5] )
120


# reducing a bunch of strings into a resultant string
>>> def concatenate(a, b):
	return a + b

>>> functools.reduce(concatenate, ['Hello', ' ', 'there!'])
'Hello there!'



# finding the largest element in an iterable object
>>> functools.reduce( lambda x, y: x if ( x > y ) else y, [10,5,15, 22,14] )
22

In order to verify the order in which the elements of the iterable object are passed to the specified function, let's make our function verbose.

>>> import functools
>>> def addTwoNumbers(x, y):
	print("x = {}; y = {}; x + y = {}".format(x, y, x + y))
	return x + y

>>> functools.reduce( addTwoNumbers, [1, 2, 3, 4, 5] )
x = 1; y = 2; x + y = 3
x = 3; y = 3; x + y = 6
x = 6; y = 4; x + y = 10
x = 10; y = 5; x + y = 15
15

Just like the map class, the reduce function is designed to be used in conjunction with Lambda Expressions for tighter code. Lambda Expressions are used to create anonymous functions. In a nutshell, these functions do not have the def keyword, instead have a lambda keyword, take any number of arguments and return a single value in the form of an expression. Click here to know more about Lambda Expressions.

There is an optional argument to the reduce() function, the initialisation value. This becomes the first argument to the specified function, and the first element of the iterable object becomes the second argument to the function.

>>> def addTwoNumbers(x, y):
	print("x = {}; y = {}; x + y = {}".format(x, y, x + y))
	return x + y

>>> functools.reduce( addTwoNumbers, [1, 2, 3, 4, 5] , 20)
x = 20; y = 1; x + y = 21
x = 21; y = 2; x + y = 23
x = 23; y = 3; x + y = 26
x = 26; y = 4; x + y = 30
x = 30; y = 5; x + y = 35
35

In the event that the iterable object is empty, the reduce() function returns this value without trying out the function. If there is no initialisation value provided and the iterable object is empty, Python raises a TypeError 'TypeError: reduce() of empty sequence with no initial value'.

In Python 2, reduce() is a builtin function instead of a function in module functools. The usage is the same as in Python 3. It is worth noting that the Documentation advises against the usage of reduce() function. As it says, an explicit for loop is more readable.


Enumerating with enumerate()

It is sometimes needed to have an index counter for elements of an iterable object. Python's builtin enumerate class enables us to do just this. The constructor of builtin enumerate class accepts an iterable object and returns an iterator of tuples in the form (index, value).

>>> help(enumerate)
...
class enumerate(object)
 |  enumerate(iterable[, start]) -> iterator for index, value of iterable
 |  
 |  Return an enumerate object.  iterable must be another object that supports
 |  iteration.  The enumerate object yields pairs containing a count (from
 |  start, which defaults to zero) and a value yielded by the iterable argument.
 |  enumerate is useful for obtaining an indexed list:
 |      (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
...

### EXAMPLE ###
>>> listOne = [ 'apple', 'ball', 'cat', 'dog' ]
>>> enumeratedObject = enumerate(listOne)
>>> next(enumeratedObject)
(0, 'apple')
>>> next(enumeratedObject)
(1, 'ball')



# Using a for loop to iterate over the iterator of tuples
>>> listOne = [ 'apple', 'ball', 'cat', 'dog' ]
>>> for pair in enumerate(listOne):
	print(pair)

	
(0, 'apple')
(1, 'ball')
(2, 'cat')
(3, 'dog')



# Unpacking the tuples
>>> listOne = [ 'apple', 'ball', 'cat', 'dog' ]
>>> for index, element in enumerate(listOne):
	print(index, ": ", element)

	
0 :  apple
1 :  ball
2 :  cat
3 :  dog

By default, the indexes start from 0. To alter this, Python provides us with an optional second argument, which tells the enumerate class to begin indexes from the specified value.

>>> listOne = [ 'apple', 'ball', 'cat', 'dog' ]
>>> for index, element in enumerate(listOne, start = 1):
	print(index, ": ", element)

	
1 :  apple
2 :  ball
3 :  cat
4 :  dog

Using builtin function isinstance()

The builtin function isinstance(obj, cls) returns True if obj is an instance of class cls, else returns False.

>>> help(isinstance)
Help on built-in function isinstance in module builtins:

isinstance(...)
    isinstance(object, class-or-type-or-tuple) -> bool
    
    Return whether an object is an instance of a class or of a subclass thereof.
    With a type as second argument, return whether that is the object's type.
    The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
    isinstance(x, A) or isinstance(x, B) or ... (etc.).

	
### EXAMPLES ###
>>> if isinstance(4, int):
	print("4 is an integer!")
	
4 is an integer!


>>> isinstance(4, str)
False
>>> isinstance(4, int)
True


>>> class Man(object): pass
>>> ethan = Man()
>>> isinstance(ethan, Man)
True	

If you are uncertain about the exact parent class of the object, you can insert all the likely classes in the form of a tuple. The isinstance() function will return True if the object belongs to either of the specified classes.

>>> isinstance(4, (str, int) )
True

Keep in mind that all builtin-classes, data types, user-defined classes inherit from the class called object.


See also: 50+ Know-How(s) Every Pythonista Must Know


Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon

Leave a Reply