- Using builtin function issubclass()
- Using a buffer while manipulating files
- Reloading a module
- Logging using logging module
- Making a variable global: global keyword
- Creating random objects of subclasses of a superclass
- Removing duplicate items from lists
- Implementing Caesar Cipher in Python
- High-level file operations using shutil module
- Regular Assignment, Shallow copy & Deep Copy
The builtin function issubclass(subClass, superClass) returns True if the class subClass is a subclass of the class superClass, else it returns False.
>>> help(issubclass) Help on built-in function issubclass in module builtins: issubclass(...) issubclass(C, B) -> bool Return whether class C is a subclass (i.e., a derived class) of class B. When using a tuple as the second argument issubclass(X, (A, B, ...)), is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.). ### EXAMPLE ### >>> class Person(object): pass >>> class Man(Person): pass >>> class Woman(Person): pass >>> issubclass(Man, Person) True >>> issubclass(Man, object) True >>> issubclass(Woman, Man) False
If you are uncertain about the exact parent class of a subclass, you can insert all the likely classes in the form of a tuple. The issubclass() function will return True if the class specified is a subclass of either of the specified classes.
>>> issubclass( Man, (Person, Woman) ) True >>> issubclass( Person, (Man, Woman) ) False
Keep in mind that all builtin-classes, data types, user-defined classes inherit from the class called object.
A buffer stores a chunk of data from the Operating System's file stream until it is consumed, at which point more data is brought into the buffer. The reason that is good practice to use buffers is that interacting with the raw stream might have high latency i.e. considerable time is taken to fetch data from it and also to write to it. Let's take an example.
Let's say you want to read 100 characters from a file every 2 minutes over a network. Instead of trying to read from the raw file stream every 2 minutes, it is better to load a portion of the file into a buffer in memory, and then consume it when the time is right. Then, next portion of the file will be loaded in the buffer and so on.
The following code snippet reads a file containing 196 bytes, with a buffer of 20 bytes, and writes to a file, 20 bytes at a time.
# A practical example will have large-scale values of buffer and file size. buffersize = 20 # maximum number of bytes to be read in one instance inputFile = open('fileToBeReadFrom.txt', 'r') outputFile = open('fileToBeWrittenInto.txt', 'a') # opening a file in append mode; creates a file if it doesn't exist buffer = inputFile.read(buffersize) # buffer contains data till the specified cursor position # Writing the contents of a buffer another file 20 bytes at a time counter = 0 # a counter variable for us to see the instalments of 20 bytes while len(buffer): counter = counter + 1 outputFile.write(buffer) print( str(counter) + " ") buffer = inputFile.read(buffersize) # next set of 20 bytes from the input file outputFile.close() inputFile.close()
To learn more about buffers, check out this link.
There are occasions when you have changed the code of a module, and you want the changes to reflect without having to relaunch the interpreter or restart the server. Python doesn't support this by default. However, the reload() function of importlib standard library helps you to do just that.
# CONTENTS OF foo.py def spam(): print("SPAM!") # A SESSION IN THE INTERACTIVE INTERPRETER >>> import foo >>> foo.spam() SPAM! # CHANGED CONTENTS OF foo.py def spam(): print("SPAM! SPAM!") # SAME SESSION IN THE INTERACTIVE INTERPRETER >>> foo.spam() SPAM! # Changes have not reflected yet. >>> import importlib >>> importlib.reload(foo) <module 'foo' from 'complete_path_to_foo.py'> >>> foo.spam() SPAM! SPAM! #### Common Practice to Handle Frequently Modified Modules #### import moduleOne import moduleTwo from importlib import reload reload(moduleOne) reload(moduleTwo) from moduleOne import * from moduleTwo import *
The standard library logging helps you to log events of different severities to a file or the standard output in interpreter. This is particularly helpful in large applications where you would like to record events as they occur for future reference. Expand the following snippet for an example of logging. To know more about the
>>> import logging >>> logging.basicConfig(level = 10, format = '%(asctime)s %(levelname)s %(message)s') >>> logging.debug('A debugging message here.') 2017-02-18 04:40:38,420 DEBUG A debugging message here. >>> logging.info('An informative message here.') 2017-02-18 04:40:41,274 INFO An informative message here. >>> logging.warning('A warning message here.') 2017-02-18 04:40:42,773 WARNING A warning message here.
There will be instances where you are declaring an object inside a confined piece of code, and you will need the object outside it as well. You can use the global keyword for this.
## BEFORE >>> def storeMyName(): name = "Ethan" >>> storeMyName() >>> name Traceback (most recent call last): # Traceback Info name NameError: name 'name' is not defined ## AFTER >>> def storeMyName(): global name name = "Ethan" >>> storeMyName() >>> name 'Ethan'
Using the random module and Generators, we can have Python make random objects of subclasses of a superclass.
>>> import random >>> class Crop(object): def sow(self): print("Sowing...") def irrigate(self): print("Irrigating...") def harvest(self): print("Harvesting...") >>> class Wheat(Crop): pass >>> class Corn(Crop): pass >>> class Tomato(Crop): pass >>> def cropGenerator(numberOfInstancesToCreate): crops = Crop.__subclasses__() for number in range(numberOfInstancesToCreate): yield random.choice(crops)() >>> cropGeneratorObject = cropGenerator(5) >>> for cropObject in cropGeneratorObject: print(cropObject) <__main__.Corn object at 0x02E7E950> <__main__.Corn object at 0x02E65BB0> <__main__.Wheat object at 0x02B09EB0> <__main__.Tomato object at 0x02E65BB0> <__main__.Corn object at 0x02B09EB0>
A simple way to remove duplicate items from a list is to cast it to a set, and then back to a list using the constructors of builtin set and list classes.
>>> aList = [1, 2, 3, 1, 2, 3, 4, 5] >>> list( set(aList) ) [1, 2, 3, 4, 5]
Julius Caesar was a Roman dictator who came up with a clever way of passing confidential information to his generals without having to worry about it falling into the wrong hands. He shifted each letter in the message by a fixed shift value i.e. if the shift value was 3, a became d, f became i and so on. He would leave the numbers and other characters untouched. His generals would only need the shift value to decode their emperor's message. Later on, this cryptography technique came to be known as Caesar Cipher.
You can implement Caesar Cipher in Python using the builtin ord(), chr() functions, a for loop, a couple of if-else constructs.
The ord() function returns the Unicode value of the character supplied to it. It is inverse of builtin chr() function which returns the character in the Unicode character set, denoted by the number provided to it.
Expand the following code snippet for the script. You can run it online here.
## Implement a Caesar Cipher that shifts all the letters in a given message by an given number of places. ## Example of Caesar Cipher: 'Hello' becomes 'Khoor' when characters are shifted by 3 places. 'Can you read this?' becomes 'Kiv gwc zmil bpqa?' when characters are shifted by 8 places. 'Can you read this?' becomes 'Zxk vlr obxa qefp?' when characters are shifted by 3 places in the backwards direction. ## THOUGHT PROCESS: Prompt the user for the message to encrypted and the number of places each character should be shifted by in the encrypted message -> initialize the encrypted message to an empty string -> begin a for loop to process each character in the entered message -> branch the control into three code blocks, to process uppercase, lowercase and non-alphabet characters separately -> for uppercase and lowercase characters, calculate the position of the character by subtracting Unicode value of the first letter i.e. 'a' or 'A' from the Unicode value of the character -> calculate its new positon by adding the shift value and obtaining the remainder on dividing by 26 -> convert the new position into character form using the builtin chr() function -> append the new character to the encrypted message -> for non-alphabet characters, append them to the encrypted message without shifting -> output the encrypted message. ## INPUT message = input("Enter the message you want to encrypt: ") shiftValue = int(input("Enter the places you want the characters to be shifted by: ")) ## PSEUDO CODE / ALGORITHM: # Initialize the newMessage to an empty string # Using a for loop, process each letter in the following way: # Determine whether it's lowercase or uppercase using an if statement, proceed accordingly: # using ord(), determine its position in the alphabet(0-25) # calculate its new offset by adding the shiftValue and getting the remainder on dividing by 26(for taking care of shiftValue > 26) # convert the position to character by using chr() # append the new character to the newMessage # If the character is not an alphabet, append it to newMessage as it is, without shifting. newMessage = "" for character in message: if character >= "a" and character <= "z": position = ord(character) - ord("a") position = (position + shiftValue) % 26 newCharacter = chr(position + ord("a")) newMessage = newMessage + newCharacter elif character >= "A" and character <= "Z": position = ord(character) - ord("A") position = (position + shiftValue) % 26 newCharacter = chr(position + ord("A")) newMessage = newMessage + newCharacter else: newMessage = newMessage + character ## OUTPUTTING RESULT print("\nHere is the encypted message: \n\n" + newMessage)
The standard library module shutil facilitates basic operations on files and directories. You can copy files and directories, move them, remove them, pretty much everything you would like to do with them. Following is a list of frequently used functions of the shutil module:
shutil.copy(source,destination) # Creates a copy of file at source path to destination path. shutil.copymode(source,destination) # Sets file permissions of destination file/directory to that of source file/directory. shutil.copystat(source, destination) # Copies permissions, statistics such as last access time, last modification time, flags of source file/directory to destination file/directory shutil.copy2(source, destination) # Copies the file data, permissions, metadata such as file creation & modification time etc. of source file/directory to destination file/directory shutil.disk_usage(path) # Returns a three-element tuple denoting total, use and free space of given path, in bytes. shutil.move(source, destination) # Moves the file/directory at source path to destination path. Renames the file if executed in the same directory. shutil.copytree(source, destination) # Copies the entire directory at source path to destination path by creating a new directory specified in destination argument. shutil.rmtree(path) # Removes the entire directory at given path.
There are three ways to copy objects in Python: assignment, shallow copy & deep copy.
- Regular assignment points the new variable towards the original object. Let's use the builtin id() function prove this. The id() function returns the object's memory address.
- Shallow copy
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
- Deep Copy
objOne = [1, 2, 3] objTwo = [4, 5, 6] objThree = [objOne, objTwo] objFour = objThree print( id(objThree) == id(objFour) ) # True as objThree & objFour are the same object print( id(objThree) == id(objFour) ) # True as objThree & objFour are the same object
import copy objFour = copy.copy(objThree) print( id(objThree) == id(objFour) ) # False as objFour is a new object print( id(objThree) == id(objFour) ) # True as objFour is the same object as objThree
objFour = copy.deepcopy(objThree) print( id(objThree) == id(objFour) ) # False as objFour is a new object print( id(objThree) == id(objFour) ) # False as objFour is a new object
See also: 50+ Know-How(s) Every Pythonista Must Know