<jupyter_start><jupyter_text>Reminder on Python> A list of definitions and memory aids for data and functions - toc: true - badges: false- comments: true- author: <NAME>- categories: [Python]  Useful informations- Variables are not typed, while objects are. - Variables address objects (strong typing).- Variable names are best in camelCase (first letter in lower case and no numbers in first) and as meaningful as possible.- In Python to identify a block of instructions, you need an identation of 4 spaces and not a tab- Small immutable objects are sometimes stored as singletons (only one possible occurrence)  Basic functions|Function|Description|Type argument(s)|Output||-|-|-|-||**help()**|Help on a function|Function name|String||**type()**|Type of a variable|All|Type||**len()**|Length|All|Int||**print()**|Print to screen|All|Exit screen||**input**("Question Text")|Retrieves value entered by user|String|All|  Types of data|Type|Example|Immutable?|Singleton?|Notes||-|-|-|-|-||**Integer**|**1**|Immutable|Possible|No loss of accuracy||**Boolean**|**True** or **False**|Immutable|Possible|No loss of accuracy||**Float**|**1.2**|Immutable|Possible|Possible loss of accuracy||**Complex**|**1+2j**|Immutable|Possible|Possible loss of accuracy||**String**|**"blah"** or **'blah'**|Immutable|Possible|||**Tuple**|**( ,)** or **( , ,)** or **,**|Immutable|Possible|||||||||**List**|**[  ,  ]**|Mutable||Stores only the references||**Dictionary**|**{ : ,  : }**|Mutable||Unordered and unchangeable keys/values||**Set**|**{ ,  }**|Mutable||Unordered and unique immutable keys|  Operators|Operator|Name|Notes||||-|-|-|-|-||**=**|Opérateur d'affectation|||||****|Comments|||||||||||**+**|Addition *or* concatenation|Int + Int = Int|**Int + Float = Float**|Text + Text = Text||**-**|Subtraction|Int - Int = Int|Int - Float = Float|||* |Multiplication|Int * Int = Int|Int * Float = Float|||**/**|Division|**Int / Int = Float**|Int / Float = Float|||||||||**%**|Modulo|Subtract from division||||**//**|Whole division|Rounded down||||** |Power|idem pow(a,b)||||**abs()**|Absolute value|||||||||||**str()**|Cast in String|str(Int) = String||||**int()**|Cast in Int|int(Float) = Int||||**float()**|Cast in Float|float(Int) = Float||||||||||**+=**|Simultaneous addition and affection||||  Logic operators|Sign|Description||-|-||**==**|equal to||**!=**|different||**<**|strictly less than||**<=**|lower than or equal to|||||**not**()|not||**and** or &|and||**or** or 'pipe'|or||**^**|or exlusive|||||element **in** myGroup|is the element in my group|  Strings (immutable)|Method|Description|Argument(s)|Output||-|-|-|-||objectString.**upper**()|All capitalized|-|Text||objectString.**capitalize**()|First letter uppercase, subsequent letters lowercase|-|Text||objectString.**strip**()|Removes spaces before and after the string|-|Text||objectString.**replace("old", "new")**|Replaces all occurrences of old with new|Text, Text|Text||objectString.**find("look")**|Returns the position of the first occurrence of the searched word or -1|Text|Int|||||||objectString.**strip(',').split(',')**|Split put each word in a list according to a fixed character (",") and thanks to strip the last "," will be deleted|-|List||**",".join(['abc', 'def'])**|Makes a string from a list according to a fixed character (e.g. here ",")|-|Text|  f string    f"blah-blah-blah {function1(variable1)} blah-blah-blah {function2(variable2)} blah-blah-blah"<jupyter_code>age = 45
name = "Paul"
gap = 10
f"In {gap} year(s), {name} will be {age + gap} year(s) old."<jupyter_output><empty_output><jupyter_text>List (mutable)    nameList = ["String", number, otherList, variable]The list does not store the objects but only the reference to the object. Its size will not vary according to the size of the referenced objects.**The index starts at 0.**Unlike text, they are modified by their methods => they are mutable. |Use|Method|Description||-|-|-||***Index***|myList[1]|Accesses the 2nd element of the list|||myList[-1]|Go to the last element of the list|||myList[1:3]|Accesses the 2nd and 3rd elements of the list|||myList.**index**(element)|Returns the index of the element||||||***Classic***|**print**(myList)|Displays the entire list|||**len**(myList)|Returns the length of a list||||||***Sorting***|myList.**sort**()|Changes myList into a sorted list instead|||**sorted**(myList)|Copy and sort myList|||myList.**copy**()|Shallow copy||||||***Add***|myList.**append**(element)|Adds the element to the end of the list|||myList.**insert**(index, element)|Add the element to the specified index and move the following elements by one index|||myList.**extend**([otherList])|Add the list otherList to the end of the first one (myList)|||||***Remove***|myList.**pop**(index)|Delete and display the element with the index as argument or the last one|||maListe.**remove**(element)|Deletes the first occurrence of an element|||**del** myList[index]|Deletes the element at the specified index||||||***String***|" ".**join**(myList)|Transforms a list into a string according to the " ", the opposite of split()||||||***Random***|random.choice(myList)|choose an element from the list|||random.choices(myList,3)|choose 3 elements in the list with throw-in|||random.sample(myList,3)|choose 3 elements from the list without throw-in|<jupyter_code>myList = [8, 5, 12, 4, 45, 7]
myList1 = [8, 5, 12, 4, 45, 7]
myList2 = myList1 # The reference to the objects are copied!
myList1[0] = 0
myList2
#hide_input
print('myList[1] =',myList[1])
print('sum(myList) =', sum(myList))
print('max(myList) =', max(myList))
myList = list(range(2))
#hide_input
print('myList =',myList)
myList.append(2)
#hide_input
print('myList =',myList)
myList.insert(1,"one half")
#hide_input
print('myList =',myList)
myList = [3, 5, 7, 6, 4, 1, 0, 2]
myList.sort()
#hide_input
print('myList =',myList)<jupyter_output>myList = [0, 1, 2, 3, 4, 5, 6, 7]<jupyter_text>Tuple (immutable)           (element,)         or  element,         => tuple singleton                   (element, element)         or (element, element,)    <= for writing long tuples on several lines        or  element, element             or  element, element,        => multiple tupleThese are sequence objects. They have the same properties as lists except that they are **immutable** => **once created they cannot be modified.**<jupyter_code>#tuple unpacking
(a, b) = [3, 4]
#hide_input
print("a =",a)
print("b =", b)
a, b = b, a
#hide_input
print("a =", a)
print("b =", b)
e = list(range(10))

# tuple unpacking : cut a list
# with the * we indicate that the length is unknown
# with the _ or "ignored" we indicate that we are not interested in the content of this variable

x, *_, y = e
#hide_input
print("x =",x)
print("y =",y)
a = [1, 2]
b = [3, 4]
z = zip(a,b)
[i for i in z]<jupyter_output><empty_output><jupyter_text>Dictionarie (mutable - immutable keys)    myDictionary = {key1:value1, key2:value2}<jupyter_code>age = {"eve":30, "ana":25, "bob":35}

listeTupleAge = [("hel",21), ("jon",41)]
dicoAge = dict(listeTupleAge)

age.update(dicoAge)
#hide_input
age
age['eve']
age.keys()    # the result is a view
age.values()  # the result is a view
for name,year in age.items():
    print(f"{name.capitalize()} is {year} years old")<jupyter_output>Eve is 30 years old
Ana is 25 years old
Bob is 35 years old
Hel is 21 years old
Jon is 41 years old<jupyter_text>Set (mutable - unordered)    {key1, key2}A set is essentially a hash table. Close to dictionaries, mutable, unordered, they store only unique keys and are optimized for membership testing.<jupyter_code>a = [1, 2, 1, 20, 1]
s = set(a)
#hide_input
s
s.add(10)
#hide_input
s
s.update([1, 3, 30])
#hide_input
s
s.discard(30)
#hide_input
s
30 in s<jupyter_output><empty_output><jupyter_text>If        if condition:        block of instructions            elif condition:        block of instructions            else:        block of instructionsIn conditional expression    Variable = valueTrue if test else valueFalseIn a test :    - False : False, 0, None, [], {}, (), ""    - True : everything else<jupyter_code>#userName = input("What's your name?")
userName = "C"

if len(userName)==1:
    print("Hello single!")
    
elif len(userName)>0:
    print("Hello", userName)
    
else:
    print("Hello World!")
y = "Hello single!" if (len(userName) == 1) else "Hello World!"
print(y)<jupyter_output>Hello single!<jupyter_text>Range(n)    range(*start, end + 1, *step)          range(0, 5, 1)     idem range(0,5)     idem range(5)     => 0, 1, 2, 3, 4<jupyter_code>x = range(2, 7, 2)
for n in x:
    print(n)<jupyter_output>2
4
6<jupyter_text>For    for element in myGroup:        instructions     for i in range(start, end + 1, step):        instructionsWith the **continue** keyword, you can indicate that you want to go directly to the next element of the loop.With the keyword **break**, we interrupt the loop.>Note: with the function **exit()**, we can stop the programme<jupyter_code>myList = [0, 3, 7, 13]

for element in myList:
    print(element)
myText = "World"

for element in myText:
    print(element)<jupyter_output>W
o
r
l
d<jupyter_text>While    while condition:        instructions        continue       ignore the following statements for this iteration        break          exit while     while True:        infinite loop        instructions        break<jupyter_code>a = list(range(1,7))

print(a)

while a:
    a.pop()
    if len(a) == 5:
        continue # ignore les instructions suivantes pour cette itération
    print(a)<jupyter_output>[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
[]<jupyter_text>Class    class ClassName():        """        documentation on several lines        """        def __init__(self, p_argument1):            self.argument1 = p_argument1                    (...)                    def __str__(self):            return "argument1 = " + str(self.argument1)                        > Important: a class is the mold of an object, it represents the **essence** of a concept or a physical object. It defines both the data characterizing this object and the actions (functions) that this object performs.> Note: a class (the mold) is instancied = an object is created according to the mold<jupyter_code># Class definition
class Ship:
    def __init__(self, model, hp, armor, damage):
        self.model = model
        self.hp = hp
        self.armor = armor
        self.damage = damage
        
    def __str__(self):
        return self.model + ", hp:" + str(self.hp) + ", armor:" + str(
            self.armor) + ", damage:" + str(self.damage)
    
# Creation of an instance of this class
ship1 = Ship("CRUISER", 1200, 100, 100)

# Print out this instance
print("ship1: ", ship1)

# Creation of an instance of this class
ship2 = Ship("FIGHTER", 300, 10, 1000)

# Print out this instance
print("ship2: ", ship2)<jupyter_output>ship1:  CRUISER, hp:1200, armor:100, damage:100
ship2:  FIGHTER, hp:300, armor:10, damage:1000<jupyter_text>Functions    def functionName(arguments):        """        documentation on several lines        """        instructions (with or without return or just pass)Document well if the function modifies the parameter passed to it<jupyter_code>def calculPerimetreTriangle (cote1, cote2, cote3):
    """
    receives three side lengths
    and returns the sum of the three
    """
    perimetre = cote1 + cote2 + cote3
    return perimetre

print(calculPerimetreTriangle(1,2,3))<jupyter_output>6<jupyter_text>You can put an optional argument with default value (not a mutable object)    def functionName(argument1, argument2, argument3=defaultvalue3):        instructions<jupyter_code>def f(a, b=10):
    print(a, b)

f(1)
f(1, 2)<jupyter_output>1 10
1 2<jupyter_text>Tuple or dictionaries in argumentsTo not have to specify the number of elements sent to the function:    Tuple    def f(*t):        print(t)    dictionary    def f(**d):        print(d)<jupyter_code>def f(*t):
    print(t)
    
f(1)
f(1, 2, 3)
def f(a, b):
    print(a, b)

L = [1, 2]
f(*L)
def f(**d):
    print(d)
    
f(nom="Dupond", prenom="Paul")<jupyter_output>{'nom': 'Dupond', 'prenom': 'Paul'}<jupyter_text>Named argumentsWhen you call the function, you can pass the arguments in the order you want, **if you name them**:    functionName(nameArgument2=valueArgument2, nameArgument1=valueArgument1) > Warning: In the function call, it is not possible to enter a positional argument after an argument named<jupyter_code>def f(a, b):
    print("a =", a,"b =", b)
    
f(b=1, a=5)
# but
f(1, 5)
# warning
#f(b=1, 5) => SyntaxError: positional argument follows keyword argument<jupyter_output>a = 5 b = 1
a = 1 b = 5<jupyter_text>Order of consumption  of argumentsThe 4 forms of arguments will be summarized, depending on how the arguments of the function have been written and how they are called :1. all "normal" arguments, called positional2. form `*args` which catches in a tuple the rest of the positional arguments3. named arguments `name=`4. form `**dargs` which catches in a dictionary the remainder of the named arguments<jupyter_code>def foo(positionalArg1, namedArg2=100, *tuplePositionalArg, **dictNamedArg):
    print(f"positionalArg1={positionalArg1}, namedArg2={namedArg2}, *tuplePositionalArg={tuplePositionalArg}, **dictNamedArg={dictNamedArg}")
foo(1)
foo(1, 2)
foo(1, 2, 3)
foo(1, 2, 3, 4, arg5=5, arg6=6)
# More logical approach : all the positional then all the named
def bar(positionalArg1, *tuplePositionalArg, namedArg2=100, **dictNamedArg):
        print(f"positionalArg1={positionalArg1}, namedArg2={namedArg2}, *tuplePositionalArg={tuplePositionalArg}, **dictNamedArg={dictNamedArg}")
bar(1)
bar(1, 2)
bar(1, 2, namedArg2=3)
bar(1, 2, 3, namedArg2=4, namedArg5=5)<jupyter_output>positionalArg1=1, namedArg2=4, *tuplePositionalArg=(2, 3), **dictNamedArg={'namedArg5': 5}<jupyter_text>Lambda functionsFunctions that we do not intend to reuse    lambda x: [function of x]You can use a lambda to access a characteristic of an object for a sort    myList.sort(key=lambda x: x.characteristic1)You can execute a lambda function on a list of arguments (x) with a **map** and see the results in a list with a **list**:    list(map(lambda x: [function of x], [list of x]))and filter the results with a filter:    list(filter(lambda x: [test on [function of x]], [list of x]))<jupyter_code>list(map(lambda x: x**2, range(10)))
list(filter(lambda x: x % 2 == 0, range(10)))
list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, range(10))))<jupyter_output><empty_output><jupyter_text>List comprehensions = For on listsWe create a list, set or dictionary according to our needs.on **l** a list    comprehesion_l = [ function(i) for i in l if test(i) ]on **s** a set    comprehesion_s = { function(i) for i in s if test(i) }on **d** a dictionary    comprehesion_d = { function(i): j for i,j in d.items() if test(i, j) }<jupyter_code>a = [1, 4, 6, 9, 13]
b = [i**2 for i in a]
#hide_input
b
name = ['Alice', 'evE', 'sonia', 'BOB']
name = [p.title() for p in name]
#hide_input
print(name)<jupyter_output>['Alice', 'Eve', 'Sonia', 'Bob']<jupyter_text>Iterator  Generator expression    iterableI = (function(x) for x in list)Simple and compact object that allows to browse an iterable object.The iterable object contains the data, the iterator object contains the mechanism to traverse it.They can be browsed only once. We recognize an iterator because it is its own iterator :     i is iter(i) => TrueThey have two methods:    * __iter()__    * __next()__<jupyter_code># list (reusable)
square = [x**2 for x in range(1_000)]
#hide_input
%timeit [x**2 for x in range(1_000)]
# iterator (more fast to build)
square2 = (x**2 for x in range(1_000))
#hide_input
%timeit (x**2 for x in range(1_000))
palindrome = (x for x in square2 if str(x) == str(x)[::-1])
list(palindrome)
generator = (x**2 for x in range(10**18) if x%17==0) 
recherche = set()
for x in generator:
    if x > 10**10:
        break
    elif str(x)[-4:] == '1316':   # with a generator, you only pay for what you use
        recherche.add(x)
#hide_input
print(recherche)<jupyter_output>{617721316, 4536561316, 3617541316, 311381316}<jupyter_text>Generator function    def functionName (arguments):        instructions        yield valueReturnFunction that returns an iterable so no memory space is used<jupyter_code>def gen(it):
    for i in it:
        if isinstance(i, int):
            yield i**2
        else:
            yield 'nan'
            
L = [1, 2, 0, '18', 'x', [11], 25]
#hide_input
print(list(gen(L)))<jupyter_output>[1, 4, 0, 'nan', 'nan', 'nan', 625]<jupyter_text>Modules and packagesA module is a Python file (.py), a package is a set of Python files (+ __init__.py).The namespace is an attribute of the module.Packages and modules are imported in the same way at the top of NoteBook    import moduleName as md    import packageName as pk        md.variableName    md.functionName    md.className    pk.filename.variableName        => perfect isolation of namespaces        Import with from (more complex) :    from nomModule import nomVariable        => risk of collision between the local variable nameVariable and the imported one    => no access to other attributes of moduleName  Package random|Method|Use||-|-||random.random()|a float between 0 and 1 (1 not included)||random.uniform(a, b)|a float between a and b (b not included)||random.randint(a, b)|an integer between a and b (included)|random.gauss(average)<jupyter_code>import random
print(random.random())
print(random.uniform(1,2))
print(random.randint(1,3))
import random
population = range(1000) 

# Number of tickets desired 
N = 10
random.sample(population,N)
def div(a,b):
    try:
        print(a/b)
    except ZeroDivisionError:
        print("oops, division by 0")
    except TypeError:
        print("oops, integers needed")
div(5,2)
div(5,0)
div("cinq",2)<jupyter_output>oops, integers needed<jupyter_text>Exceptions    try:        expression0    except nomException1:        expression1    except nomException2:        expression2    else:                on passe si aucune exception est attrapée (on n'y passe pas s'il y a un return avant)        expression3    finally:             on passe dans le finally même s'il y a un return avant        expression4  Mistrust on the floats<jupyter_code>0.3 - 0.1
0.3 - 0.1 == 0.2
# the decimal module allows to solve rounding problems, but it is a bit greedy
from decimal import Decimal

Decimal('0.3') - Decimal('0.1') == Decimal('0.2')
# the fractions module defines the Fraction symbol
from fractions import Fraction

Fraction(3, 10) - Fraction(1, 10) == Fraction(2, 10)<jupyter_output><empty_output><jupyter_text>Time mesurement<jupyter_code>import datetime
start_time = datetime.datetime.now()
print(f"Start: {start_time} microseconds")
print(f"Delay: {datetime.datetime.now() -  start_time} microseconds")<jupyter_output>Delay: 0:00:02.790415 microseconds<jupyter_text>Choosing a priority after going through an entire list    priority = 100    choice = None        for l in myList:        if tests1 and priority > 1:            choice = "1"            priority = 1        if test2 and priority > 2:            choice = "2"            priority = 2           print(choice)<jupyter_code>myList = [5, 0, 10, 7, 11, 1, 12]
priority = 100
choice = None
    
for l in myList:
    if l > 10 and priority > 1:
        choice = l
        priority = 1
    if l > 2 and priority > 2:
        choice = l
        priority = 2

print(choice)<jupyter_output>11
{'fraction_non_alphanumeric': 0.14515383430068313, 'fraction_numerical': 0.027274128101083775, 'mean_word_length': 4.379939209726444, 'pattern_counts': {'":': 3, '<': 79, '<?xml version=': 0, '>': 99, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '403524', 'license': 'Apache-2.0', 'n_tokens_mistral': 6720, 'n_tokens_neox': 6297, 'n_words': 2099, 'path': '_notebooks/2021-04-15-ReminderPython.ipynb', 'repo_name': 'CecileGallioz/blog', 'size': '19477'}