Python Basics - New - Session 11 - Pages 1-141
Python Basics - New - Session 11 - Pages 1-141
for programmers…
https://www.python.org
https://conda.io/miniconda.html
Faster Python
● PyPy
● Cython (optimising static compiler)
Online IDEs REPL (Read–Eval–Print Loop)
https://try.jupyter.org/
http://www.skulpt.org/
$ pbython
ptpython
$ ptython
Python IDEs
Editors
● SublimeText 3
Python IDE
● IDLE ($ python3 -m idlelib # Or idle3)
● spyder
● PyDev (eclipse)
● pycharm
● WingIDE
Command Line Arguments and Environment Variables
Debugging tools
● pdb
objbrowser
Object size
Commonly used
PYPI: https://pypi.python.org/pypi
Warehouse: https://pypi.io/ (currently in pre-production)
The Python Package Index is a repository of software for the Python programming language
Conda repositories
● Available in py3 by default (conda does not have ensurepip module and pip installation)
○ $ pyvenv --without-pip venv3
○ $ python3 -m venv --without-pip venv3
○ $ . venv3/bin/activate # or source venv3/bin/activate.csh
○ $ wget -O - https://bootstrap.pypa.io/get-pip.py | python
○ $ pip instal ...
○ $ deactivate
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.
● help and pydoc use this attribute
● All modules should normally have docstrings
● 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.
● For consistency, always use """triple double quotes""" around docstrings.
● Use r"""raw triple double quotes""" if you use any backslashes in your docstrings.
● For Unicode docstrings, use u"""Unicode triple-quoted strings""" (from __future__ import unicode_literals)
class A(builtins.object)
| Class A.
FUNCTIONS
main(args)
Main entry point
FILE
/home/akhailta/work/Amal/Python/prog.py
Underscore: _, Double-Underscore (dunder, double-under): __
https://dbader.org/blog/meaning-of-underscores-in-python
Python Modules
$ cat mod.py
def hello(name):
print(‘Hello’, name)
Package
● Is a way of structuring Python’s module namespace by using “dotted module names”
● Is a hierarchical file directory structure that defines a single Python application environment that
consists of modules and subpackages and sub-subpackages, and so on.
sound/ # Top-level package
__init__.py # Initialize the sound package
formats/ # Subpackage for file format conversions
__init__.py
wavread.py
effects/ # Subpackage for sound effects
__init__.py # __all__ = ["echo", "surround", "reverse"]
echo.py
filters/ # Subpackage for filters
__init__.py
...
● The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to
be the list of module names that should be imported when from package import * is encountered.
$ cat sound/effects/__init__.py
>>> x = 0
>>> globals()['x'] = 10
>>> x
10
locals() → (copy of) dictionary of local variables (read-only)
Namespaces and Scopes (continued)
def f1()
# enclosing function (E)
x = 'abc' # local
global s # s top-level
print('f1() locals:', locals())
locals()['x'] = 93
print('f1() locals:', locals())
def f2():
# local inner function (L)
nonlocal x # x in f1()
global s # s top-level
y = 2
print('f2() locals:', locals())
locals()['y'] = 93
print('f2() locals:', locals())
f2()
f1()
Python Data Model (Objects)
Object
● Everything is an object
○ Object are created when needed and garbage collected when not referenced (reference counting)
● Objects have
○ Identity - is operator compares the id() of two objects (unique integer/long integer - address)
○ Type - type() returns object type # Py3 # Py2
○ Value - mutable/immutable # #
>>> a = 6 >>> a = 6
>>> a >>> a
>>> type(4) 6 6
<class 'int'> >>> >>>
>>> type(4.5) >>> print(type(a)) >>> print(type(a))
<class 'float'> <class 'int'> <type 'int'>
>>> type('abc') 5 0x7fef64776720 >>> >>>
<class 'str'> >>> a = int(6) >>> a = int(6)
>>> type([1,2,3]) >>> a >>> a
<class 'list'> 6 6
>>> type((1,2,3)) a 6 0x7fef64776740 >>> >>>
<class 'tuple'> >>> print(a.__class__) >>> print(a.__class__)
>>> type({1,2,3}) <class 'int'> <type 'int'>
<class 'set'> >>> hex(id(a)) >>> hex(id(a))
>>> type({'a':1,'b':2}) '0x7fef64776740' '0x7f97b9acd740'
<class 'dict'> >>> hex(id(6)) >>> hex(id(6))
>>> type(True) '0x7fef64776740' '0x7f97b9acd740'
<class 'bool'> >>> hex(id(5)) >>> hex(id(5))
'0x7fef64776720' '0x7f97b9acd720'
Variables
Assignment
a_number = 100
a_string = 'Error finding the results!'
Multiple assignment
a = b = c = 1
x, y, z = 55, 'string', -21
del var
Types
● None
● NotImplemented
● Ellipsis (...)
● Numbers (class numbers.Number)
○ Integral (class numbers.Integral)
■ Integer (int) :2
■ Boolean (bool) : True/False
○ Real (class numbers.Real) (float) : 3.14
○ Complex (complex) : 3.14e-10j
● Sequences
○ Immutable sequences
■ Strings/Unicode : ‘abc’, u"\N{BLACK SPADE SUIT}", ‘a’, “ABC”, ‘’’xyz’’’, “””XuX”””
■ Tuples : (33, ‘a’, [4, 7])
■ Bytes : b'abc'
○ Mutable sequences
■ Lists : [‘1’, ‘a’, [2, 3]]
■ Byte Arrays : bytearray([0x13, 0x00, 0x00, 0x00, 0x08, 0x00])
● Set types
○ Sets : {1, 2, 3, ‘a’} empty set: set()
○ Frozenset (immutable set) : frozenset([1, 2, 3, ‘a’])
● Mappings
○ Dictionaries : {‘a’: 1, ‘b’: [5, 6]}
Types (continued…)
Scalars Non-scalars
● int (2) ● sequences
● float (3.14) ○ str ‘a’, “ABC”, ‘’’xyz’’’, “””XuX”””
● bool (True, False) ■ → immutable
● NonType (None) ○ list [‘1’, ‘a’, [2, 3]]
○ tuple (33, ‘a’, [4, 7])
Operators ■ → immutable
● Assign: = ● dict {‘a’: 1, ‘b’: [5, 6]}
● Arithmetic: + - * / // % ** += -= *= /= ● set, frozenset {1, 2, 3, ‘a’}
○ 3/2=1 # *py2 ● file
○ from __future__ import division ● contextmanager (with)
○ 3 / 2 = 1.5, 3 // 2 = 1 # or py3 ● module, function, method
● Conditional: > >= < <= == != <> ● class
● Membership/identity tests: in, not in, is, is not
● Logical (boolean): and or not sequence operators:
● Bitwise: & | ^ << >> ~ ● len min max index count
● Lambda expression: lambda ● insert append pop remove reverse sort
● Conditional expression: if – else ● in not in + * [] :
● Subscription, slicing, call, attribute reference ○ [start : end : step]
○ x[index], x[index:index], x(arguments...), x.attribute ○ [::-1]
Types (continued…)
class int(x [,base]) Converts x to an integer. base specifies the base if x is a string.
class float(x) Converts x to a floating-point number.
class complex(real [,imag]) Creates a complex number.
class str(x) Converts object x to a string representation.
repr(x) Converts object x to an expression string.
eval(str, globals=None, locals=None) Evaluates a string and returns an object.
class tuple(s) Converts s to a tuple.
class list(s) Converts s to a list.
class set(s) Converts s to a set.
class dict(d) Creates a dictionary. d must be a sequence of (key,value) tuples.
class frozenset(s) Converts s to a frozen set.
chr(x) Converts an integer to a character.
unichr(x) Converts an integer to a Unicode character.
ord(x) Converts a single character to its integer value.
hex(x) Converts an integer to a hexadecimal string.
oct(x) Converts an integer to an octal string.
bin(x) Converts an integer to an binary string.
*py2
*py3
Types (continued…)
● Callable
○ User-defined functions - attrs on next page
○ Instance methods - attrs : __self__, __func__, __doc__ (__func__.__doc__), __name (__func__.__name__), __module__
○ Generator functions (yield, __next__())
○ Coroutine functions *py3
○ Built-in functions - attrs: __doc__, __name__, __module__
○ Built-in methods
○ Class types (new style classes - inherit from object)
○ Classic classes *py2
○ Class instances (implement __call__())
● Modules (import)
● Classes (new style and classic)
○ __name__, __module__, __dict__ - C.x == C.__dict__["x"] -, __bases__, __doc__
● Class instances
○ __class__, __dict__, __setattr__(), __getattr__(), __delattr__()
● I/O or File - sys.stdin, sys.stdout and sys.stderr, open()
● Internal types
○ Code (compiled byte-code)
○ Frame (execution frame, stack)
○ Traceback
○ Slices (a[i:j:step], a[i:j, k:l], or a[..., i:j], slice())
○ Static method
○ Class method
Types (continued…)
Attribute Meaning
__doc__ The function’s documentation string, or None if unavailable; not inherited by subclasses Writable
__module__ The name of the module the function was defined in, or None if unavailable. Writable
__defaults__ A tuple containing default argument values for those arguments that have defaults, or None if no arguments have a default value Writable
__code__ The code object representing the compiled function body. Writable
__globals__ A reference to the dictionary that holds the function’s global variables — the global namespace of the module in which the function Read-only
was defined.
__closure__ None or a tuple of cells that contain bindings for the function’s free variables. Read-only
__annotations__ A dict containing annotations of parameters. The keys of the dict are the parameter names, and 'return' for the return annotation, if Writable
provided.
*py2
*py3
Sequences - class str (immutable)
String operations
● 'a', "ABC", '''xyz''', """XuX"""
○ r/R → raw string
○ u/U → unicode string
○ b/B → byte string
● class str methods
○ 'capitalize', 'casefold', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs',
'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit',
'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper',
'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex',
'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip',
'swapcase', 'title', 'translate', 'upper', 'zfill'
● len() → length
● [] → slicing, sequence operations s[5:], s[:-5], s[::-1], s[::2]
● + → concatenate first_name + ' ' + last_name
● * → repetition '=' * 80
● in, not in → membership 'a' in 'Big str', 'a' not in 'Big str'
● for c in s: ... → iteration
● `obj` → repr(obj)
*py2
● % → format string (similar to c or java) 'x = %d, s = "%s"' % (10, 'abc)
*py3
Sequences - class list
List operations
● [1, 2, [4, 'aaaa'], x, dd]
● class list methods
○ 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse',
'sort'
● list() → convert sequence/iterable to list
● len() → length
● [] → slicing, sequence operations l[5:], l[:-5], l[:], l[::-1], l[::2]
● del l[?] → delete list element
● + → concatenation (extend)
● * → repetition
● in → membership
● for x in l: ... → iteration
Tuple operations
● () (1, ) ('xyz', 123, 'abc', obj1) 1, 2, 3
● class tuple methods
○ 'count', 'index'
● tuple() → convert sequence to tuple
● len() → length
● [] → slicing, sequence operations t[5:], t[:-5], t[:], t[::-1], t[::2]
● + → concatenation
● * → repetition
● in → membership
● for x in l: ... → iteration
*py2
*py3
class dictionary
*py2
*py3
class set/frozenset
Set
● {'Apple', 'Orange', 'Pear'} set(['Apple', 'Orange', 'Pear'])
● class set methods
○ 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection',
'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove',
'symmetric_difference', 'symmetric_difference_update', 'union', 'update'
● class frozenset methods
○ 'copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset',
'symmetric_difference', 'union'
● set() / frozenset() → convert sequence/iterable to set/frozenset
● s['key'] → access value
● len() → length
● del s['key'] → delete set element
issubset(other) == set <= other
● in → membership set < other == set <= other and set != other
issuperset(other) == set >= other
● for x in s: ... → iteration set > other == set >= other and set != other
● Operator equivalents union(other, ...)
intersection(other, ...)
==
==
set
set
| other | ...
& other & ...
difference(other, ...) == set - other - ...
symmetric_difference(other) == set ^ other
update(other, ...) == set |= other | ...
intersection_update(other, ...) == set &= other & ...
difference_update(other, ...) == set -= other | ...
symmetric_difference_update(other) == set ^= other
Python Language Reference
Language Reference
Notes
● DO NOT USE TABS AND DO NOT MIX TABS AND SPACES
● Use 4 spaces for indents
○ Code block with same indentation is called a suite
if expression :
suite
elif expression :
suite
else :
suite
○ Same indentation in a suite
○ Don’t mix space/tab
● Explicit line joining using ‘\’ (rarely used, not recommended)
● Comments start with ‘#’
● Multiple statements can be place on a single line joined with ‘;’ (not recommended)
● Python 2 Grammar, Python 3 Grammar
● PEP8 : Style Guide for Python Code - pycodestyle
○ PEP8 online check
○ Elements of Python Style
● PEP257: Python Docstring Conventions - pydocstyle
● Pyflakes - passive checker of Python programs
● Pylint - lint
Language Reference (continued…)
and as assert break class continue def del elif else except exec finally for from global if import in is lambda nonlocal not
or pass raise return try while with yield
Constants
False
True
None
NotImplemented
Ellipsis → …, slicing [?:?:]
__debug__ → True if python -O else: False
\newline, \\, \', \", \a, \b, \c, \f, \n, \r, \s, \t, \v, \ooo, \xhh Note: Adjacent strings are
\N{name}, \uxxxx, \Uxxxxxxxx concatenated:
\cx or \C-x → Control-x 'ABC' "DEF" → "ABCDEF"
\M-\C-x → Meta-Control-x
Language Reference (continued…)
*py2
*py3
Language Reference (continued…)
Expressions
● Arithmetic conversions
number operator complex → complex
number operator float → float
integer operator integer → integer
● Atoms
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display | generator_expression | yield_atom
○ Literals
literal ::= stringliteral | bytesliteral | integer | floatnumber | imagnumber
○ Parenthesized forms
parenth_form ::= "(" [expression_list] ")"
Language Reference (continued…)
Expressions (continued…)
● Atoms (continued)
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display | generator_expression | yield_atom
● Atoms (continued)
○ Generator expressions
generator_expression ::= "(" expression comp_for ")"
■ Generator-iterator methods
generator.__next__()
generator.send()
generator.throw(type[, value[, traceback]])
generator.close()
○ Yield expressions
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]
Language Reference (continued…)
Expressions (continued…)
# making a list the hard way # set comprehension
squares = [] primes = {x for x in range(2, 101) if all(x % y for y in range(2, min(x, 11)))}
for x in range(10):
squares.append(x**2) # making a set the hard way
prime_pairs = set()
# list comprehension for x in primes:
squares = [x**2 for x in range(10)] if x + 2 in primes:
prime_pairs.add((x, x + 2))
# dictionary comprehension
{n: 2**n for n in range(11)} # set comprehension
prime_pairs = {(x, x + 2) for x in primes if x + 2 in primes}
# making a set the hard way
primes = set() # generator using tuple () notation
for x in range(2, 101): >>> g = (x for x in range(3))
for y in range(2, min(x, 11)): >>> g.next()
if not x % y: 0
break >>> g.next()
else: 1
primes.add(x) >>> g.next()
2
# nested the hardway >>> g.next()
matrix = [[0,1,2,3], [4,5,6,7], [8,9,10,11]] Traceback (most recent call last):
flat = [] File "<stdin>", line 1, in <module>
for row in matrix:
StopIteration
for col in row:
* unpacks a list or tuple into positional arguments
flat.append(col)
** unpacks a dictionary into keyword arguments
# nested
flat = [c for row in matrix for c in row] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
transposed = [[row[c] for row in matrix] for c in range(len(row))] → list(zip(*matrix)) # [(0,4,8), (1,5,9), (2,6,10), (3,7,11)]
Language Reference (continued…)
Expressions (continued…)
# iterator # generator using function and yield
l = [1, 2, 3, 4] def fibonacci(n):
it = iter(l) a, b, counter = 0, 1, 0
while True:
# Using for loop if counter > n:
for x in it: return
print(x, end=' ') yield a
a, b = b, a + b
# Using while loop and next() counter += 1
while True:
try: # generator is an iterator object
print(next(it)) f = fibonacci(5)
except StopIteration:
break while True:
try: # Using for loop
print (next(f), end=" ") for x in f:
except StopIteration: print(x, end=' ')
break
http://www.tutorialspoint.com/python3/python_loops.htm
Language Reference (continued…)
Expressions (continued…)
● Primaries
primary ::= atom | attributeref | subscription | slicing | call
○ Attribute references
attributeref ::= primary "." identifier → module, list, instance attribute
○ Subscriptions
subscription ::= primary "[" expression_list "]" → string, tuple, list, dictionary
○ Slicing → string, tuple, list
slicing ::= primary "[" slice_list "]"
slice_list ::= slice_item ("," slice_item)* [","]
slice_item ::= expression | proper_slice
proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression s[start:end] # start to end-1
s[start:] # start to end
s[:end] # beginning to end-1
s[:] # a copy of sequence
s[::-1] # reverse sequence
● Primaries (continued)
○ Calls → callable object (function, class, method, ...)
call ::= primary "(" [argument_list [","] | comprehension] ")"
argument_list ::= positional_arguments ["," keyword_arguments]
["," "*" expression] ["," keyword_arguments]
["," "**" expression]
| keyword_arguments ["," "*" expression]
["," keyword_arguments] ["," "**" expression]
| "*" expression ["," keyword_arguments] ["," "**" expression]
| "**" expression
positional_arguments ::= expression ("," expression)*
>>> def f(a, b=1, *c, **d):
keyword_arguments ::= keyword_item ("," keyword_item)*
... print(a, b, c, d)
keyword_item ::= identifier "=" expression >>> f(1)
(1, 1, (), {})
>>> f(1, 3)
Argument (1, 3, (), {})
1. Positional arguments >>> f(1, 3, 5)
2. Positional arguments with default value (1, 3, (5,), {})
>>> f(1, 3, 5, 6)
3. Non-keyword args → tuple >>> f(1, 3, 5, 6, x=5)
4. Keyword args → dictionary (1, 3, (5, 6), {'x': 5})
>>> f(1, 3, 5, 6, x=5, y=6)
(1, 3, (5, 6), {'y': 6, 'x': 5})
Language Reference (continued…)
Expressions (continued…)
● Primaries (continued)
○ Await expression → (*py3)
await ::= ["await"] primary
○ Power operator (pow function)
power ::= await ["**" u_expr]
○ Unary arithmetic and bitwise operations
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
○ Binary arithmetic operations
m_expr ::= u_expr
| m_expr "*" u_expr | m_expr "@" m_expr
| m_expr "//" u_expr | m_expr "/" u_expr (*py3: The / (division) and // (floor division))
| m_expr "%" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
○ Shifting operations
shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr
○ Binary bitwise operations
and_expr ::= shift_expr | and_expr "&" shift_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
or_expr ::= xor_expr | or_expr "|" xor_expr
Language Reference (continued…)
Expressions (continued…)
● Primaries (continued)
○ Comparisons
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!=" | "is" ["not"] | ["not"] "in"
■ Value comparison "<" | ">" | "==" | ">=" | "<=" | "!="
■ Membership test operations "in" | "not in"
■ Identity comparison "is" | "is not"
○ Boolean operations
or_test ::= and_test | or_test "or" and_test
and_test ::= not_test | and_test "and" not_test
not_test ::= comparison | "not" not_test
○ Conditional expressions
conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr
expression_nocond ::= or_test | lambda_expr_nocond
○ Lambdas
lambda_expr ::= "lambda" [parameter_list]: expression
lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond
○ Expression lists
expression_list ::= expression ( "," expression )* [","]
Operators
Operator Operation
Boolean: and, or, not
Operator Description
Expression Statement
expression_stmt ::= expression_list
Assignment statements
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" target_list ")"
| "[" target_list "]"
| attributeref
| subscription
| slicing
| "*" target
x = [0, 1]
i = 0
i, x[i] = 1, 2 # i is updated, then x[i] is updated
a, b = b, a # swap a and b
if a:
pass
else:
x()
while True:
pass # Busy-wait for keyboard interrupt (Ctrl+C)
del
del_stmt ::= "del" target_list
d = {'a': 1, 'b': 2}
del d
Language Reference (continued…)
Statements (continued…)
print → *py2
print_stmt ::= "print" ([expression ("," expression)* [","]] | ">>" expression [("," expression)+ [","]])
import sys
print >> sys.stderr, sys.version → sys.stderr.write(sys.version + '\n')
return
return_stmt ::= "return" [expression_list]
def mygen(n):
l = range(n)
for i in l:
yield i * 2 raise IOError, "file error" # accepted in Python 2
raise IOError("file error") # accepted in Python 2
for i in mygen(4): raise IOError, "file error" # syntax error in Python 3
raise IOError("file error") # recommended in Python 3
print i
raise
raise_stmt ::= "raise" [expression ["," expression ["," expression]]]
raise SystemExit
raise RuntimeError('Something bad happened')
Language Reference (continued…)
Statements (continued…)
break
break_stmt ::= "break"
continue
continue_stmt ::= "continue"
import
import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*
| "from" relative_module "import" identifier ["as" name]
( "," identifier ["as" name] )*
| "from" relative_module "import" "(" identifier ["as" name]
( "," identifier ["as" name] )* [","] ")"
| "from" module "import" "*"
future
future_statement ::= "from" "__future__" "import" feature ["as" name]
("," feature ["as" name])*
| "from" "__future__" "import" "(" feature ["as" name]
("," feature ["as" name])* [","] ")"
feature ::= identifier
name ::= identifier
global
global_stmt ::= "global" identifier ("," identifier)*
global a, b, c
nonlocal → *py3
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
def f(a):
z = 1
def f1(b):
nonlocal z
return b + z
return a + f1(a)
if for
if_stmt ::= "if" expression ":" suite for_stmt ::= "for" target_list "in" expression_list ":"
( "elif" expression ":" suite )* suite
[ "else" ":" suite ] [ "else" ":" suite ]
while
while_stmt ::= "while" expression ":" suite
["else" ":" suite]
while cond:
# do something
else:
# do something else if cond is false
Language Reference (continued…)
Compound Statements (continued…)
try
try_stmt ::= try1_stmt | try2_stmt
try1_stmt ::= "try" ":" suite
("except" [expression [("as" | ",") identifier]] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try2_stmt ::= "try" ":" suite
"finally" ":" suite
except Myerror, err: # Python 2
except Myerror as err: # Python 3
try:
# do something except (RuntimeError, TypeError, NameError):
except Exception as e
# do some error handling # Reads file in one shot into a string
else: with open('filename.txt') as f:
# do something at the end if exceptions don’t occur data = f.read()
finally:
# cleanup code on the way out # Reads all lines and puts them in a list
with open('filename.txt') as f:
lines = f.readlines()
with → context managers (methods: __enter__/__exit__)
with_stmt ::= "with" with_item ("," with_item)* ":" suite # Reads file line by line
with_item ::= expression ["as" target] with open('filename.txt') as f:
for line in f:
print(line)
Language Reference (continued…)
Compound Statements (continued…)
class Timer(object):
def __enter__(self):
# self.start = time.clock()
self.start = time.time()
self.t1 = datetime.datetime.now()
return self
if __name__ == '__main__':
with Timer(verbose=True) as t:
with open(sys.argv[1], 'r') as f:
f.read()
Language Reference (continued…)
function # mytimeit.py
import time
class
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite
async_for_stmt ::= "async" for_stmt
async_with_stmt ::= "async" with_stmt
import asyncio
import datetime
__builtins__
● raw_input()
str = raw_input("Enter a string: ")
print("str: %s" % str)
● input()
value = input("Enter new value: ")
print("value: {}".format(value))
Builtin function open():
<file object> = open(file_name [, access_mode][, buffering])
access_mode :: ( 'r' | 'rb' | 'r+' | 'rb+' | 'w' | 'wb' | 'w+' | 'wb+' | 'a' | 'ab' | 'a+' | 'ab+' )
Attributes:
● closed, encoding, errors, line_buffering, mode, name
Methods:
● close(), flush(), isatty(), read(), readline(), readlines(), seek(), tell(), truncate(), write(), write_lines()
File Object and its Methods (continued…)
● The type of file object returned by the open() function depends on the mode.
○ When open() is used to open a file in a text mode ('w', 'r', 'wt', 'rt', etc.), it returns a subclass of io.TextIOBase
(specifically io.TextIOWrapper).
○ When used to open a file in a binary mode with buffering, the returned class is a subclass of io.BufferedIOBase.
The exact class varies: in read binary mode,
■ returns an io.BufferedReader; in write binary and append binary modes,
■ returns an io.BufferedWriter, and in read/write mode
■ returns an io.BufferedRandom.
■ When buffering is disabled, the raw stream, a subclass of io.RawIOBase, io.FileIO, is returned.
Useful File-Related modules/methods
os module functions:
● os.access(path, mode), os.chdir(path), os.chflags(path, flags), os.chmod(path, mode)
● os.chown(path, uid, gid), os.chroot(path), os.close(fd), os.closerange(fd_low, fd_high), os.dup(fd)
● os.dup2(fd, fd2), os.fchdir(fd), os.fchmod(fd, mode), os.fchown(fd, uid, gid), os.fdatasync(fd)
● os.fdopen(fd[, mode[, bufsize]]), os.fpathconf(fd, name), os.fstat(fd), os.fstatvfs(fd), os.fsync(fd)
● os.ftruncate(fd, length), os.getcwd(), os.getcwdu(), os.isatty(fd), os.lchflags(path, flags)
● os.lchmod(path, mode), os.lchown(path, uid, gid), os.link(src, dst), os.listdir(path)
● os.lseek(fd, pos, how), os.lstat(path), os.major(device), os.makedev(major, minor)
● os.makedirs(path[, mode]), os.minor(device), os.mkdir(path[, mode]), os.mkfifo(path[, mode])
● os.mknod(filename[, mode=0600, device]), os.open(file, flags[, mode]), os.openpty()
● os.pathconf(path, name), os.pipe(), os.popen(command[, mode[, bufsize]]), os.read(fd, n)
● os.readlink(path), os.remove(path), os.removedirs(path), os.rename(src, dst), os.renames(old, new)
● os.rmdir(path), os.stat(path), os.stat_float_times([newvalue]), os.statvfs(path), os.symlink(src, dst)
● os.tcgetpgrp(fd), os.tcsetpgrp(fd, pg), os.tempnam([dir[, prefix]]), os.tmpfile(), os.tmpnam()
● os.ttyname(fd), os.unlink(path), os.utime(path, times)
● os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]), os.write(fd, str)
$ python $ python
# Open file to write to $ cat f.txt # read a file in whole, return string
>>> fo = open('f.txt', 'w') Line 1 >>> with open('f.txt', 'r') as f:
>>> fo.write('Line 1\n') Line 2 ... content = f.read()
>>> fo.write('Line 2\n') Line 3
>>> fo.write('Line 3\n') >>> content
>>> fo.close() 'Line 1\nLine 2\nLine 3\n'
>>> print(c, end='')
>>> f = open('f.txt', 'r') Line 1
>>> f.name Line 2
'f.txt' Line 3
>>> f.closed
False # read a file in whole, return list of lines
>>> f.mode >>> with open('f.txt', 'r') as f:
'r' ... content = f.readlines()
>>> f.tell() ...
0 >>> content
>>> f.isatty() ['Line 1\n', 'Line 2\n', 'Line 3\n']
False
c = f.read(10)
>>> c
'Line 1\nLin'
>>> f.tell()
10
>>> f.close()
>>> <CTRL+D>
Python OOP and Class Type
New Style vs Old Style Classes
Class
● class attribute (class variable)
● class method (static method)
Instance
● instance attribute (member variable)
● instance method
Car
Delegation
● Implement new features
● Modify parent features
# py2 # py3 SportsCar Truck
class Car(object): class Car:
def __init__(self): pass def __init__(self): pass
def method(self): pass def method(self): pass
Class
Attributes
Operations
Python Class Composition (ownership - to have)
Car
Composition
(is part of) 1 1 (is part of)
(has) 4 1 (has)
# py2 # py3 Wheel Engine
class Wheel(object): class Wheel:
def __init__(self): pass def __init__(self): pass
# c.py # c.py
class C(object): class C(object): $ python c.py
# Class member variable # Class member variable 'C' object has no attribute '__obj_count'
_obj_count = 0 __obj_count = 0 type object 'C' has no attribute '__obj_count'
3
def __init__(self): def __init__(self):
# self.__class__._obj_count += 1 # self.__class__._obj_count += 1
C._obj_count += 1 C.__obj_count += 1
@property @property
def obj_count(self): def obj_count(self):
return self._obj_count return self.__obj_count
c1 = C() c1 = C()
print(c1._obj_count) try:
print(c1.__obj_count)
c2 = C() except Exception as e:
print(C._obj_count) print(e)
c3 = C() c2 = C()
print(c3.obj_count) try:
print(C.__obj_count)
except Exception as e:
$ python c.py print(e)
1
2 c3 = C()
3 print(c3.obj_count)
Special Methods
*py2
*py3
Special Methods (continued)
*py2
*py3
Special Methods (continued)
*py2
*py3
Class Variables and Class Methods
@classmethod
def static_method(cls, msg, y):
print('{} : {} - {}'.format(msg, cls._static_var, cls._static_var1))
cls._static_var1 = y
if __name__ == '__main__':
c = C(5)
print(c.x)
c.static_method('DEBUG', 20)
C.static_method('INFO', 30)
print(C._static_var1)
Private Class Members
if __name__ == '__main__':
c = C(1, 2)
print(c._protected)
try:
print(c.__private)
except Exception as e:
print(e)
print(c._C__private)
Python Instance Properties (managed attribute)
# Method 1 # Method 3
# class property([fget[, fset[, fdel[, doc]]]]) class C(object):
class C(object): def __init__(self): self._x = None
def __init__(self): self._x = None
def x(self):
def getx(self): return self._x doc = "I'm the 'x' property."
def fget(self): return self._x
def setx(self, value): self._x = value def fset(self, value): self._x = value
def fdel(self): del self._x
def delx(self): del self._x
return locals()
x = property(getx, setx, delx, "I'm the 'x' property.")
x = property(**x())
# Method 2
class C(object):
def __init__(self): self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value): self._x = value
@x.deleter
def x(self): del self._x ;
Python Instance Properties (managed attribute) - continued...
print() ; d.action()
Object Attribute Access
In a function call:
# Python2
a, b, c = range(3) # a = 0, b = 1, c = 2
# Python3
a, b, *c = range(5) # a = 0, b = 1, c = [2, 3, 4]
a, *b, c = range(5) # a = 0, b = [1, 2, 3], c = 4
# Use of the * and ** unpacking operators in literals, or multiple times in function calls
print(*range(3), *range(3)) # 0 1 2 0 1 2
http://python-future.org/
http://python-future.org/compatible_idioms.html
http://pythonhosted.org/six/
Only if you are writing python 2 and want to be compatible with python 3:
# pylint: disable=redefined-builtin,unused-wildcard-import
from builtins import *
from future import standard_library
import six
standard_library.install_aliases()
Python Standard Library
Built-in Functions
FloatingPointError
BufferError
OverflowError KeyboardInterrupt SystemExit GeneratorExit
ArithmeticError
ZeroDivisionError StopIteration
AssertionError Warning
DeprecationWarning
AttributeError
IOError
PendingDeprecationWarning
EnvironmentError
OSError
RuntimeWarning
EOFError WindowsError (Windows)
SyntaxWarning
VMSError (VMS)
ImportError
UserWarning
LookupError IndexError
FutureWarning
KeyError
MemoryError ImportWarning
NameError UnboundLocalError
UnicodeWarning
ReferenceError
BytesWarning
RuntimeError NotImplementedError
Python Modules
● File as python module
○ m.py → (import m) → __pycache__/m.pyc
● Directory as python module:
○ m/__init__.py (import m) → m/__pycache__/__init__.pyc
print(f'{__name__}, {__package__}')
"""App package"""
#!/bin/sh
if __package__ is None or __package__ == '': __author__ = 'Amal Khailtash'
from app import cli # noqa __email__ = '[email protected]' PYTHON=/opt/tools/wh/dtd/RHE64-6/python/3.6.3/bin/python
else: __version__ = '0.1.0' 3.6
from .app import cli # noqa
$ cat app_zip/app/cli.py
sys.exit(cli.main()) ${PYTHON} -m pip \
"""Command line interface.""" install --prefix ./app_zip --upgrade --requirement
app_zip/requirements.txt
# Standard libraries
import pkg_resources
${PYTHON} \
# Thirdparty libraries -m zipapp \
import click --python ${PYTHON} \
--output app_zip.pyz \
# Other libraries app_zip
from . import __author__, __version__ # noqa
# --main app:main \
def main():
print(f'{__name__}') chmod +x app_zip.pyz
print(f'Author: {__author__}, Version: {__version__}')
print(pkg_resources.resource_string(
'__main__', 'requirements.txt').decode("utf-8"))
Application/Package Directory Organization
$ cat requirements.txt
--requirements requirements/prod.txt
$ cat requirements/prod.txt
# Requirements file for production
--requirement index.txt
click==6.7
click_completion==0.2.1
click_help_colors==0.4
coloredlogs==7.3
Using virtualenv, distutils/setuptools and setup.py
parser.add_argument(
'-v', '--version', action='version', version='%(prog)s ' + __version__, Simple program that greets NAME for a total of COUNT times.
help='output version information and exit'
)
parser.add_argument('--count', type=int, help='number of greetings') optional arguments:
parser.add_argument('--name', help='the person to greet')
-h, --help show this help message and exit
argcomplete.autocomplete(parser) -v, --version output version information and exit
args = parser.parse_args()
--count COUNT number of greetings
# Use args as dictionary instead of namespace --name NAME the person to greet
# args = vars(parser.parse_args())
print(args)
if args.name is None:
name = raw_input('Your name: ')
else:
name = args.name
for x in range(count):
print('Hello %s!' % name)
Parsing Command-Line Arguments - docopt
if args['--name'] is None:
name = raw_input('Your name: ')
else:
name = args['--name']
for x in range(count):
print('Hello %s!' % name)
Parsing Command-Line Arguments - click
# If you don't want to see log messages from libraries, you can pass a
# specific logger object to the install() function. In this case only log
# messages originating from that logger will show up on the terminal.
coloredlogs.install(level='DEBUG', logger=logger)
# Some examples.
logger.debug("this is a debugging message")
logger.info("this is an informational message")
logger.warn("this is a warning message")
logger.error("this is an error message")
logger.critical("this is a critical message")
Code Style, Lint and Static Type
Checking
pep8, pyflakes, flake8, Pylint
Extensions
● nose (unittest) - alternate test discovery and running process for unittest
- similar to py.test
- many plugings
Python Testing Tools - doctest
Trying:
square(2)
# doctest_example.py Expecting:
def square(x): 4
""" Return x squared. ok
>>> square(2) Trying:
4 square(3)
Expecting:
>>> square(3)
8
9 **************
""" File "square.py", line 8, in square.square
return x ** 2 Failed example:
square(3)
Expected:
8
if __name__ == '__main__': Got:
9
import doctest 1 items had no tests:
doctest.testmod(verbose=True) square
**************
1 items had failures:
1 of 2 in square.square
2 tests in 2 items.
$ python3 -m doctest -v doctest_example.py 1 passed and 1 failed.
***Test Failed*** 1 failures.
Python Testing Tools - unittest
# unittest_unittest_example.py assertFalse
import unittest assertTrue
assertEqual
import doctest_example assertNotEqual
assertAmostEqual
class UnitTestExample(unittest.TestCase): assertAlmostNotEqual
assertCountEqual
def setUp(self): assertDictEqual
print('setUp') assertListEqual
assertMultilineEqual
def tearDown(self): assertSequenceEqual
print('tearDown') assertSetEqual
assertTupleEqual
def test(self): assertIn
x = 2 assertRaises
self.assertEqual(square(x), 4)
test_sample.py::test_answer FAILED
def test_answer(): test_square.py::test_square PASSED
assert func(3) == 5 test_square.py::test_exception PASSED
Alternative implementations:
Other options:
https://docs.python.org/3/extending/extending.html
Instant
Creates a swig interface (.i) and wrapper (.py), compiles it into .so
# ~/.cache/instant/python3.6/cache/
from instant import inline
wxform builder
Qt designer
TKinter Example
def calculate(*args):
try:
value = float(feet.get())
meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
except ValueError:
pass
root = Tk()
root.title("Feet to Meters")
feet = StringVar()
meters = StringVar()
feet_entry.focus()
root.bind('<Return>', calculate)
root.mainloop()
PyGTk Example (with glade)
import os
import sys
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
import gobject
class MainWindow(object):
def __init__(self):
self.wTree = gtk.glade.XML('feet_to_meters.glade', None, None)
self.wTree.signal_autoconnect(self)
self.mainWindow.show()
if __name__ == '__main__':
MainWindow()
gtk.main()
PyQt4 Example
#!/bin/env python
class MainWindow(QtGui.QDialog):
@QtCore.pyqtSlot()
def on_btnCalculate_clicked(self):
value = self.entFeet.text()
self.lblMeters.setText(str((0.3048 * float(value) * 10000.0 + 0.5)/10000.0))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())