Python



Preamble

Python has greatly changed from ver. 3.x. This tutorial only deals with this version (code below has been tested with ver. 3.7).

Installation
Execution
Enterprise Architect
Headlines
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)

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)

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)

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 @classmethod or @staticmethod decorators. 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_secret

Resource(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)

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 % 97

Example (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.txt

Example (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)