Object Type | Example |
---|---|
Numbers | 1.23, 123, 3+4j |
Strings | "hello, world" |
Lists | [1, 'hello', ['I', 'am', 'list', 'in', 'a', 'list'], 4.5] |
Dictionary | {"key":"value", 'foo':0, 'bar':'drink'} |
Tuples | (4, 'hello', 3.14) |
Others | set, types, booleans, none |
Numbers, Strings, Tupples are immutable. Means they can't be changed after creation
Lists and Dictionaries are mutable
Example: 'hello, world', "I am me" etc
len()
function gives the length of the string.
>>> str = "Hello, World"
>>> print len(str) # Python 2
12
>>> print(len(str)) # Python 3
12
Individual character can be indexed from a string. Index can be negative. Negative index will return chars backword.
>>> print str[0]
H
>>> print str[-1]
d
>>> print str[-2]
l
Extract a section of a string in one step. str[m:n] will produce 'str[m]str[n-1]'. Default value of m is 0 and n is the length of the string.
>>> print str[7:10] # Slice from 7 to 10(non-inclusive)
'Wor'
>>> str[:] # Slice from start to end */
'Hello, World'
>>> str[:4] # Slice from start upto 4
'Hell'
>>> str[:-1] # Slice from start upto last item
'Hello, Worl'
General format of slicing is x[i:j:k]. Where k is the step size from i upto j. k can be negative, in that case slice will occur from i upto j in reverse order. Default value of k is 1.
>>> "12345678"[1:6:2] # From index 1 upto index 6 and step size 2
'246'
"hello"[::2] # Entire string, step size 2
'hlo'
"hello"[::-1] # Entire string. Step size 1. But as the step
'olleh' # size is negetive, slicing will be done in reverse order
Strings can be concatenated using + sign and repeated using * sign.
>>> foo = "I am little bunny foo foo"
>>> bar = " and bar is with me"
>>> foo + bar
'I am little bunny foo foo and bar is with me'
>>> foo * 3
'I am little bunny foo fooI am little bunny foo fooI am little bunny foo foo'
Every operation we have performed on string can be performed other sequence objects like lists and tupples
>>> string = "foo bar"
>>> string.find('o')
1
>>> string.replace('oo', 'uu')
'fuu bar'
>>> string
'foo bar' # String itself unchanged as immutable
>>> bands = "Warfaze, Black, Artcell, Bangla"
>>> bands.split(',') # Split according to the argument and return as list
['Warfaze', ' Black', ' Artcell', ' Bangla']
string = "Hello, how are you\n\n\n"
>>> string = string.rstrip() # Remove whitespaces from the rigth most side
>>> string
'Hello, how are you'
ord()
function returns ASCII value of a character.
>>> ord('A')
65
chr()
function converts ASCII value to character.
>>> chr(65)
'A'
\0 or null terminator doesn't end python strings
>>> s = 'A\0B\0C'
>>> s
'A\x00B\x00C'
>>> print s
ABC
>>> len(s)
5
Multiline strings can be specified using three " or '.
>>> str = """
... When this form is used
... all the lines are concatenated togather
... and end-of-the line characters are added
... where line breaks appear
... """
>>> str
'\nWhen this form is used\nall the lines are concatenated togather\n\tand end-of-the line characters are added\nwhere line breaks appear\n'
>>> print str
When this form is used
all the lines are concatenated togather
and end-of-the line characters are added
where line breaks appear
List object is sequence object. They are mutable.
>>> list = [1, 2.3, 'foo'] # Creating list object
>>> len(list) # Finding length
3
>>> list[0] # Can be indexed
1
>>> list[-1]
'foo'
>>> list[1:3] # Slicing
[2.3, 'foo']
>>> list + ['bar'] # Concatenation
[1, 2.3, 'foo', 'bar']
>>> list = list + ['bar'] # Mutability
>>> list
[1, 2.3, 'foo', 'bar']
- Can hold different types of object
- No fixed size
- Mutable.
>>> list = [1, 'foo']
>>> list.append('bar') # Add an item at the end of the list
>>> list
[1, 'foo', 'bar']
>>> list.insert(1, 'baz') # Insert an item at a specific index
>>> list
[1, 'baz', 'foo', 'bar']
>>> list.pop(1) # return and remove an item from a specific
'baz' # index
>>> list
[1, 'foo', 'bar']
>>> list.remove('bar') # remove first occurance of an item found
>>> list # in the list
[1, 'foo']
As list is a mutable object there are methods that can change a list object in place.
>>> list = ['heaven', 'and', 'hell']
>>> list.sort() # Sort List
>>> list
['and', 'heaven', 'hell']
>>> list.reverse() # Reverse sort List
>>> list
['hell', 'heaven', 'and']
Lists can be nested.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> matrix[0]
[1, 2, 3]
>>> matrix[0][0]
1
List comprehension is a way to build a new list running an expression on each item in a sequence, once at a time.
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> col2 = [row[1] for row in matrix]
>>> col2
[2, 5, 8]
>>> list = [var for var in range(0, 11)]
>>> list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[num for num in range(0, 11) if num % 3 == 0] # Filtering
[0, 3, 6, 9]
Dictionaries are used to store value in a key value pair.
- Mutable
- Values are stored in a key value pair
- Stores any type of objects
- Can be nested
band = {'name':'Bangla', 'albums':2} # Creation
>>> band
{'albums': 2, 'name': 'Bangla'}
>>> band['name'] # Indexing by key
'Bangla'
>>> band['started'] = 1999 # Mutable
>>> band
{'started': 1999, 'albums': 2, 'name': 'Bangla'}
Type Specific Methods:
>>> dic = {'c':1, 'a':2, 'b':3}
>>> dic
{'a': 2, 'c': 1, 'b': 3}
>>> dic.keys() # Returns List of the keys
['a', 'c', 'b']
Iterating over a Dictionary:
>>> dic = {'c':1, 'a':2, 'b':3}
>>> dic
{'a': 2, 'c': 1, 'b': 3}
>>> for key in dic.keys():
... print "key: %s\tValue: %s" % (key, dic[key])
...
key: a Value: 2
key: c Value: 1
key: b Value: 3
Python tuples are list like sequence object. But they are immutable.
>>> T = (1, 2, 3, 4)
>>> T
(1, 2, 3, 4)
>>> T[0]
1
>>> len(T)
4
>>> T[1] = 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
Collection of unique elements. Supports usual mathematical set operations.
>>> x = set('hello')
>>> x
set(['h', 'e', 'l', 'o'])
>>> y = set(['w', 'o', 'r', 'l', 'd'])
>>> y
set(['d', 'r', 'o', 'w', 'l'])
>>> x & y
set(['l', 'o'])
>>> x | y
set(['e', 'd', 'h', 'l', 'o', 'r', 'w'])
>>> x - y
set(['h', 'e'])
repr()
display numbers as in code.
str()
Convert numbers into string.
oct()
converts decimal into octal
hex()
converts decimal into hexadecimal
int(string, base)
- converts strings into numbers.
float()
- Coverts strings into floating point number.
bin()
- Converts integer to binary
Fixed precision representation of numbers.
>>> 0.1 + 0.2 - 0.3
5.551115123125783e-17 # The problem
>>> from decimal import Decimal
>>> Decimal(0.1) + Decimal(0.2) - Decimal(0.3) # Solution
Decimal('2.775557561565156540423631668E-17')
>>> Decimal('0.1') + Decimal('0.2') - Decimal('0.3')
Decimal('0.0')
>>> Decimal(1) / Decimal(7)
Decimal('0.1428571428571428571428571429')
>>> decimal.getcontext().prec = 4 # Precision
>>> Decimal(1) / Decimal(7)
Decimal('0.1429')
Different Forms:
- Single Quotes: 'he said, "hello"'
- Double Quotes: "Robin's book"
- Block of strings: """string block""", '''String Block'''
- Raw strings: r'\thello, world\n'. Take each characters leterally, omits escape sequences. e.g. r"C:\new\values". But raw string won't work for a string ended with backslash. r"..."; This is invalid.
- Byte Strings: b'spam' (Python 3)
- Unicode strings: u'\u0986\u09AE\u09BE\u09B0' (in 2.6 only)
In python 3 there are three string types. str
is used for unicode text(ASCII and others). bytes
is used
for bynary data. bytearray
is mutable variant of bytes.
>>> print 'he said, "hello"' # Python 2.6
he said, "hello"
>>> print ('he said, "hello"') # Have to use brackets in python 3
he said, "hello"
>>> print "Robin's book"
Robin's book
>>> print """Once upon a time
... there was a man
... one day"""
Once upon a time
there was a man
one day
>>> print r'\thello, world\n'
\thello, world\n
>>> print u'\u0986\u09AE\u09BE\u09B0'
আমার
ord('char')
convert char into ints ASCII value.
chr(value)
convert from ASCII to character.
eval(str)
- convert a string into python executable code.
>>> list = [1, 2, 3]
>>> str = '%s' % list # List is converted into a string
>>> str
'[1, 2, 3]'
>>> eval(str) # String is converted back to list
[1, 2, 3]
>>> print("%s:%d\t%s:%d" % ("Alice", 40, "Bob", 50))
Alice:40 Bob:50
>>>
>>>print("My List: %s" % [1, 2, 3])
My List: [1, 2, 3]
Type Code | Meaning |
---|---|
%s | String |
%r | Raw string |
%c | Character |
%d | Integer |
%i | Integer |
%u | Unsigned Integer |
%o | Octal |
%x | Hexadecima(lower) |
%X | Hexadecimal(Upper) |
%e | Floating point Exponent |
%E | e, but uppercase |
%f | Floating point decimal |
%g | e or f |
%G | E or f |
%% | literal % |
General conversion code structure: %[(name)][flags][width][.precision]typecode
Dictionary base string formating: "%(name)s has %(value)d taka" % {'name':'ashik', 'value':50}
>>> 'Distance between {0} and {1} is {2} km'.format('Dhaka', 'Khulna', 279.6)
'Distance between Dhaka and Khulna is 279.6 km'
string.replace('old', 'new')
- replce old substring with new substring from string and return new string.
>>> str = "hello, world"
>>> str.replace('world', 'bob')
'hello, bob'
>>> str
'hello, world'
>>>
>>>
>>> str = 'FooBarFooBar'
>>> str
'FooBarFooBar'
>>> str.replace('Bar', 'Baz') # Replace all occurance
'FooBazFooBaz'
>>> str.replace('Bar', 'Baz', 1) # Replace only first occurance
'FooBazFooBar'
>>>
string.find('substring')
- Find the index of the first occurance of the substring from string.
>>> str = 'hello, world'
>>> str
'hello, world'
>>> where = str.find('ello')
>>> where
1
>>> str = str[:where] + 'ola' + str[(where + 4):] # Replace trick
>>> str
'hola, world'
list(string)
- convert string into list.
>>> str
'FooBarFooBar'
>>> L = list(str)
>>> L
['F', 'o', 'o', 'B', 'a', 'r', 'F', 'o', 'o', 'B', 'a', 'r']
string.join(list)
- join list items with string.
>>> ''.join(L) # Join list item of L with empty string
'FooBarFooBar'
string.split(delimiters)
- split string into a list according to specified delimiters. Default delimiter is whitespaces if nothing specified.
>>> str = 'Sing me song you are a singer'
>>> str.split() # No delimiters specified. Default whitespaces.
['Sing', 'me', 'song', 'you', 'are', 'a', 'singer']
>>>
>>>
>>> str = 'Warfaze, Black, Artcell'
>>> str.split(', ') # Used ', ' as delimiter
['Warfaze', 'Black', 'Artcell']
string.rstrip()
- remove whitespaces from the end of the string.
string.upper()
- Convert all characters into uppercase.
string.endswith(substring)
- Check if the string ends with specified substring.
- Some basic operations.
>>> len([1, 2, 3]) # Length
3
>>>
>>> [1, 2, 3] + [4, 5, 6] # Concatenation
[1, 2, 3, 4, 5, 6]
>>>
>>> [1, 2] * 3 # Repetition
[1, 2, 1, 2, 1, 2]
>>>
>>> 2 in [1, 2, 3] # Membership Check
True
>>>
>>> for i in [1, 2, 3]: # Iteration
... print i
...
1
2
3
- Indexing, Slicing, Nesting
>>> list = [1, 2, 3]
>>> list[0] # Indexing
1
>>>
>>> list[1:3] # Slicing
[2, 3]
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # Nesting
>>> matrix[0][0]
1
- Mutability
>>> list = [1, 'foo', 2, 'bar']
>>> list[3] = 'baz' # Changing in place using indexing
>>> list
[1, 'foo', 2, 'baz']
>>> list[1:3] = [2, 3] # Changing in place using slicing
>>> list
[1, 2, 3, 'baz']
>>>
>>> del list[0] # Delete one item from list
>>> list
[2, 3, 'baz']
>>>
>>> del list[1:] # Delete a section from list
>>> list
[2]
>>>
>>> list = [1, 2, 3, 4]
>>> list[1:3] = [] # Another way of deleting a section
>>> list
[1, 4]
list.append(item)
- To append item at the end of the list.list.extend(argList)
- Append multiple items at the end of the list at once.list.insert(index, item)
- To insert item at index index of the list.list.pop([index])
- Remove item from list at index index. If index isn't specified default is the last item.list.remove(item)
- Remove first occurence of the item from the list.list.sort()
- Sort List.list.reverse()
- Reverse sort the list.
>>> mList = [1, 2]
>>> mList.append(3) # Append at the end of the list
>>> mList
[1, 2, 3]
>>>
>>>
>>> mList.extend([4, 5]) # Extend list with multiple items
>>> mList
[1, 2, 3, 4, 5]
>>>
>>>
>>> mList.insert(1, 9) # Insert at specific index
>>> mList
[1, 9, 2, 3, 4, 5]
>>>
>>>
>>> mList.pop()
5
>>> mList
[1, 9, 2, 3, 4]
>>> mList.pop(1)
9
>>> mList
[1, 2, 3, 4]
>>>
>>>
>>> mList.remove(4)
>>> mList
[1, 2, 3]
>>>
>>>
>>> mList.reverse()
>>> mList
[3, 2, 1]
>>> mList.sort()
>>> mList
[1, 2, 3]
- Creation:
>>> dic = {'foo':0, 'bar':1, 'baz':2}
>>> dic
{'baz': 2, 'foo': 0, 'bar': 1} # Notice Order Scambled
>>>
>>> dic['foo'] # Fetching value using key
0
- Some basic operations
>>> dic
{'baz': 2, 'foo': 0, 'bar': 1}
>>> len(dic) # Length
3
>>>
>>> 'foo' in dic # Key membership check
True
>>> dic.has_key('bar') # Key membership check
True
>>> dic.keys() # Gives a list of all keys
['baz', 'foo', 'bar']
>>>
>>> dic
{'goo': 3, 'foo': 5, 'bar': 1}
>>> for key in dic.keys(): # Iterating
... print dic[key]
...
3
5
1
- Mutability
>>> dic
{'baz': 2, 'foo': 0, 'bar': 1}
>>> dic['goo'] = 3 # Adding new entry
>>> dic
{'baz': 2, 'goo': 3, 'foo': 0, 'bar': 1}
>>>
>>>
>>> dic['foo'] = 5 # Changing existing entry
>>> dic
{'baz': 2, 'goo': 3, 'foo': 5, 'bar': 1}
>>>
>>>
>>> del dic['baz'] # Deleting an entry
>>> dic
{'goo': 3, 'foo': 5, 'bar': 1}
- Some methods
>>> dic
{'goo': 3, 'foo': 5, 'bar': 1}
>>> dic.keys() # Returns a list of all keys
['goo', 'foo', 'bar']
>>>
>>> dic.values() # Returns a list of all values
[3, 5, 1]
>>>
>>> dic.items() # Returns a list of tupples of
[('goo', 3), ('foo', 5), ('bar', 1)] # key/value pair
>>>
>>> dic.get('foo') # Fetching
5
>>>
>>> dic2 = {'zoo':10, 'loo':40}
>>> dic.update(dic2) # Exteding multiple items
>>> dic
{'goo': 3, 'bar': 1, 'foo': 5, 'loo': 40, 'zoo': 10}
>>>
>>> dic.pop('zoo') # Deliting item
10
>>> dic
{'goo': 3, 'bar': 1, 'foo': 5, 'loo': 40}
Almost all properties are same as list, except tupples are immutable.
>>> t = (0, 1, 2) # Creation
>>> t
(0, 1, 2)
>>> tt = (2,) # Single element tupple
>>>
>>> t[1] # Indexing
1
>>> t + (3, 4) # Concatenation
(0, 1, 2, 3, 4)
>>> (1, 2) * 3 # Repeatition
(1, 2, 1, 2, 1, 2)
>>> t
(0, 1, 2)
>>> t[1:] # Slicing
(1, 2)
open(path, mode, buffering)
function opens a file and returns a file object which can be used to read and write files.
Open modes:
Mode | Effect |
---|---|
r | open file in read mode. Default, if nothing specified. |
w | Open file in write mode. |
a | Open file in append mode |
file.write(str)
- write a string to a file.
>>> outf = open('myfile', 'w') # Creates a file object
>>> outf.write('hello, world\n')
>>> outf.close()
file.read()
- Reads whole file.
>>> fin = open('myfile') # Default read mode
>>> print fin.read()
hello, world!
I am foo.
I am bar.
>>>
file.readline()
- Returns a line from a file including \n.
>>> fin.seek(0)
>>> fin.readline()
'hello, world!\n'
file.readlines()
- Returns a list of all lines from a file.
>>> fin = open('myfile')
>>> fin.read()
'hello, world!\nI am foo.\nI am bar.'
>>> fin.seek(0)
>>> fin.readlines()
['hello, world!\n', 'I am foo.\n', 'I am bar.']
file.truncate(bytes)
- File will be truncated to specified bytes. All previous data will be lost. Specified byte space will be zero filled.
- Check if a file/path exists
from os.path import exists
print(exists("/home/username/myfile.txt"))
Tool to store python object in a file directly with no to-or-from string conversion.
# Storing Object
>>> list = [1, 2, 3]
>>> list
[1, 2, 3]
>>> fobj = open("file.bin", "wb")
>>> pickle.dump(list, fobj)
>>> fobj.close()
# Restoring object from file
>>> fobj = open("file.bin", "rb")
>>> l = pickle.load(fobj)
>>> l
[1, 2, 3]
Boolean values are two constant objects True and False.
- Non zero numbers are true.
- Non empty objects are true.
Example:
>>> bool(0)
False
>>> bool(1)
True
>>> bool(50)
True
>>>
>>> bool([])
False
>>> bool([1, 2])
True
>>>
>>> bool({})
False
>>> bool({'spam': '2$'})
True
>>>
>>> bool(None)
False
- Python statements are ended by new lines. No semicolon is needed.
a = 40 # Statement
x = a + 10 # Another Statement
- Semicolons can be used to use multiple statements in a single line.
a = 40; b = 60; print(a + b)
- Brackets (first, second or third) are used to span single statement in multiple lines.
x = (a + b +
c + d)
list = [1, 2, 3,
4, 5, 6]
- Also
\
can be used to span single statement in multiple lines.
x = a + b + \
c + d
- In python colons are used for compound statements (Statements which have nested blocks)
if x > y:
print("%d is larger" % x)
- Nested blocks are nested using indentations. Curly braces are not needed.
if x > y:
a = x
b = y
- For single line block statement can be placed right after colon.
if x > y: print(x)
- Assignments create object references.
- Names are created when first assigned.
- Names must be assigned before being referenced.
>>> spam = 'hello, world' # Basic form
>>> spam
'hello, world'
>>> spam, ham = 'hello', 'world' # Tupple assignment(Positional)
>>> spam, ham
('hello', 'world')
>>> [spam, ham] = ['hello', 'world'] # List assignment(Positional)
>>> spam, ham
('hello', 'world')
>>>
>>> a, b, c, d = 'spam' # Sequence assignment
>>> a, b, c, d
('s', 'p', 'a', 'm')
>>>
>>> a, *b = 'spam' # Extended sequence unpacking
>>> a
's'
>>> b
['p', 'a', 'm']
>>> spam = ham = 'launch' # Multiple assignment
>>> spam, ham
('launch', 'launch')
In case of multiple assignment all the variables point to the same object(same piece of memory)
>>> spam = ham = [1, 2, 3] # spam & ham are pointing to same object
>>> spam
[1, 2, 3]
>>> ham
[1, 2, 3]
>>> spam[1] = 4 # spam changed
>>> spam
[1, 4, 3]
>>> ham # ham changed too as they are pointing to same object
[1, 4, 3]
In case of concatenation must create a new object, copy it in the object on the left, then copy it on the right. So it is slower. On the other hand in case of in-place assignment new item is just added at the end of the memory block.
>>> L = [1, 2]
>>> L = L + [3, 4] # Concatenation: Slower
>>> L
[1, 2, 3, 4]
>>> L.extend([5, 6]) # In-place assignment: Faster
>>> L
[1, 2, 3, 4, 5, 6]
>>> L += [7, 8] # Python automaticaly use the faster method
>>> L = [1, 2]
>>> M = L # M & L are shared object
>>> M
[1, 2]
>>> L
[1, 2]
>>>
>>> L = L + [3] # Concatenation
>>> L
[1, 2, 3] # L changed
>>> M
[1, 2] # But M isn't as concatenation creates new object
>>>
>>> M = L # M is pointing to L
>>> M
[1, 2, 3]
>>>
>>> L += [4] # In-place assignment
>>> L
[1, 2, 3, 4] # L is changed
>>> M
[1, 2, 3, 4] # M is changed too as augmented assignmets are in-place
-
Names that begin with single underscore(
_X
) are not imported by from module import * statement -
Names that begin with two leading and trailing underscore(
__X__
) are system defined and have special meaning to interpreter. -
Names that begin with two leading underscore(
__X
) are localized to enclosing classes -
Class names usually starts with uppercase letters.
-
Module names starts with lowercase letters.
see: Python String data type in details
A fun \r
(carriage return trick):
while True:
for ch in ["\\", "-", "|", "/"]:
print("%s\r" % ch, end = "")
Using file
argument of the print() function:
>>> print("hello, world", file = open("hello.txt", "w"))
>>> open("hello.txt").read()
'hello, world\n'
Using sys.stdout
:
>>> import sys
>>> tmp = sys.stdout
>>>
>>> sys.stdout = open("hello.txt", "w")
>>> print("hello, world!")
>>>
>>> sys.stdout = tmp
>>> open("hello.txt").read()
'hello, world!\n'
Pyhton takes inputs as a string from stdin. In python 3 input("prompt")
function is used to take input. In python 2.x raw_input("prompt")
is used.
name = input("Enter your name: ")
# Inputs are taken as Strings. To convert to int.
age = int(input("Enter your age: "))
print("Hello, %s! Your age is %d" % (name, age))
from sys inport argv
script, arg0, arg1, arg2 = argv
print("Script name: %s" % script)
print("First argument: %s" % arg0)
print("Second argument: %s" % arg1)
print("Third argument: %s" % arg2)
Structure:
if <test1>:
<statement1>
elif <test2>:
<statement2>
else:
<statement3>
No switch case in python. Work around with if:
>>> choice = 'gam'
>>>
>>> if choice == 'spam':
... print("0$")
... elif choice == 'ham':
... print("1$")
... elif choice == 'gam':
... print("2$")
... else:
... print("Bad Choice!")
...
2$
Dictionary based work around (Less typing!):
>>> choice = 'jam'
>>>
>>> print({'spam': '0$',
... 'ham': '1$',
... 'gam': '2$'}.get(choice, 'Bad choice!'))
Bad choice!
and
operator:
if X and Y: # True if X and Y both True
# Do something
Return Value: and
didn't return True or False. Returns first object which is
false(zero or empty) from left to right. If expression is true returns right most
object.
>>> 1 and 2
2
>>> [] and 2
[]
>>> 1 and [] and 2
[]
or
operator:
if X or Y: # True if X or Y is True
# Do something
Return value: or
didn't return True or False. Returns first object which is true
(non-zero / non-empty) from left to right.
>>> 2 or 3
2
>>> [] or 3
3
>>> {} or 3 or []
3
not
operator:
if not X: # Invert logic
# Do something
Return value: Returns True or False
Range:
if 0 <= x <= 10: DO SOMETHING
>>> rn = 1500
>>> if 2100 < rn < 4000:
... print("Transitional")
... else:
... print("Different flow pattern")
Different flow pattern
Consider following code:
if X:
A = Y
else:
A = Z
Ternary Expression:
A = Y if X else Z
>>> count = 5
>>> "five" if count == 5 else "not five"
'five'
while <test1>:
<statement1>
if <test2>: break # Exit loop now. Skip else part
if <test3>: continue # Continue to test1
else: # Execute only if loop is exited without break
<statement2>
pass: Do nothing. Just an empty statement place holder.
for <target> in <object>/<sequence>:
<statements>
if <test>: break
if <test>: continue
else:
<statements>
- Any sequence works in for loop
>>> for i in [1, 2, 3]:
... print(i, end = '\t')
... else:
... print("")
...
1 2 3
>>>
>>> for ch in "abc":
... print(ch, end = '\t')
... else:
... print("")
...
a b c
>>> for (a, b) in [(1, 2), (3, 4)]:
... print("%d, %d" % (a, b))
...
1, 2
3, 4
>>> for ((a, b), c) in [((1, 2), 3), ((4, 5), 6)]:
... print(a, b, c)
...
1 2 3
4 5 6
>>> for ((x, y), z) in [((1, 2), 3), ("XY", 'Z')]:
... print(x, y, z)
...
1 2 3
X Y Z
>>> dict = {1: 'a', 2: 'b', 3: 'c'}
>>> for key in dict.keys():
... print("Key: %d\tValue: %c" % (key, dict[key]))
...
Key: 1 Value: a
Key: 2 Value: b
Key: 3 Value: c
>>>
>>> for key, value in list(dict.items()):
... print(key, value)
...
1 a
2 b
3 c
range(FROM, UPTO, STEP)
- Create a list of numbers FROM to UPTO in python 2.0. In python 3.0 it's an iterator.
Example:
# Python 2.0
>>> range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> range(0, 10, 2)
[0, 2, 4, 6, 8]
# Python 3.0
>>> list(range(0, 10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> list(range(0, 10, 2))
[0, 2, 4, 6, 8]
Range items can be negative numbers and can be in reverse order.
>>> list(range(8, 0, -1))
[8, 7, 6, 5, 4, 3, 2, 1]
>>>
>>> list(range(4, -4, -1))
[4, 3, 2, 1, 0, -1, -2, -3]
Range can be used as a iterator in for loops.
>>> X = "abcdefgh"
>>> for i in range(0, len(X), 2):
... print(X[i], end = '')
... else:
... print()
...
aceg
# Alternative good solution is with sclicing
>>> X
'abcdefgh'
>>> for ch in X[::2]:
... print(ch, end = '')
... else:
... print()
...
aceg
zip(seq1, seq2, ...)
takes one or more sequence as argument and creates a list of Tuples from them. zip creates an iterable object. Which can be converted to list or other sequence object.
>>> l = [1, 2, 3]
>>> m = [4, 5, 6]
>>> n = [7, 8, 9]
>>> list(zip(l, m, n))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
zip()
truncates if the size of the sequences mismatches.
>>> l = [1, 3, 5, 7]
>>> m = [2, 4]
>>> list(zip(l, m))
[(1, 2), (3, 4)] # Truncates
zip()
can be used to iterate through multiple sequence in for
loop.
>>> for x, y, z in zip(l, m, n):
... print(x, y, z)
...
1 4 7
2 5 8
3 6 9
zip()
can be used to construct a dictionary from key and value lists.
>>> key = ["spam", "ham", "egg"]
>>> value = [1, 2, 3]
>>>
>>> D = {}
>>> for k, v in list(zip(key, value)):
... D[k] = v
...
>>> D
{'ham': 2, 'spam': 1, 'egg': 3}
>>>
# Also dict constructor can be used
>>> D = dict(zip(key, value))
>>> D
{'ham': 2, 'spam': 1, 'egg': 3}
Python 2.0: In python 2.0 map()
gives similar functionality like zip()
.
# Python 2.0
>>> l = [1,2,3]
>>> m = [4,5,6]
>>> map(None, l, m)
[(1, 4), (2, 5), (3, 6)]
Python 3.0: In python 3.0 map takes a function and one or more sequence arguments and collects the results of calling the function.
>>> list(map(ord, "spam"))
[115, 112, 97, 109]
enumerate()
is used to find the index and value of a sequence. It creates a generator object which is iterable.
# Normal Way
>>> S = "hello"
>>> index = 0
>>>
>>> for value in S:
... print(index, value)
... index += 1
...
0 h
1 e
2 l
3 l
4 o
# enumerate way
>>> S = "hello"
>>>
>>> for index, value in enumerate(S):
... print(index, value)
...
0 h
1 e
2 l
3 l
4 o
An object is called iterable if it's a sequence or an object that produce one result at a time.
Any object that supports iteration has __next__()
method. It raises StopIteration exception
at the end of the series of results.
# Manual method
General Structure: [expression for target1 in iterable1 if condition1 for target2 in iterable 2 if condition2 ...]
List Comprehension:
>>> L = [1, 2, 3]
>>> L = [x ** 2 for x in L]
>>> L
[1, 4, 9]
>>>
# Equavalent map
>>> list(map((lambda x: x ** 2, ), [1, 2, 3]))
[1, 4, 9]
>>> lines = [line for line in open('text')]
>>> lines
['hello, world!\n', 'Imagine\n']
>>>
>>> lines = [line.rstrip() for line in open('text')]
>>> lines
['hello, world!', 'Imagine']
Filtering:
>>> L = [x for x in range(0, 11) if x % 2 == 0]
>>> L
[0, 2, 4, 6, 8, 10]
# Equavalent using map using filter
>>> list(filter((lambda x: x % 2 == 0), range(0, 11)))
[0, 2, 4, 6, 8, 10]
Evaluating and Filtering:
>>> [x ** 2 for x in range(0, 11) if x % 2 == 0]
[0, 4, 16, 36, 64, 100]
# Equavalent
>>> list(map((lambda x: x ** 2), filter((lambda x: x % 2 == 0), range(0, 11))))
[0, 4, 16, 36, 64, 100]
Nested Loops:
>>> [x + y for x in [0, 1, 2] for y in [100, 99, 98]]
[100, 99, 98, 101, 100, 99, 102, 101, 100]
>>> [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
Work with Matrices:
>>> M = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
>>> M
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
>>>
>>> [M[row][0] for row in range(len(M))]
[0, 3, 6]
>>>
>>> N = [[9, 10, 11], [12, 13, 14], [15, 16, 17]]
>>>
>>> [M[row][col] * N[row][col] for row in range(len(M)) for col in range(len(M))]
[0, 10, 22, 36, 52, 70, 90, 112, 136]
>>> [[M[row][col] * N[row][col] for col in range(len(M))] for row in range(len(M))]
[[0, 10, 22], [36, 52, 70], [90, 112, 136]]
>>> {key: value for key, value in list(zip("abc", [1, 2, 3]))}
{'c': 3, 'a': 1, 'b': 2}
>>>
>>> {x for x in "abccde"}
{'c', 'e', 'a', 'd', 'b'}
Python dir()
lists all the methods of an object.
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Docstrings are used for documenting python module, class, class methods, functions etc. Docstrings are placed as the first statement of the module, class, methods, functions.
From PEP 257
A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the
__doc__
special attribute of that object.
All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the
__init__
constructor) should also have docstrings. A package may be documented in the module docstring of the__init__.py
file in the package directory.
Example:
def add(x, y):
"""Add two numbers
Args:
x : first number
y : second number
Returns:
addition of the two number
"""
return x + y
Python help()
function gives the documentation of an object that are
created by docstrings
Example:
>>> def sum(x, y):
... return x + y
...
>>> sum(10, 5)
15
>>> sum(10, 10)
20
Default Argumets:
>>> def func(a, b):
... print(a, b)
...
>>> dir(func)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>>
>>> func.__name__
'func'
>>>
>>> dir(func.__code__)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
>>>
>>> func.__code__.co_varnames
('a', 'b')
>>> func.__code__.co_argcount
2
Custom Argumets:
>>> func.cusarg = 1
>>> print(func.cusarg)
1
>>> dir(func)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cusarg']
>>> def func(a: 'spam' = 0, b: (1, 10) = 1, c: float = 2) -> int:
... print(a + b + c)
...
>>> func.__annotations__
{'return': <class 'int'>, 'c': <class 'float'>, 'a': 'spam', 'b': (1, 10)}
>>>
>>> for arg in func.__annotations__:
... print(arg, " => ", func.__annotations__[arg])
...
return => <class 'int'>
c => <class 'float'>
a => spam
b => (1, 10)
>>> x = 10
>>>
>>> def func1():
... x = 20
... def func2():
... print(x) # func2() knows about x
# as enclosing function
... func2()
...
>>>
>>> func1()
20 # 20 not 10 because LEGB rule
# However this code doesn't work
# in previous versions. As searches only local scope
# before global scope. Work around:
>>> x = 10
>>>
>>> def func1():
... x = 20
... def func2(x = x):
... print(x)
... func2()
...
>>>
>>> func1()
20
# Supposed to make a list of functions
# With different values of i.
>>> def actionMaker():
... acts = []
... for i in range(0, 5):
... acts.append(lambda x: i ** x)
... return acts
...
>>>
>>> f = actionMaker()
>>>
>>> f[0](2) # Should print 0
16 # prints 16 instead
>>>
>>> f[1](2) # Should print 1
16 # prints 16 insead
# This doesn't work because eclosing namespace is looked up when
# the nested function is called. so i is looked up when
# f[]() is called. But after actionMaker() call i is 4
# Work around:
ctionMaker():
... acts = []
... for i in range(0, 5):
... acts.append(lambda x, i = i: i ** x)
... return acts
...
>>>
>>> f = actionMaker()
>>> f[0](2)
0
>>> f[1](2)
1
>>> f[2](2)
4
>>> def func1():
... x = 10
... func2(x) # OK as long as def for func2() is
# executed before func1() is called
...
>>> def func2(x):
... print(x)
...
>>> func1()
10
>>> def maker(x):
... def action(y):
... return x ** y
... return action
...
>>>
>>> f = maker(2)
>>> f
<function maker.<locals>.action at 0x7f69aa6e99d8>
>>> print(f(5)) # Nested function is remembering 2
32
>>> print(f(6))
64
>>>
>>> g = maker(3) # Changing state
>>>
>>> print(g(5)) # Each function got its own state. g got its own state
243
>>> def tester(state):
... def nested(local):
... print(state, local)
... return nested
...
>>> f = tester(0)
>>> f('hello')
0 hello
>>> f('gello')
0 gello
>>>
>>> def tester(state):
... def nested(local):
... print(state, local)
state += 1 # Can't do this. Raise error.
# Nested function can't change
# enclosing variable. Can only read.
... return nested
# Use nonlocal to change enclosing variable in a nested function.
>>> def tester(state):
... def nested(local):
... nonlocal state
... print(state, local)
... state += 1
... return nested
...
>>> f = tester(0)
>>> f('hello')
0 hello
>>> f('gello')
1 gello
>>>
>>> L = [1, 2]
>>>
>>> def changer(x):
... x[0] = 10
...
>>> changer(L)
>>> L
[10, 2] # Function can change mutable objects
>>> L = [1, 2]
>>>
>>> changer(L[:]) # Call by copying to prevent change
>>> L
[1, 2]
>>>
>>> def changer(x):
... x = x[:] # Make copy to prevent change.
... x[0] = 10
...
>>> changer(L)
>>> L
[1, 2]
>>>
>>> changer(tuple(L)) # Really prevent change. Will raise error
# in attempting change
>>> def func(a, b, c, d):
... print(a, b, c, d)
...
>>> func(1, 2, 3, 4) # Normal Call
1 2 3 4
>>>
>>> func(1, *(2, 3), 4) # Tuple unpacking
1 2 3 4
>>>
>>> func(1, **{'b': 2, 'c': 3, 'd': 4}) # Dictionary unpacking
# keyword should be matched
# with function argument
1 2 3 4
>>>
>>> func(1, *(2,), **{'c': 3, 'd': 4}) # Mixed
1 2 3 4
######################################################################
>>> def func(a, b): # Normal Arguments
... print(a, b)
...
>>> func(1, 2)
1 2
>>>
######################################################################
>>> def func(a, b = 0, c = 1): # Function with default arguments
... print(a, b, c)
...
>>> func(1)
1 0 1
>>> func(1, 2)
1 2 1
>>> func(1, 2, 3)
1 2 3
>>>
######################################################################
>>> def func(*targs): # Using Tuple. Can take variable number of argumets
... print(targs)
...
>>> func(1, 2)
(1, 2)
>>> func(1, 2, 3)
(1, 2, 3)
>>>
######################################################################
>>> def func(**dargs): # Dictionary based. Can take variable numer of arguments
... print(dargs)
...
>>> func(a = 1, b = 2) # But argumets have to be passed in key = value
# pair
{'b': 2, 'a': 1}
>>> func(a = 1, b = 2, c = 3)
{'c': 3, 'b': 2, 'a': 1}
######################################################################
>>> def func(a, *targs, **dargs): # Mixed
... print(a, targs, dargs)
...
>>> func(1, 2, 3, d = 4, e = 5)
1 (2, 3) {'e': 5, 'd': 4}
#####################################################################
# in function defination every argumet afte * are keyword only
# argumets. They have to be passed using key = value format in the
# function
>>> def func(a, *b, c): # c is keyword only argumet
... print(a, b, c)
...
>>> func(1, 2, c = 3) # c is passed using key = value format
1 (2,) 3
>>> func(1, 2, 3) # Raise error as c is keyword only
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() missing 1 required keyword-only argument: 'c'
>>>
>>> def func(a, *, c): # without variable argumet, only two argumet
... print(a, c)
...
>>> func(1, c = 3)
1 3
>>> func(1, 2, c = 3) # Raise error as 3 argumet passed instead of two
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given
Argumet order: func(normal, *tupple, keyword only, **dictionary)
General form: lambda arg1, arg2, ...: expression
>>> x = lambda a = 1, b = 2, c = 3: a + b + c
>>> x(10, 20, 30)
60
lambda is an expression not a statement. So it can be used where def can't. Like inside a list or dictionary.
>>> L = [lambda x: x ** 2, lambda x: x ** 3, lambda x: x ** 4]
>>> L[0](5)
25
>>>
>>> {'to': lambda x: x ** 2, 'lo': lambda x: x ** 3, 'mo': lambda x: x ** 4}['to'](10)
100
>>> def genSeq(N):
... for i in range(N):
... yield i ** 2
...
>>>
>>> I = iter(genSeq(3))
>>> I.__next__()
0
>>> I.__next__()
1
>>> I.__next__()
4
>>> I.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Send:
>>> def gen(n):
... for i in range(n):
... x = yield i
... print(x)
...
>>>
>>> g = gen(10)
>>> next(g)
0
>>> next(g)
None
1
>>> next(g)
None
2
>>> next(g)
None
3
>>> g.send(80)
80
4
>>> G = (x ** 2 for x in range(10))
>>> G.__next__()
0
>>> G.__next__()
1
>>> G.__next__()
4
- Both generator function and expression are their own iterators. So they can have only one active iterator. I multiple iterator is assign, they all will point to same iteration point.
>>> G = (x ** 2 for x in range(10))
>>> G is iter(G)
True
>>> it1 = iter(G)
>>> next(it1)
0
>>> next(it1)
1
>>> it2 = iter(G)
>>> next(it2)
4
Decorators are used to change any callable objects behaviour like function or class etc. There are two type of decorators. Function decorator and class decorator. One is work for function and another is work for classes. But both work in same way.
Consider this senario where a function func_decorator
is changing other
functions behaviour. This function takes other functions as argument and
change is behaviour using a wrapper function. Then this wrapper function is
assigned to the original function to change original functions behaviour.
#!/usr/bin/env python3
def func_decorator(func):
def func_wrapper(x):
print("Function " + func.__name__ + " does:")
func(x)
print("I have changed its behaviour")
return func_wrapper
def foo(x):
print("hello, " + x)
def bar(x):
print("gello, " + x)
print("Befor using func_decorator:\n")
foo("tux")
bar("tux")
foo = func_decorator(foo)
bar = func_decorator(bar)
print("\nAfter using func_decorator:\n")
foo("tux")
bar("tux")
Output:
Befor using func_decorator:
hello, tux
gello, tux
After using func_decorator:
Function foo does:
hello, tux
I have changed its behaviour
Function bar does:
gello, tux
I have changed its behaviour
We can find the same behaviour by using python decorator:
#!/usr/bin/env python3
def func_decorator(func):
def func_wrapper(x):
print("Function " + func.__name__ + " does:")
func(x)
print("I have changed its behaviour")
return func_wrapper
@func_decorator
def foo(x):
print("hello, " + x)
@func_decorator
def bar(x):
print("gello, " + x)
foo("tux")
bar("tux")
Output:
Function foo does:
hello, tux
I have changed its behaviour
Function bar does:
gello, tux
I have changed its behaviour
- Module files run only once after the first import
print("hello")
spam = 1
>>> import mod1
hello
>>> mod1.spam
1
>>> mod1.spam = 2
>>> mod1.spam
2
>>> import mod1
>>> mod1.spam # Didn't reinitialized as modules run only once
2
- If two module contains same name and both are imported via from. Then namespace will be resolved with the latest from.
def func():
print("mod1")
def func():
print("mod2")
>>> from mod1 import func
>>> from mod2 import func
>>> func()
mod2 # Resolved with the last from statement
- Import module mod which in ./dir1/dir2 location.
print("./dir1/dir2/mod.py imported")
>>> import dir1.dir2.mod
./dir1/dir2/mod.py imported
#!/bin/python
class Point:
def setX(self, x):
self.x = x
def setY(self, y):
self.y = y
def setPoint(self, x, y):
self.x = x
self.y = y
def getPoint(self):
return self.x, self.y
p = Point()
p.setX(5)
p.setY(5)
print(p.getPoint())
In class a special method __init__()
works as a constructor.
#!/bin/python
class Point:
# Constructor
def __init__(self, x, y):
print("Executing constructor!")
self.x = x
self.y = y
def getPoint(self):
return self.x, self.y
p = Point(2, 3)
print(p.getPoint())
A special method __del__
works as a destructor.
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
print("Created (%f, %f)" % (self.x, self.y))
def __del__(self):
print("Removing (%f, %f)" % (self.x, self.y))
if __name__ == "__main__":
p = Point(2, 3)
del(p)
Output:
Created (2.000000, 3.000000)
Removing (2.000000, 3.000000)
var
- Public variable. Can be accessed from outside of the class._var
- Protected variable. Can be accessed from outside of the class but it should be accessed only from the sub class.__var
- Private variable. Can be accessed only within the class.
#!/usr/bin/env python3
class Point:
""" Point class - Creates a point in 2D space """
def __init__(self, x = 0, y = 0):
""" Initiate a point object with x and y
Args:
x : x coordinate
y : y coordinate
Returns:
None
"""
self.x = x
self.y = y
# Getter for x
@property
def x(self):
""" Returns value of x coordinate"""
return self.__x
# Setter for x
@x.setter
def x(self, x):
""" Set the value of x coordinate"""
self.__x = x
# Getter for y
@property
def y(self):
"""Returns value of y coordinate"""
return self.__y
# Setter for y
@y.setter
def y(self, y):
""" Set the value of y coordinate """
self.__y = y
if __name__ == "__main__":
p = Point(2, 4)
print(p.x) # calling getter
print(p.y) # calling getter
p.x = 5 # calling setter
p.y = 3 # calling setter
print(p.x) # calling getter
print(p.y) # calling getter
Static methods can be called by both the class and an instance of the class.
Problem with normal method:
#!/usr/bin/env python3
class Skynet(object):
__id = 0
def __init__(self): # can be called only by an instance
type(self).__id += 1
def get_id(self):
return Skynet.__id
if __name__ == "__main__":
moly = Skynet()
print(moly.get_id()) # This is ok
print(Skynet.get_id()) # This will generate an error
And in this case:
#!/usr/bin/env python3
class Skynet(object):
__id = 0
def __init__(self):
type(self).__id += 1
def get_id(): # Can be called only by class itself
return Skynet.__id
if __name__ == "__main__":
moly = Skynet()
print(moly.get_id()) # will generate error
print(Skynet.get_id()) # ok
To solve this problem static method can be used:
#!/usr/bin/env python3
class Skynet(object):
__id = 0
def __init__(self):
type(self).__id += 1
@staticmethod # can be called both by class
def get_id(): # and class instance
return Skynet.__id
if __name__ == "__main__":
moly = Skynet()
print(moly.get_id()) # calling using an instance
print(Skynet.get_id()) # calling using the class
Like static methods class methods are not bound to specific instance. But take a class as the first argument.
#!/usr/bin/env python3
class Skynet(object):
__id = 0
def __init__(self):
type(self).__id += 1
@classmethod
def get_id(cls):
return cls.__id
if __name__ == "__main__":
moly = Skynet()
print(moly.get_id()) # calling using an instance
print(Skynet.get_id()) # calling using the class
class C1:
# C1 class methods
class C2:
# C2 class methods
# class C3 inherited class C1 and C2
class C3(C1, C2):
# C3 class mathods
Example:
#!/usr/bin/env python3
class Robot:
""" Robot class """
def __init__(self, name, dimension):
self.name = name
self.dimension = dimension
def __str__(self):
return "Name: " + self.name + "\n" + "Dimension: " + str(self.dimension)
class LazyRobot(Robot):
def __init__(self, name, dimension, speciality):
super().__init__(name, dimension)
self.speciality = speciality
def __str__(self):
return super().__str__() + "\n" + "Speciality: " + self.speciality
if __name__ == "__main__":
ceaser = Robot("ceaser", 5)
print(ceaser)
walle = LazyRobot("walle", 2, "waiting")
print(walle)
#!/bin/python
class Rec: pass
Rec.name = "Name"
Rec.age = 0
Rec.sex = "Sex"
# Instance of the class
x = Rec()
# Automatically inherites class attributes
print("%s | %d | %s" % (x.name, x.age, x.sex))
# Can assign its own value
x.name = "Bob"
x.age = 43
x.sex = "Male"
# Can defaine its own attributes
x.married = True
# Another instance of the class
y = Rec()
y.name = "Alice"
y.age = 19
y.sex = "Female"
y.married = False
print("%s | %d | %s | Married? %d" %(x.name, x.age, x.sex, x.married))
print("%s | %d | %s | Married? %d" %(y.name, y.age, y.sex, y.married))
Output:
Name | 0 | Sex
Bob | 43 | Male | Married? 1
Alice | 19 | Female | Married? 0
There are special methods in python with double underscore
at the begining and end like __add__
which can be used
for operator overloading. Following example shows
overloading __str__
method, which will be called when
printing the object or str(object)
:
#!/bin/python
class Person:
def __init__(self, name, job = None, pay = 0):
self.name = name
self.job = job
self.pay = pay
# Operator Overloading
# Automaticaly called when object is in print statement
def __str__(self):
return '[Person: %s, %s, %s]' % (self.name, self.job, self.pay)
# Execute when run as a script
if __name__ == '__main__':
bob = Person("Bob Smith", "Kernel Developer", "10000")
print(bob)
Output:
[Person: Bob Smith, Kernel Developer, 10000]
Here is another example overloading __add__()
method
and __str__()
method:
#!/usr/bin/env python3
class Money(object):
""" This class represents money """
def __init__(self, value, unit = "USD", rate = 1):
""" Initialize Money object
Args:
value : Money value
unit : Unit of the money. e.g: USD, BDT
rate : Exchange rate in USD
Returns:
None
"""
self.value = value
self.unit = unit
self.rate = rate
def __str__(self):
return str(self.value) + " " + self.unit
class BDT(Money):
""" This class represents Bangladesh Taka """
def __init__(self, value, rate = 0.012):
super().__init__(value, "BDT", rate)
def __add__(self, other):
"""
overloaded __add__ method for BDT
convert into dollar then add them
returns the result in BDT
"""
return BDT((self.rate * self.value \
+ other.rate * other.value) \
/ self.rate)
class EURO(Money):
"This class represents Euro"
def __init__(self, value, rate = 1.17):
super().__init__(value, "EURO", rate)
def __add__(self, other):
"""
overloaded __add__ method for EURO
convert into dollar then add them
returns the result in EURO
"""
return EURO((self.rate * self.value \
+ other.rate * other.value) \
/ self.rate)
if __name__ == "__main__":
print(BDT(5) + EURO(1) + BDT(2))
A list of python magic methods can be found here
For each binary overloading methods, there is a
reverse method. Like for __add__()
method there
is a __radd__()
method to handle situation like:
#!/usr/bin/env python3
class BDT:
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value) + " " + "BDT"
def __add__(self, other):
if type(other) == int or type(other) == float:
return BDT(self.value + other)
else:
return BDT(self.value + other.value)
if __name__ == "__main__":
print(BDT(50) + BDT(5))
print(BDT(10) + 2)
print(3 + BDT(13))
Output:
55 BDT
12 BDT
Traceback (most recent call last):
File "./radd.py", line 19, in <module>
print(3 + BDT(13))
TypeError: unsupported operand type(s) for +: 'int' and 'BDT'
This problem can be solved using reverse method. Python first search the overloaded method within the class, then the corresponding reverse method in the class. Then search the method in the parent class.
#!/usr/bin/env python3
class BDT:
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value) + " " + "BDT"
def __add__(self, other):
if type(other) == int or type(other) == float:
return BDT(self.value + other)
else:
return BDT(self.value + other.value)
def __radd__(self, value):
return self.__add__(value)
if __name__ == "__main__":
print(BDT(50) + BDT(5))
print(BDT(10) + 2)
print(3 + BDT(13))
Output:
55 BDT
12 BDT
16 BDT
Normally we can create class attributes dynamically outside of the class.
#!/usr/bin/env python3
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
if __name__ == "__main__":
p = Point(2, 3)
p.z = 4 # Dynamically adding attribute
print(p.z)
Slots are used to prevent this dynamic attribute creation.
#!/usr/bin/env python3
class Point:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
if __name__ == "__main__":
p = Point(2, 3)
# Will generate error as we have added slots in the class.
# Now the number of class attributes are fixed.
p.z = 4
print(p.z)
Output:
Traceback (most recent call last):
File "./slots.py", line 15, in <module>
p.z = 4
AttributeError: 'Point' object has no attribute 'z'
[]
- Make a list.{}
- Make a dictionary.()
- Make a Touple.if
- if blockelse
- else blockwhile
- While loopin
- Membership check- 'not' - Logical not
- 'and' - Logical and
- 'or' - Logical or
dir()
function returns a list of all the attributes of an objetc.
>>> s = "I am a string"
>>> dir(s)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
details of an object's methods or attributes can be found using help()
function.
>>> help(s.join)
Help on built-in function join:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.