The document outlines an advanced Python course covering various Python concepts like object orientation, comprehensions, extended arguments, closures, decorators, generators, context managers, classmethods, inheritance, encapsulation, operator overloading, and Python packages. The course agenda includes how everything in Python is an object, comprehension syntax, *args and **kwargs, closures and decorators, generators and iterators, context managers, staticmethods and classmethods, inheritance and encapsulation, operator overloading, and Python package layout.
2. Agenda:
1. How Everything in python is Object?
2. Comprehension (Multiple and Nested)
3. Extended Keyword Arguments(*args, **kwargs)
4. Closure and Decorators
5. Generators and Iterators Protocol
6. Context Managers
7. @staticmethod, @classmethod
8. Inheritance and Encapsulation
9. Operator Overloading
10.Python packages and Program Layout
3. 1. How Everything in python is Object?
Strings are objects. Lists are objects. Functions are objects. Even modules are objects.
everything is an object in the sense that it can be assigned to a variable or passed as an
argument to a function.
Anything you can (legally) place on the right hand side of the equals sign is (or creates) an
object in Python.
>> def hello():
>> hi = hello()
>> hi()
4. Objects
That has:
1. An Identity(id)
2. A value(mutable or immutable)
I. Mautable: When you alter the item, the id is still the same. Ex: Dictionary, List
II. Immutable: String, Integer, tuple
5.
6. 2. Comprehension
short-hand syntax for creating collections and iterable objects
1. List Comprehension => [ expr(item) for item in iterable ]
2. Set Comprehension => { expr(item) for item in iterable }
3. Dictionary Comprehension => { key_expr:value_expr for item in iterable }
4. Generator Comprehension => ( expr(item) for item in iterable)
5. If-clause => [ expr(item) for item in iterable if predicate(item) ]
6. Multiple Comprehension => [(x,y) for x in range(10) for y in range(3)]
7. Nested Comprehension => [[y*3 for y in range(x)] for x in range(10)]
7. 3. Extended Arguments
Function Review:
Def function_name(arg1, arg2=1.0,):
BODY
Arg1 => Positional Argument
Arg2 => Keyword Argument
8. Extended Formal Argument Syntax
def extended(*args, **kwargs):
=>Arguments at the function definition side.
How we use print, format function?
Ex: print(“one”)
print(“one”, “two”)
We are passing any number of argument in print statement.
9. *args => tuple
**kwargs => dict
Way of writing:
Def func(arg1, arg2, *args, kwarg1, **kwargv):
10. Extended Actual Argument Syntax
Argument at the function call side.
extended(*args, **kwargs)
Ex: t = (1, 2, 3, 4)
Def print_arg(arg1, arg2, *args):
>> print_arg(*t)
11. 4. Closure and Decorators
Local Function:
def func():
def local_func():
a = 'hello, '
b = 'world'
return a + b
x = 1
y = 2
return x + y
12. •Useful for specialized, one-off functions
•Aid in code organization and readability
•Similar to lambdas, but more general
• May contain multiple expressions
• May contain statements
Python follows LEGB Rule.
14. Closures
Maintain references to object from earlier scopes.
def outer():
x = 3
def inner(y):
return x + y
return inner
>> i = outer() >> i.__closure__
We can use __closure__ to verify function is closure or not.
15. Decorators
Modify and enhance function without changing their definition.
Implement as callables that take and return other callable.
@my_decorator
def my_function():
We can also create classes as decorators and instances as decorators.
16.
17. 5. Generators and Iterable protocol
Iterable objects can be passed to the built-in iter() function to get an iterator.
Iterator objects can be passed to the built-in next() function to fetch the next item.
iterator = iter(iterable)
item = next(iterator)
18. Generators
Python generators are a simple way of creating iterators. All the overhead we
mentioned above are automatically handled by generators in Python.
A generator is a function that returns an object (iterator) which we can iterate over
(one value at a time).
If a function contains at least one yield statement it becomes a generator function.
The difference is that, while a return statement terminates a function entirely, yield
statement pauses the function saving all its states and later continues from there
on successive calls.
19. Why generators are used in Python?
1. Easy to Implement
2. Memory Efficient
3. Represent Infinite Stream
4. Pipelining Generators
def PowTwoGen(max = 0):
n = 0
while n < max:
yield 2 ** n
n += 1
20. 6. Context Manager
context manager an object designed to be used in a with-statement.
A context-manager ensures that resources are properly and automatically
managed.
with context-manager:
context-manager.begin()
Body
context-manager.end()
21.
22. __enter__()
• called before entering with-statement body
• return value bound to as variable
• can return value of any type
• commonly returns context-manager itself
__exit__()
called when with-statement body exits
__exit__(self, exc_type, exc_val, exc_tb)
23. 7. @staticmethod, @classmethod
class attributes versus instance attributes:
Class A:
CLASS_ATTRIBUTE = 1
Def __init__(slef, instance_attribute):
Self.instance_attribute = instance_attribute
24.
25. If you need to access class attributes within the function, prefer to use
@classmethod.
If don’t need to use cls object than use @static method.
Unlike other language, In python static method can be overridden in subclass.
27. Inheritance
single inheritance:
class SubClass(BaseClass)
> Subclass will have all functionality of base class and it can also modify and
enhance.
>subclass initializer want to call base class initializer to make sense that the full
object is initialized.
28. Calling other class initializer
• Other languages automatically call base class initializers
• Python treats __init__() like any other method
• Base class __init__() is not called if overridden
• Use super() to call base class __init__()
Isinstance(instance, class): Determine if an object is of a specified type.
Issubclass(subclass, baseclass): Determine if one type is subclass of other.
29. Multiple Inheritance
Defining a class with more than one base class.
Class SubClass(Base1, Base2, …):
How does python know which base class function should call?
Python Uses Method Resolution Order and super to do that.
__bases__ => a tuple of base classes
__mro__ => a tuple of mro ordering
30. method resolution order
ordering that determines method name lookup
• Commonly called “MRO”
• Methods may be defined in multiple places
• MRO is an ordering of the inheritance graph
• Actually quite simple
31.
32.
33. 9. Operator Overloading
Python Operator work for built-in classes. But same operator behaves differently
with different types. For example, the + operator will, perform arithmetic addition
on two numbers, merge two lists and concatenate two strings.
34. Operator Expression Internally
Addition p1 + p2 p1.__add__(p2)
Subtraction p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2)
Power p1 ** p2 p1.__pow__(p2)
Less than p1 < p2 p1.__lt__(p2)
Less than or equal to p1 <= p2 p1.__le__(p2)
35. Python Package and Program Layout
Package a module which can contain other modules.
36. Sys.path list of directories Python searches for modules.
PYTHONPATH Environment variable listing paths added to sys.path .
37. 1. Packages are modules that contain other modules.
2. Packages are generally implemented as directories containing a special
__init__.py file.
3. The __init__.py file is executed when the package is imported.
4. Packages can contain sub packages which themselves are implemented
with __init__.py files in directories.
5. The module objects for packages have a __path__ attribute.
38. absolute imports: imports which use a full path to the module
from reader.reader import Reader
relative imports: imports which use a relative path to modules in the same
package.
from .reader import Reader
__all__: list of attribute names imported via from module import *