Skip to content

Instantly share code, notes, and snippets.

@AD0791
Last active October 17, 2020 19:38
Show Gist options
  • Save AD0791/09112f626e07c4e85a29559b37583b8d to your computer and use it in GitHub Desktop.
Save AD0791/09112f626e07c4e85a29559b37583b8d to your computer and use it in GitHub Desktop.
python for developpers notes 2

Python-Dev


We have set up the learning path and the most particular features of python.

We are looking for efficiency and a quick glossary-type to retrieve and process the task or information.

dir(class_ name or module_name)
# return all the avalaible methods ,property and class avalaible
def increment(number,by=1):
  return number + by

# it's also possible case
def increment(number,by=1):
  return(number,number + by)

increment(2,3)
>>>> (2,5)

# possible type annotation (doesn't make it statistically type nevertheless)
def increment(number: int,by=1: int) -> tuple:
  return(number,number + by)

(2,5) is an instance of a tuple class (or object). A tuple is a read only list. It's iterable.

Built-in fonctions : search built-in fonction python 3 (we'll get them all)

Python has iterable !!! remember that

reverse

test = ["a", "b"]
test[::-1] # reverse

test = "ab"
test[::-1] # reverse

# dictionary looks complex. it's really a dictionary comprehensions
# come back later

We have some built-in function capable of generating object instance from a given class

  • list()
  • tuple()
  • set()
  • dict()
  • They are factory methods
  • object()
  • isinstance()
  • issubclass()

Get the size of an object

from sys import getsizeof

# Generator
values = (expression for item in iterable_object_large)
getsizeof(values) -> much smaller

Python Programming for Developers

  1. getting started
  • python implementations
  • How python code is executed
  1. Basics
  • Variables: all assignment and declaration possible
  • dynamic typing: Python doesn't have static typing
  • type annotation: it's possible to work with mypy, buit still dynamic
  • Mutable and Immutable types: memory allocation are different
  • String: each strings is an instance of the clrass str
  • Escape Sequences: multiple line string with triple quotes
  • Formatted Strings: string interpolation, interpolation = 10 f"{interpolation}"
  • Usefull string methods: Inherited from the class str
  • Numbers: int, float, binaries, hexodecimals, complex Numbers
  • Arithmetics Operators: the basics 4 (+,*,-,/), // return the floor part of the division results, modulo %', power **, x(+,*,-,/,//,%,**)= 1
  • Working with Numbers: no constant in python it's just a naming convention, usefull built-in fonctions, the math module
  • type conversion: int(), float(), bool(), str(), Falsy values
  • conditional statements: if, else, elif
  • Ternary Operator: message = "Eligible" if age > 18 else "Not Eligible"
  • For Loops: for x in str_instance:, for x in list_instance:, for x in range(number): range(number) -> 0,...,number-1 = instance of range class, for key in dictionay_instance: a dictionary is iterable on a multiple way.
  • For Else: for var in **iterable_instance: <block><break> else: <block>**
  • While Loops: while <condition>: you can had a else clause that will be executed when the while loop is done.
  • Functon: def function_name(parameter_list): pass, a function always a default return value, understand the return keyword of a function, type annotation is possible if you use mypy
  • Arguments xargs: Multiple arguments, def mutliply(*parameters): *parameters, all the arguments we will be put inside a tuple, A tuple is iterable (read-only)
  • Arguments xxargs: A variation of the concept of Multiple arguments, def user(\**user): , now we can add multiple keyword arguments, it return dictionary with the parameters as the keys and their arguments, a dictionary is iterable
  • Scope: global scope, function scope, class scope, the global keyword make sure you avoid the possible side effects
  • debugging: pdb class, or use the ide/code editor debugging system
  • vscode trick for mac
  • fizzbuzz test
  1. Python Data Structures (list , tuples, set and dictionaries)
  • List: [] is an instance of List class,[0]*5 -> [0,0,0,0,0], [] + [] -> [], list function list(range(number))
  • Accessing Items: indexing with square bracket notation just as strings
  • Unpacking List: num= [] \n a,...,c = num, a, b = [1,2,3] -> a =1 && b=[2,3]
  • Looping over List: use an enumerate object for index, values in enumerate(list_object): ->(index, value), iterable, enumerate will return a tuple that we unpack in the index and value
  • Adding or removing items: use the list_object.methods to remove or add items, del keyword
  • Finding Object in a list: use the a list method to look for an object based on a conditional
  • Sorting List: use the list method list.sort(), sorted() built-in, list.sort() is a higher-order function && The key will accept the callback function
  • Lambda function: anonymous function, very cleaner way to add as a callback function in an higher-order function, list_instance.sort(key= lambda params:expression), we are telling python how to sort the given list if he can't
  • Map function: another higher-order function,map(lambda params:expression, list_instance), return a iterable map object, list(map(..))
  • Filter function: return a iterable filter object, filter(lambda params:expression,list_instance), higher-order function, list(filter(..))
  • List Comprehension: 1) [expression for items in list_instance] and 2) [item for item in list_instance if expression]
  • Zip function: zip([],[]) -> [(), ...,()], return a iterable zip object, list(zip(..))
  • Stacks: particular topic in a data structure and algorithm course, LIFO, list_instance list_instance.append() list_instance.pop() redirect to the last list_instance[-1], if empty if not list_instance: <code block> we looking for a falsy 0, "" or []
  • Queues: another topic in Data structures and algorithm, FIFO, list_instance can be ineffective, from collections import deque and queue = deque([]), we have more methods like queue.popleft() or queue.appendleft()
  • Tuples: read only list, point = (1,2) or point= 1, 2 point is an instance of class tuple, () + () -> (), tuple(iterable) -> tuple_instance, you can't modify a tuple but you can use concatenation to add element, unpacking is working x, y = points -> x =1 and y = 2
  • Swapping Variables: a, b = b, a but it's really unpacking a tuple a,b =b,a <=> a, b = (b,a)
  • Arrays: Dealing with large number, from array import array, it has a lot the list_class methods, array.array("i",list_instance) "i" is the typecode indicating the types
  • Sets: collection with no duplicate data, bitwise operator, first={1,2,3} second={1,4} first | second -> {1,2,3,4}, first & second -> {1}, other possible operation first - second first ^ second, They are unOrder collection no INdex, still possible to iterate and test for existence
  • Dictionaries: a collection of key-value pair, the key must be immutable types but the value can be of any types, {"x":1,"y":2} <=> dict(x=1,y=2), mutable, point[key] <=> point.get(key), iterate over dictionary for key, value in point.items(): <Block>
  • Dictionary Comprehensions: set comprehension {expression for item in iterable_object}, dictionary comprehension {x: expression for item in iterable_object}, tuple comprehensions leads to a generators object (expression for item in iterable_object) -> generator Object
  • Generator Expressions: Problem dealing with large streams of data, generator objects are iterable, (expression for item in iterable_object) -> generator Object, the size a generator will be consistant even if the iterable becomes more large
  • Unpacking Operator: similar to the spread operator in javascript, n=[] && b = [] => c = [*n, *b] -> [], we can unpack any iterable, we can unpack a string, unpacking dictionary has a particularity
  • Most repeated character test
  1. Exceptions
  • Exceptions: Error that terminate the execution of a program, Handeling exceptions to prevent program from crashing
  • Handeling Exceptions: try: <code block> except Built-in-Exception-object: <code block concerning the error> <any other code block wibe executed despite the error>
  • Handeling different exceptions: There is a module containing all the class exeptions,try: <code block> except Built-in-Exception-object: <code block concerning the error> except another-B-in-Exception-Object:<code block for the second exception> <any other code block wibe executed despite the error>, A better way to handle mutiple types of exceptions try: <code block> except(Exception_classA, Exception_ClassB): <code block for exceptions> <the rest of the program
  • Cleaning Up: some case scenario we need to add add a finally clause, try: code except ErrorClass: code else: code finally: code
  • The With statement: work with certain type of object, when you are working with files scenario, object (class) that have context management protocol class_instance.__enter__ class.__exit__ we can work with the with statement
  • Raising Exceptions: raise statement to raise an exception, raise Built-in-ErrorClass("error message"), raise by itself is costly and he did prevent the programm to crash
  • Cost of Raising Exceptions: Costly, from timeit import timeit time of execution of the code, it cost in efficiency of the run time, Raise exception if you really have to
  1. Classes, status:watch
  • Classes: allow us to create object with methods and attribute, It is a blueprint to create new object
  • Creating Classes: class NameOfClass: pass, class NameOfClass: def myfun(self): pass, seems like the file containing a class is considered a module, create an instance instance = NameOfClass(), built-in isinstance(instance, NameOfClass) to check, type(insctance) -> <class __main__.NameOfClass>
  • Constructor: set initial values for our class, __init__ is the magic method who is the constructor, class NameOfClass: def __init__(self,valueA, valueB): self.valueA = valueA self.valueB = valueB <other methods or behavior of the class>
  • Class VS Instance Attributes: instance attributes are avalaible for the instances, class attributes are only for the class, class attributes are share for all instances code_below
  • Class VS Instance Methods: mostlikely the same philosophy, factory methods are class methods that create objects
  • Magic Methods: you can see the complete list of magic methods online, use the dir(class or instance_class) to see the behavior and magic mehtods avalaible, num = 10 num.__add__(100) -> 110, num.__str__() -> "10" <=> str(num)
  • Comparing Objects: even if the objects where initialize the same way they will haev their own reference in memory, comparison magic methods will help with this purpose, we can override the magic method with we want to, most of the magic methods aren't implemented, class NameOfClass: def __magicMethods__(self,<...>): <code block>i, implement the NameOfClass.__gt__() and python will know how to deal with less than, go on the documentation to know all the comparison operator
  • Performing Arithmethic Operations: depending of the class you are using - you will mostlikely implementing the beahvior yourself def __add__(self, nameofinstance): return NameOfClass(self.varA + nameofinstance.varA, ..., self.varN+ nameofinstance.varN)
  • Making Custom COntainers: make a container for blogue content handle by a class , inside the file tagcloud.py, best practice to use you own class when the given data structure won't gives you the features that you need, nice exercice to see how powerful magic methods are
  • Private Members: i already make the construct attributes private, we have the concept for private methods and attributes to hide somme information, access them is dfficult, instance_class.__dict__ holds all the attributes of a class even the private one, cloud.__dict__ -> {'_TagCloud__tags': {'python': 51, 'r': 1, 'latex': 3, 'rdms': 1, 'nrdms': 1}} and cloud._TagCloud__tags -> {'python': 51, 'r': 1, 'latex': 3, 'rdms': 1, 'nrdms': 1}, they are still accessible
  • Properties: control over an attributes inside a class, we know that the __init__ automatically is a getter and setter, but we can implement our own getter and setter with a property, an object that help us set or get an attributes property(), a decorator @property
  • Inheritance: we know that we have the root class, A class can inherite from another class, Parent class / child class, parent class class Animal: child class class Mammal(Animal):
  • The Object Class:The object class is the base class for all object from python, built-in function to create an object object()
  • Method Overriding: overriding or replacing a method in the base class, super()
  • Multi-level Inheritance: Avoid multi-level inheritance, a good limitation is to 1 or 2 level
  • Example of Inheritance: not much than 1 or 2 level, Avoid method overriding
  • Abstract Base Classes: learn to identify abstract concept, from abc import ABC, abstractmethod, we can't extenciate an abstract class
  • Polymorphism: Many forms situation
  • Duck Typing: something about python being dynamic, you can achieve polymorphism without abstraction
  • Extending built-in types: we get the built-in objects, class Text(str): et class TreackableList(list):
  • Data Classes: class without behavior, class dealing only with data, from collections import namedtuple namedtuple() inside the collections modules -> an object class, nametuple is better suited to work with data class
  1. Modules, status:watch
  • Creating Modules: A module is a file that contain some python code, naming convention lowercase_lowercase_..., from name_module import functionOrClass -> functionOrClass, or import name_module -> name_module.functionOrClass
  • Compiled python files: __pycache__ will be created because of the module interaction we introduce, to speed up module loading
  • Modules search path: an array of all possible path look by python import module_name import sys print(sys.path)
  • Packages: a package is a container for one or more modules, import package_name.module_name -> package_name.module_name.functionOrClass, a package must have __init__.py, from package_name.module_name import functionOrClass -> functionOrClass, from package_name import module_name -> module_name.functionOrClass
  • Sub-packages: we can break down package to subpackages, __init__.py is also important, from package_name.subpackage_name.module_name import functionOrClass -> functionOrClass, from package_name.subpackage_name import module_name -> module_name.functionOrClass
  • Intra-package references: from package_name.subpackage_name import module_name <=> from ..subpackage_name import module_name -> module_name.functionOrClass
  • The dir function: get the list of method and attributes from a given object, dir(), module_name.__name__, module_name.__package__), module_name.__file__
  • Executing Modules as Scripts: if __name__ == "__main__"

Higher-order functions

  1. sort |> list_instance.sort() and sorted
  2. map
  3. filter
  4. reduce
  5. sum
  6. any
  7. all

Comprehensions

  1. List comprehensions
  • use instead 1) of list(map(..))
  • use instead 2) ofr list(filter(..))
  1. dictionary comprehensions
  2. tuple comprehensions leads to generator object
  3. set comprehensions

Stacks and Queues

  1. Stacks
  • Last In First Out
  • can use a list_instance
  • deque can also do stacks
  1. Queues
  • First In First Out
  • can use a list_instance
  • deque object to avoid memory problem
  • deque is from the collections module
  • collections has a lot of good class (Defaultdict, Counter, Deque, Namedtuple, ChainMap, OrderedDict)

array.array

  1. Performance problem
  2. Class built very similarly with The list class
  3. The type code has special meaning

Unpacking

  1. we can unpack any iterable
  2. we can unpack a string
  3. dictionary scenario:
  first = dict(x=1)
  second = dict(x=10,y=2)
  # unpacking use **dict_instnace in this case
  combo = {**first,**second, "z"=1}
  combo
  # -> {'x': 10, 'y':2, 'z':1}
  # but we woull get an error if we use the built-in dict()
  combo = dict(**first,**second,z=1)
  combo
  # -> TypeError: type object got multiple values for keyword argument 'x'
  • the value of the key x has change in the first scenario

With Statement

  1. class capable of context management protocol
  2. To be clear -> class that have two magic methods class.__enter__() and class.__exit__()
  3. The with statement work for these objects

Class

Remember to understand how to set proper association in python

Object Oriented Paradigm:

  • Encapsulation
  • Abstraction
  • Inheritance
  • Polymorphism
  1. Constructor is use to initialize an object from a class
  2. Maybe a class inside a python file automatically makes this file a module?
  3. Magic Methods avalaible for each Classes in python
  4. Class has methods or attributes, we call that behavior
  5. Instance variables, class variables, class function, instance function, private variables, private functions
  6. Seems that instance attributes and class attributes are getters and setters (automatically)
  7. read the documentation on the magic methods, most of them are inherited
  8. Most of the magic methods aren't implemented, you have to do that
  9. We don't really have a strict concept of private members
  10. Set our own getters and setters with a property object property()
  11. cleaner way, use a decorator to set the getter and setter @property
  12. Inheritance, method overriding, astract class
  13. Polymorphism

Class Attributes VS Instance Attributes

class Point:
  # class attributes
  default_color = "red"

  # constructor that define instance attributes automatically
  def __init__(self,x,y):
    self.x = x
    self.y = y
  • class Attributes are share accross all instances
  • point = Point(1,2)
  • point2 = Point(3,4)
  • point.default_color will output the same as point2.default_color
  • because It's a class Variable we can do Point.default_color

Class Methods VS Instance Methods

class Point:
  # clase attributes
  default_color = "red"

  # constructor that define instance attributes automatically
  def __init__(self,x,y):
    self.x = x
    self.y = y

  # class methods
  @classmethod
  def zero(cls):
    return cls(0,0)
    # same as Point(0,0)


  # instance method
  def draw(self):
    return f"point du repere: {self.x} and {self.y}"
  • class methods can helps us define factory methods
  • zero = Point.zero()will create an object initialize with 0 and 0
  • class __main__.zero() zero is considered a factory methods
  • I can conclude that the built in function generating objects are factory methods

Class Inheritance (method overriding)

A proper way to work with method overriding

class Animal:
  def __init__(self):
    self.age = 1

class Mammal(Animal):
  def __init__(self):
    super.__init__()
    self.weight = 2

Here, we are properly overriding the constructor. with super() we have access to the methods, attributes and the constructor inside the based class. Now we make sure that the based constructor is not comletely override.

Modules

Hierachy

  • pypi is where libraires are stored
  • package : __init__.py, contains modules and subpackages
  • subpackage: __init__.py, include inside package, contains modules
  • Modules: include package, include subpackage, contains class, contain functions
  • class: include inside modules, contains attributes and methods (functions)
  • function: include inside class, include modules, contains block of codes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment