Master PEP
Style Guide
https://www.python.org/dev/peps/pep-0008/
Readability counts
- Basic Elements
1.Types
2.Relational Operators
3.While loop - String,Collections,for-loop
- Modularity
- Object and Types
- Class
- Define new Class
- Instance Methods
- Adding to Classes
- self argument
- Initializers
- Contrast with constructors
- Collaborating Classes
- Polymorphism / Interfaces and Implementations / Duck Typing
- Inheritance
- Files IO and resource managemnt
- Iterable and Iterators
a / b = return floating point
a // b = return only the integral part ( no rounding off )
- int
int as constructor
```
int(3.5) = 3 ( rounding is always close to 0)
int("234") = 243
```
-
float
3.125 3e8 = 3 X 10^8 1.616e-35 = 1.616 X 10^(-35)float as constructor
float("2.234") float("nan") -
NoneType
a = None
a is None == true
-
bool ( Constructor Usages)
a = True
a = FalseAny integer or float with 0 value is Falsy else Truthy bool(0) --> False bool(0.0) --> False bool("") --> False bool([]) --> False Any String or collection if empty is considered falsy , else truthy bool("Some value") --> True bool(["one","two"]) --> True bool("False") --> True ( as it has value important to keep note)
| Relational Operator | Relevance |
|---|---|
| == | value equality / equivalence |
| != | value inequality / inequivalence |
| < | less-than |
| > | greater-than |
| <= | less-than or equal |
| >= | greater-than or equal |
while {boolean evaluated expression}:
counter = 5
while counter != 0:
print(counter)
counter-=1
Using break
while True:
print("press a number which is multiple of 5 to break and come out from the infinite loop")
data_in = input()
if int(data_in) % 5 == 0:
break
- str
- list
- dictionary
- for-loop
Key Note : String are immutable in python too. So to capitalize a variable you have to catch the return.
String supports slicing as they implement the sequence protocol
name = 'satadru'
capitalized_name = name.capitalize()
print(name) --> satadru
print(capitalized_name) --> Satadru
- Multiline Strings:
```
"""
A multiline string
Starting and ending with triple quotes
Single Or Double
"""
```
( \n is universtal to all platforms)
\r for windows not needed
If multiple \ used , python supports raw string which doesnt support any escape.
Begin with a r.With this kind of initialization the variable automatically added the .
```
variable_path = r'D:\Program~1\'
```
- str.join() much more memory eficient than +
- the joined object acts as separator
';'.join(["fname","mname","lname"])
results in : fname;mname,lname
- We can use the '' empty string to perform normal concatenations
- partition() returns tuple
"unforgetable".parition('forget')
results in : ('un','forget','able')
- Positional parameters to format
"My first name is {0} , and last name is {1}".format('Satadru','Basu')
- Keyword parameters
"My first name is {fname} , and last name is {lname}".format(fname="Satadru",lname="Basu")
- Evaluate Expressions and embed in the string , including calling a function
f'Current time is {datetime.datetime.now().isoformat()}.'
- Keyword parameters
"My first name is {fname} , and last name is {lname}".format(fname="Satadru",lname="Basu")
-
slicedList = list[sliceStart:sliceEnd]
-
slicedList = list[1:]
-
slicedList = list[:5]
-
slicedList = list[:]
-
list.reverse() AND list.sort()
-
use copy module for deep copy of nested collections.
-
remove an element from list
del list[3]
- insert an element from list
del list[3]
my_dict = {}
- dest_dict.update(sourceDict)
- looping through dict : dict.items()
for key in colors:
print(f"{key} => {colors[key]}")
for key,value in colors.items():
print(f"{key} => {value}")
- "red" in colors_dict
- "blue" not in colors_dict
- del colors_dict['blue']
inventory = {"car":"ciaz","phone":"nokia","laptop":"mac","salary":00,"comments":"dont take these seriously"}
for item in inventory:
print(item,inventory[item])
mylist = [11,22,33,44,55]
for item in enumerate(mylist):
print(item)
- Using tuple unpackin on the go
mylist = [11,22,33,44,55]
for i,v in enumerate(mylist):
print(f"index = {i} , value = {v}")
t = ("Pune",1.234,5)
- Immutable sequences of arb objects once initialized can't be change
- tuples can be added or multipled :
t + ("London",1.00,3)
t * 8 - tuples can be nested - good for multi dimensional matrix
t = ((101,102),(201,202),(301,302),(401,402))
t[2][2] - tuple complex initializations
(a,(b,(c,d))) = (4,(3,(2,1)))
- tuple swap
a,b = b,a
- tuple constructor
tuple([11,22,33,44])
- Check for containment
5 in (3,5,6,7)
- generally used as counters
- range(stop) OR range(start,stop) OR range(start,stop,step)
range(5) = 0 to 4
list(range(5,10)) = [5, 6, 7, 8, 9]
list(range(1,21,3)) = [1, 4, 7, 10, 13, 16, 19]
- Set is unordered and Initialization like dict has {}
python_coders = {'satbasu','goku',krillin'}
- Note {} empty initializes a dict so need to use a set constructor for empty ones.
java_coders = set()
shell_coders = set(["goku","gohan","trunks","satbasu"])
java_coders.add("satbasu")
java_coders.update(["goku","gohan"])
-
Set Algebras
java_coders.intersection(shell_coders) java_coders.intersection(shell_coders) == java_coders.intersection(python_coders) java_coders.difference(shell_coders)
If we import a python file without functions , just during import statement it executes the entire File.Hence the need of functions.
_feature_ is called dunder : double underscore
Source code files called modules - A module is executed once on first import.
Python Arguments - sys.argv ( parameters)
Making programs executable using (_name_ == _main_ )
docstring used in help(Object name)
Ideal not to print but return some value.
def cube(x):
return x*x*x
dunder name : Special variable allows to detect whether a module is run as a script or imported into another module.
print(_name_) behaviour :
| When | Output |
|---|---|
| import sample | sample |
| import sample | No output as sample was already imported and printed the module name on first time |
| python sample.py | _main_ |
So to ensure flow of code when a python script is executed from shell python <scriptname.py>
if __name__ == '__main__':
fetch_workds()
Refer to samply.py for reference
if __name__ == '__main__':
## run this program with sample.py https://raw.githubusercontent.com/satadrubasu/Unix-PythonReference/master/resources/sample.txt
## From SHELL : python sample.py
## From REPL : import sample
## From REPL : main('https://raw.githubusercontent.com/satadrubasu/Unix-PythonReference/master/resources/sample.txt')
main(sys.argv[1])
-
The first line of a block ( function / module / class ) to have comments in triple double quotes
-
Tool like Sphinx to create HTML documentation from python docstrings
-
see help in interpreter :
from sample import *
help(fetch_words)
""" def fetch_words(url): Fetchs list of words , read from a passed URL. Args: url: The URL of a UTF-8 text Document Returns: List of strings containing the words from the document. """
- Locate Python Using PATH : #!/usr/bin/env python3
-
Python Object Model ( same Garbage collection as Java)
-
Named references to objects
Mutable Objects r = [11,22,33] s = r # s is a new name pointing to same objet as r s[1] = 17 # change to s = change to r s is r == True -
Value equality vs identity equality
p = [11,22] q = [11,22] p == q ( Value Equality ) True p is q ( id equality ) False -
Passing args and returning values
-
Pythons type sysmtem
-
scope to limit name access
-
Evertything is an Object
Even int is an immutable object so changing value , keeps the old value floating till GC
id() --> returns a unique int identifier constant for the lifetime of an value object.
Mutable Objects passes a reference and hence the original object also changes in the following example. m will reflect the new value added. Note since we are using the append()
m = [11,5,12]
def modify(k):
k.append(33)
print("k = ", k)
modify(m)
m = [11,5,12,33]
Note the following variant of the above example where the variable is altogether assigned to a new list. By the core concept , the k is now pointing to a new value object reference.While the calling object m points to the original list.This results in m continue to point to its old data.
m = [11,5,12]
def modify(k):
k = [44,55,66,77]
print("k = ", k)
modify(m)
m = [11,5,12]
m = [11,5,12]
def function_my(k):
return k
p = function_my(k)
p is m
True
positional arguments and keyword arguments ( with keys)
city - is a keyword argument and is optional and non -positional.
Always use immutable default values , else when its called without the pramas , it initializes once during def and keeps working on it.
def labelled_msg(msg,separator='-'):
seperator_line = separator * len(msg)
print(seperator_line)
print(msg)
print(seperator_line)
labelled_msg("Positional Parameter")
labelled_msg("Positional Parameter",separator="#")
No Type declarations are needed in python.
| command | response |
|---|---|
| type(sample) | class 'module' |
| type(32) | class 'int' |
| type(32) | class 'int' |
| dir(sample) | all attributes inclusive of the module and what we defined |
| type(sample.print_items) | all attributes inclusive of the module and what we defined |
- Scopes in python do not correspond to source code blocks by indentation
- global -- refers to outer namespace of the same variable name and not the local.
| Scope order | SHort | Scope | Description |
|---|---|---|---|
| Narrowest | L | Local | Inside the current function |
| Narrower | E | Enclosing | Inside Enclosing functions |
| Broader | B | Global | Top level of module |
| Boradest | G | Built-in | In the special built in modules |
- All is public : No public / private / protected
- Constructor forawrds parameter to matching initializers.
- Class Invariants can be used by init() to ensure some rules are followed while creating an object ,else throw ValueError.
Consider airtravel.py having the following class definition of Flight.
class Flight:
pass
> f = Flight()
> type(f) will return <class 'airtravel.Flight'>
- _init_() is an initializer of already created object and not a constructor.Constructor forwards parameters to initializers.
- Note how self._number create a new instance attribute with _number.
- init should not return anything but only create/modify self.(objects)
- A function and object attribute are both objects so attribute name and functionname MUST not be same.
- _variable naming convention to identify objects that should not be modified by client to the objects.
```
class Flight:
def __init__(self,number):
self._number = number
```
Polymorphism - Using Objects of different types via common Interfaces. Applies to Objects and Functions both.
Polymorphism in Python is preferred via ducktyping rather than traditional inheritance from base classes.
Class Inheritance is more useful in sharing implementation rather than acheiving polymorphism.(airtravel_inherit.py)
Duck Typing in python
Suitability is not defined by interfaces or inheritance , but by parameters at point in runtime.This is where its different from JAVA.
Refer to airtravel.py
class Aircraft:
""" Base Class to Airbus and Boeing
Can't be initialized
the self reference is not present , expects some implementation class to provide
"""
def num_seats(self):
rows,row_seats = self.seating_plan()
return len(rows) * len(row_seats)
class Boeing777(Aircraft):
""" num_seats is inherited from Base Class Aircraft """
def __init__(self,registration):
self._registration = registration
def registration(self,registration):
return self._registration
def model(self):
return "Boeing777"
def seating_plan(self):
return (range(1, 56), "ABCDEFGHJK")
- Resource : Program Elements that must be closed or released after use.
- Pythons offering for automatic resource management ( Context Managers )
- Core functions of opening file (Text Mode vs Binary Mode)
- Callers responsible for new lines.
Default Encoding - sys.getdefaultencoding() - utf-8
| MODE | MEANING |
|---|---|
| r | reading |
| w | writing |
| a | open for appending |
| SELECTOR | MEANING |
| b | binary Mode |
| t | text Mode |
fstream = open('filename.txt',mode='wt',encoding='utf-8')
fstream = fstream.write('First Line written\n')
fstrem.close()
fileReader = open('filename.txt',mode='rt' , encoding='utf-8')
fileReader.readline() # read till first \n char and return
fileReader.readline() # further calls after reaching eol return empty.
If enough memory , read all lines into list:
['line1\n','lastline']
fileReader.readlines()
File Iterators:
Observe not using print(line) -- which adda an empty line while printing on console.
import sys
try:
f = open('afile.txt',mode='rt',encoding='utf-8')
for line in f:
sys.stdout.write(line)
finally:
f.close()
Observe how no try / catch / finally block needed
import sys
with open('afile.txt',mode='rt',encoding='utf-8') as f:
for line in f:
sys.stdout.write(line)
- Comprehensions : ( Concise syntax for describing lists/sets and dictionaries)
- create familiar objects
- create new kinds of objects
- Filtering
- Low Level Iterable API - Iterators ( Iteration Protocols)
- Generator Functions
- Yield keyword
- Statefullness / Laziness & infitine sequences
- Generator Expressions
- Iteration Tools
- any / all
- zip ( imagine CSV , different columns merged to present a multi column data)
Using the Square Bracket for Lists:
[expr(item) for item in iterable]
Using the Curly Braces for Sets:
{expr(item) for item in iterable}
words = "Take me home alabama".split()
words = ['My','Complete'......,'delimiters']
Below list comprehension will print the length of each word in the words list [4, 2, 4, 7]
[len(word) for word in words]
Below list comprehension will print upper case of each word in the words list ['TAKE', 'ME', 'HOME', 'ALABAMA']
[word.upper() for word in words]
Below list comprehension will print a list having string lenght of resultnt factorial coming from range(20)
f = [len(str(factorial(x))) for x in range(20)]
-
{
key_expr(item): value_expr(item)
for item in iterable
} -
we cannot use the dict object directly but do tuple unpacking by using:
dict.items()
E.g from a dictionary of Country-> Captial , say we want to form a captial based lookup. Capital->Country
country_to_cap = {"India":"New Delhi","Australia":"Sydney","Sri Lanka":"Colombo","England":"London"}
cap_to_country = { capi:cntry for cntry,capi in country_to_cap.items()}
Using the Square Bracket for Lists:
[expr(item) for item in iterable if ]
- StopIteration Exception |Iterable|Iterator| |---|---| |Can be passed to iter() to produce an iterator|Can be passed to next() to get the next value in sequence|
iterable = ['Cricket','Football','Table Tennis']
iterator = iter(iterable)
next(iterator) = Cricket
next(iterator) = Football
next(iterator) = Table Tennis
next(iterator) = StopIteration Exception
| Finite Seqeunce | Infinite Sequence |
|---|---|
| Reaches the end will throw the StopIteration Exception |
Consider Like a defined ENUM in java IS a SEQUENCE
- Iterables defined by functions , does throw StopIteration if next(lastSequenceOfObject)
- Lazy evaluation
- Can model sequences with no definite end ( e.g log files etc )
- Composable in to pipelines
- Must include at least one yield statement , may also include return
def genSports():
print('About to yield ')
yield 'Cricket'
print('About to yield ')
yield 'Basketball'
print('About to yield ')
yield 'Tennis'
### Usage 1 ###
sportIter = genSports()
next(sportIter)
#### Usage 2 ###
for sport in genSports():
print(f"{sport}")
- any / all
- zip
any([False,False,True]) = True
all([False,False,True]) = False
"Starting Letter is Capital".title() == true
Combined with a Comprehension Expression :
any(is_prime(x) for x in range(1328,1366))
Check if every name in iterable is a title , meaning starting with a Capital letter
all( name == name.title() for name in ['London','Amsterdam','Sydney','New York'] )
Bind Iterables together
| Iterable | Sample Data |
|---|---|
| firstname | ["Satadru","Christiano","Roger","Virat"] |
| lastname | ["Basu","Ronaldo","Federrer","Kohli"] |
| empid | ["EMP0010","EMP0011","EMP0012","EMP0013"] |
firstname = ["Satadru","Christiano","Roger","Virat"]
lastname = ["Basu","Ronaldo","Federrer","Kohli"]
empid =["EMP0010","EMP0011","EMP0012","EMP0013"]
for item in zip(firstname,lastname,empid):
print(f"{item}")