Python has greatly changed from ver. 3.x. This tutorial only deals with this version (code below has been tested with ver. 3.7).
- Where is Python on macOS ⤳
which python3.7⤳/usr/local/bin/python3.7- Where is Python on Windows ⤳
Get-Command python⤳C:\Python311\python.exe- Python shell (current directory) ⤳
>>> import os; print(os.getcwd())- Python shell (current directory) ⤳
>>> from pathlib import Path; print(Path.cwd())
- Operating System -OS- shell ⤳
python .\EA.py- Python shell ⤳
>>> exec(open("C:\\Users\\franc\\Desktop\\EA.py").read())- Python shell ⤳
>>> exit()or>>> quit()
- Update of Python ⤳ best and simpler solution is downloading the latest version and installing it…
pip install pywin32- -OR- macOS (install Node Version Manager) ⤳
python .\EA.py- macOS ⤳
import os; print(os.getcwd())
Most programming languages require a way of representing types (numbers especially) in memory. Interpreters as Python crucially rely on type representation to instrument calculations: +, -, *, /, … Rule(s)
- Python views common numbers (integers, floating point numbers…) as constructed types instead of primitive types. For example, integers are unbounded in Python.
Example
import math import sys # Integers are unbounded in Python 3.x my_int = int() print('my_int', my_int) # '0' print('Size of \'int\'', sys.getsizeof(int())) # Size (in bytes) of an *instance* of the 'int' class, namely size of '0'... # Disappeared from Python 3.x: # print('long', sys.getsizeof(long())) # Size of an *instance* of the 'long' class one_bit_set = [False, False, False, False, False, False, False, True] # 8 bits... one = int() for value in one_bit_set: one = one << 1 one = one | 1 if value else one print(bin(one)) # '0b1' two_bit_set = [False, False, False, False, False, False, True, False] two = int() for value in two_bit_set: two = two << 1 two = two | 1 if value else two print(bin(two)) # '0b10' three = int('00000011', 2) print(three) minus_nine = ~(9 - 1) print(minus_nine, bin(minus_nine)) minus_ten = ~(10 - 1) print(minus_ten, bin(minus_ten)) print(type(math.pi)) # '<class 'float'>' # https://docs.python.org/3/library/stdtypes.html#float.hex -> print(float.hex(math.pi)) # [sign] ['0x'] integer ['.' fraction] ['p' exponent] -> '0x1.921fb54442d18p+1' print(float.fromhex('0x1.921fb54442d18p+1'))Numerical stability
Rule(s)
sys.float_infoprovides information on memory representation constraints about floating point numbers.Example
# https://docs.python.org/3/library/sys.html#sys.float_info print('Max float: ', sys.float_info.max) print('Epsilon such that there is *no* \'x\' such that \'1 < x < 1 + sys.float_info.epsilon\': ', sys.float_info.epsilon) # Floating point numbers are not primitive: my_float = float() my_other_float = float() my_yet_another_float = my_float print(my_float == my_other_float) # 'True' is displayed since both are equal to '0' assert (not my_float is my_other_float) # 'is' and 'id()' are *totally* equivalent assert (my_float is my_yet_another_float) assert (not id(my_float) == id(my_other_float)) assert (id(my_float) == id(my_yet_another_float))Accessing to bytes…
Rule(s)
- In a more generic way,
bytearrayis a relevant class to deal with byte sets as internal representation of objects: strings, etc.Example
b = bytearray('ABC', 'utf-8') print(b, 'size:', len(b)) for character in b: print(bin(character)) # Display: '0b1000001' '0b1000010' '0b1000011' print('**') print(bytearray([65, 66, 67]).decode('utf-8')) # Display: 'ABC'Resource(s)
Class functions are identified by, either the @classmethodor@staticmethoddecorators. Instead of “instance functions”, class functions are called from classes themselves. As for class attributes, they are declared “as is” since “instance attributes” are declared in constructors only.Example
class Carrefour_Items: _X_ibm_client_id = os.getenv("_X_ibm_client_id") # Class attribute… _X_ibm_client_secret = os.getenv("_X_ibm_client_secret") # Class attribute… @classmethod def Get_X_ibm_client_id(Carrefour_Items_class): # First argument is implicitly the class itself… return Carrefour_Items_class._X_ibm_client_id @staticmethod def Get_X_ibm_client_secret(): # … while this is not the case here… return Carrefour_Items._X_ibm_client_secretResource(s)
Sets are here…
Although dictionaries (a.k.a. hash tables, hash maps, associative containers, etc.) are fully fledged collections, choosing a dictionary as underlying data representation structure hotly is a question of fluent data processing. More details on Python collections are here… Example
from collections import OrderedDict class Polynomial: def __init__(self, *elements): self.__representation = {} # Python common dictionary... for e in elements: # print(e) self.__representation[e[1]] = e[0] # Powers are keys... # sorted(self.__representation) # Sort on keys (ascending)... returns a list... # Required for Horner eval.: self.__representation = OrderedDict(sorted(self.__representation.items(), key=lambda pair: pair[0], reverse=True)) # Sort on keys (descending)... # print(type(self.__representation)) # '<class 'collections.OrderedDict'>' is displayed # print(self.__representation) def eval(self, x): result = 0 for key, value in self.__representation.items(): # print(key) result += pow(x, key) * value return result # https://en.wikipedia.org/wiki/Horner%27s_method def eval_Horner(self, x): # Horner method that required less multiplication stuff... prior_key = None result = 0 for key in self.__representation: if prior_key is not None: assert key < prior_key # Imposed by sorting in '__init__' # print(key) result += self.__representation.get(prior_key) for i in range(prior_key, key, -1): # print(i, end='-') result *= x prior_key = key result += self.__representation.get(prior_key) for i in range(prior_key, 0, -1): # print(i, end='-') result *= x return result p1 = Polynomial((5, 2), (-3, 1), (8, 0)) print('eval p1:', p1.eval(2)) # '22' is displayed print('eval_Horner:', p1.eval_Horner(2)) p2 = Polynomial((-12, 10), (8, 39)) print('eval p2:', p2.eval(1)) # '-4' is displayed print('eval_Horner:', p2.eval_Horner(1)) p3 = Polynomial((3, 11), (-8, 7), (-7, 1), (-43, 0)) print('eval p3:', p3.eval(5)) # '145859297' is displayed print('eval_Horner:', p3.eval_Horner(5))Resource(s)
Hash method overriding
Rule(s)
- For homemade built types acting as the type of keys in dictionaries, the overriding of the
__hash__function is mandatory along with that of the__eq__function.- As in many other programming languages, the crucial rule to be respected is:
x == y ⇒ hash(x) == hash(y).Example (homemade built type)
import re class N_INSEE: # Similar to 'static initializer' in Java: _Expression_reguliere_N_INSEE = re.compile("^\d{13}$", re.ASCII) # 're.ASCII' only allows [0-9] in excluding UNICODE digits # Improve regular expression as follows (https://fr.wikipedia.org/wiki/Num%C3%A9ro_de_s%C3%A9curit%C3%A9_sociale_en_France): # One digit sex between '1' and '2' # 2 digits birth year between '01' and '99' # 2 digits birth month between '01' and '12' # Etc @staticmethod def Format_N_INSEE(): return N_INSEE._Expression_reguliere_N_INSEE def __init__(self, valeur, clef): assert clef >= 1 and clef <= 97 # Pre-condition # print(re.findall('^\d{13}$', valeur)) self._valeur = None if N_INSEE.Format_N_INSEE().match(valeur) is not None: self._valeur = int(valeur) def __eq__(self, n_insee): # Python 3 *IMPLICITELY* implements '__ne__(self, n_insee)' while Python 2 *DOESN'T*! return self.__class__ == n_insee.__class__ and self._valeur == n_insee._valeur def __hash__(self): return hash(self._valeur) def clef(self): if self._valeur is None: raise Exception("Le N°INSEE n'est pas conforme au format " + '"^\d{13}$"') return 97 - self._valeur % 97Example (homemade built type as type of keys in ordinary dictionaries)
from N_INSEE import N_INSEE class University: def __init__(self, *students): self.__students = {} # Python common dictionary... for s in students: # print(s) self.__students[s.get_n_insee()] = s # Danger: index is based on a *HOMEMADE* built type! def count(self): return len(self.__students) def search(self, s): if s.get_n_insee() in self.__students: return True return False class Student: def __init__(self, surname, given_name, student_id, n_insee, photo=None): self._surname = surname self._given_name = given_name self._student_id = student_id self._n_insee = n_insee # Type is 'N_INSEE' # Etc. def get_n_insee(self): return self._n_insee fb1 = Student('Barbier', 'Franck', '?', N_INSEE('1630125388055', 29)) fb2 = Student('Barbier', 'Franck', '?', N_INSEE('1630125388055', 29)) u = University(fb1, fb2) print(u.count()) # '2' is displayed '__eq__(self, n_insee)' '__hash__(self)' are *NOT* overridden!Resource(s)
pip is the most famous Python library (package) manager as Maven Repository for Java or npm for JavaScript. Example (Operating System -OS- level)
# 'Carrefour_Items_requirements.txt' file beautifulsoup4 Pillow requests … # Test access and version: pip -V pip install -r Carrefour_Items_requirements.txtExample (library access and use)
from bs4 import BeautifulSoup # https://pypi.org/project/beautifulsoup4/ import os # built-in package import requests # https://pypi.org/project/requests/ … def request_Carrefour_Items(search_text): headers = { 'accept': "application/json", 'content-type': "application/json", 'x-ibm-client-id': Carrefour_Items.Get_X_ibm_client_id(), 'x-ibm-client-secret': Carrefour_Items.Get_X_ibm_client_secret() } query = "{\"queries\":[{\"query\":\"" + search_text + "\",\"field\":\"barcodeDescription\"}]}" return requests.post("https://api.fr.carrefour.io/v1/openapi/items", data=query, headers=headers).json()Resource(s)