Python Full Course
Basics
History of Python
Python was conceived in the late 1980s by Guido van Rossum. Guido was considered a Benevolent dictator for life (BDFL).

Python 3.0 final was released on December 3rd, 2008.
So please use python3 😉 #nomorepython2
Its name is based on the "Monty Python".
What is Python
Python is :
an interpreted language (in opposition to a compiled language)
source code is converted into bytecode that is then executed
strongly typed
can't perform operations inappropriate to the type, eg. in Python you can't add a number typed variable with a string typed variable
dynamically typed
you can write
a = 2and python will know thatais an Integervariables, parameters, and return values of a function can be any type. Also, the types of variables can change while the program runs.
dynamic typing makes it easy to cause unexpected errors that you can only discover until the program runs (runtime).
note : but python can now be statically typed through
type hinting
garbage collected
Why choose python then ?
/!\ opinions - be careful /!\
sweet syntax
good standard library
big community
various profesionnal applications (IT, space, maths, IA, games...)
does the job
"Our clients"
Google / Youtube
Vine (#rip)
Instagram
Reddit
Spotify
Netflix
NASA
Amazon
Every math teacher ever
ZEN of python
A collection of 19 principles that influence the conception and usage of the language.
CPython
CPython ? What is that ?
CPython is the reference implementation of the Python programming language. Written in C and Python, CPython is the default and most widely used implementation of the Python language.
CPython can be defined as both an interpreter and a compiler as it compiles Python code into bytecode before interpreting it.
mise-en-jambe
écrire un programme pseudo.py qui vous demande votre pseudo et l'affiche verticalement
exemple :
correction
Comments
Single line comments start with a # : # this is a comment
Multiline comments can be written using triple single-quotes ''' or double-quotes """.
We usually use triple-quotes """ to write documentation, also called docstrings.
Variables
You don't need to declare a variable before using it, nor its type.
A variable stores a piece of data, and gives it a specific name.
Memory management
Naming
The name of a variable should use the snake_case convention.
Reading a variable name should give you a hint about its meaning.
You should not put the type of the variable in its name.
Finally, you should NOT use reserved keywords for a variable name (eg. dict, from)
Primitive/native data types
/!\ even if it won't makes sense right now, remember that everything in python is an Object /!\
The most common types are :
numbers : integers ; floating point numbers (floats) ; complex
string
list
dict
tuple
boolean (bool) :
TrueandFalseNone,0, and empty strings/lists/dicts/tuples all evaluate toFalse
but there's a lot of other special ones :
iterators
range
bytes ; bytearray ; memoryview
frozenset
remember when we said that everything in python is an object ? all these types are objects, represented by a class.
more about what's a class later 😉
Note : all native types are available here
Casting / converting a type to another one
a variable can be converted to another type, for example :
For custom types (classes that you designed), you will have to code the operations necessary to convert your class to another one.
Operators
Python comes with a lot of operators that you can use and combine.
You can use them with variables of the same type, and also with variables of different types.
But be careful, some operations don't exist and will raise an Exception and crash your app.
is keyword
is keyword can be a little confusing and can lead to error later if not properly used.
is checks that two variables refer to the same object (memory address).
== checks if two objects have the same value.
See the difference here ?
even if the two lists have the same values, they dont have the same address
We can dig deeper with the help of the id function, which returns the memory address of an object.
None
None is an object. Always use is to compare a variable to None.
Mutability
some sequences (tuples and strings for example) are immutable which means that you can't edit them after creation.
If you wan't to edit them, you need to reassign them.
Type hinting
Python’s type hints (PEP 484) provide you with optional static typing to leverage the best of both static and dynamic typing.
Functions (intro)
functions vs procedure
A function returns a value and a procedure just executes commands.
The name function comes from math. It is used to calculate a value based on input.
A procedure is a set of commands which can be executed in order.
In most programming languages, even functions can have a set of commands. Hence the difference is only returning a value.
QUESTION : how can we declare a procedure in Python ?
we can't (lol). Procedures don't exist in Python. If a function doesn't have a
returnstatement in Python, it returnsNone.
Multi return
In C, you can only return one value. In python you can return multiple values.
But ... if the most popular implementation of Python is in C (remember CPython), how did they do it ?
Let's take a look at the following code :
In fact, when you return multiple values, in reality, a Tuple object is created (reminder: a tuple is like an immutable list object).
We can also choose to unpack those values in different variables if we need to.
declaration
A function is declared via the keywork def then the name of the function (follow the snake_case naming convention please), followed by its argument(s) between parentheses (they can be positional or keywords), eventually their types and the type of the return of the function.
Note : there is no correlation between the name of the variable inside the function and the name of the variable that you need to give during the function call.
The following concat function expects a string as an argument, this string will then be named text inside the function only.
We can then call this function, by using positional arguments :
or we can call this function by naming its arguments :
QUIZZ :
what would the call of the following function looks like ?
correction
Default arguments
A function can have multiple arguments with a default value already set.
This allows you to design your function both for casual usage and advanced usage.
But you can't use keywords arguments any way you want.
Be careful of default mutable arguments
Be careful when using default mutable arguments ...
Can you feel what's gonna be wrong with the follo code ?
QUIZZ : why is this code wrong ?
because the default argument is mutated anytime that value is mutated !
You can prevent this behaviour by setting the default argument to None.
This feature of Python is so nasty that the PEP 505 was submitted to create a new operator ??=.
This operator would replace a if ... is None.
Fun debugging times :<
Signature
The signature of a function is the list of its arguments and their types + the return type.
Here, the function f takes one argument that is a string and returns None. The argument will be named text in the function.
QUIZZ : find the signature of the built-in `print` function
use the
helpfunction :
LGI
When Python encounters a variable, it first looks if this variable is local to the function.
In this example, when the line res = text + "\n" will be interpreted, python will try to find the text variable. Here text is defined in the function so it is a local variable.
If this variable is not found locally, python will then look for it globally.
Here when the lines.append(text) will be interpreted, the lines variable won't be found locally, but is defined before the definition of the function and so is accessible inside the function. lines is a defined as a global variable in this case.
Finally, if a variable is not local nor global, python will search internally if it is one of its own variable.
Good Naming
Imagine that you're reading this line of code :
ts("obama", False, 20, True)
What about this ?
Is the comment really necessary ?
How about this ?
twitter_search(username=‘@obama’, retweets=False, numtweets=20, unicode=True)
Much better 😃 All we had to do is rename the function and rename + use keywords arguments.
Your code shouldn't need comment to explain this kind of behaviour.
This kind of code modification is called a refactoring.
Famous Acronyms
TODO bouger cette partie
One of the many times those terms will be mentioned in this course.
DRY means Don't Repeat Yourself. Don't write the same stuff in multiple places, or you will have to keep them synchronized at every change.
YAGNI means You Aren't Gonna Need It. Complexity introduced in order to solve a possible future problem that you won't necessarily have.
KISS means Keep It Simple, Stupid (the last word is actually an insult, but yeah). Avoiding unnecessary complexity will make your system more robust.

Built-in functions
Python comes with built-in functions for various purposes 😃
Here's a shortlist :
dir(obj)returns an alphabetized list of the attributeshelp(obj)returns the docstringvars(obj)returns an object's (writable) attributesrange(int)builds a sequence (is in fact a class 😉 )len(obj)returns the length of an object

Classes (intro)
wait, isn't it only the beginning of the course ? sorry again, we need to address this subject too 😃
A class is a way to encapsulate data (named fields or attributes) and functionalities (methods).
A class is a way to store a state and a behaviour.
An object is an instance of a class. For example a Car would be a class, and a peugeot_208 would be an object instance of the Car class.
The object is responsible for modifying its own internal states, the way an object refers to itself is via the keyword self.
Objects then interact with each others.
Magic methods
Also called dunder for double under methods (because they begin and end with 2 underscores _).
They're special methods that you can define to add "magic" to your classes.
Those methods are used for all kind of usage in Python.
Ever wondered how len([1,2,3]) worked ? Or why you can iterate on a dict ? How the with statement works like with open("f.txt") as f: ?
Let's dive in 😃
Here's some "famous" methods :
__repr____str____len____eq__
(Note: a huge list can be found here in plain english)
string representation (repr + str) example
<__main__.Malware object at 0x113323df0> what a weird print, isn't it ?
if you're interested in knowing why this line is formated like that, here's the source code
Scenario : imagine that we are printing some logs to debug, is this information useful ? How could we improve it ?
We could find a way to add useful and critical infos in the string representation of an instance of the Malware class.
How can we change and improve the string representation then ?
Behind the scenes, the print function is in reality calling the __str__ method of the object. If this method is not defined, the __repr__ method is called.
What's the difference between repr and str ?
__repr__goal is to be unambiguous, developer oriented, evaluable / REPRoduce__str__goal is to be readable, user friendly
Let's define the different string representations of our Malware class 😃
Functions are objects ?
wait... what ?!
Yes, you can assign an attribute to a function, let's check out its __dict__ to confirm that.
String interpolation
Python supports multiple ways to format text strings. (string interpolation, also named variable substitution)
String modulo operator
The modulo operator uses format indicators (eg. %s for string).
A shortlist of format indicators :
%s: String (performed using the str() function)%d: Integer%f: Floating point%e: Lowercase exponent%E: Uppercase exponent%x: Lowercase hexadecimal%X: Uppercase hexadecimal%o: Octal%r: Raw (performed using the repr() function)%g: Floating point for smaller numbers, lowercase exponent for larger numbers%G: Floating point for smaller numbers, uppercase exponent for larger numbers%a: ASCII (performed using the ascii() function)%c: Converts an int or a char to a character, such as 65 to the letter A
Those format indicators can be combined with flags to modify the output.
In this example, the format indicator %05d, uses the 5 flag to indicate that the integers should be formatted with 5 spaces and the 0 flag is used to pad those with zeros. Since the d portion converts the floating-point numbers to integers, four 0 are placed in front of the integers. The format indicator %.2f indicates that the float should have only 2 decimals.
str.format() method
The string format method can also use format indicators and flags !
f-string
f-string or literal string interpolation was introduced in python 3.6 and is characterized by a new prefix f.
f-strings are really powerful. In fact, they are an expression evaluated at run time, not a constant value, making them quicker than others string interpolations.
Exercice : explain the result of the previous print :]
From the specs :
>is an align format specifier, right align+is a sign format specifier, indicates that the+and-sign should be printed20is the width reserved for printing the number_is a group format specifier, indicates the caracter that should be printed to separate every 3 numbers.4is a precision format specifier, here indicates that the number should have only 4 decimalsfis a type format specifier, here for anon scientific notation
limitations
If your format strings are provided by the user, use
Template Stringsto avoid security issues.Can’t use backslashes to escape in the expression part of an f-string.
Expressions should not include comments using the # symbol
Lists
A list is a sequence object that stores an ordered sequence of objects, which can be of any types (even lists, yes).
Trying to access an invalid index results in an Exception IndexError being raised.
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[41], line 1
----> 1 random_stuff[4]
IndexError: list index out of range
One of the under-rated feature of python is its negative index ! If you want to access the last element of a list without having to calculate its size, use the -1 index !
also works for string : (but string are not lists, how does it work ? more on that later)
Slicing
Slicing is used to get a part (a slice) of a sequence. A lot of tricks can be done with slicing.
The syntax of a slice is as followed : [<start_index>:<stop_index>:<step>].
Common list methods
we can enumerate all the methods of the list object by using the dir built-in function.
But here's some commonly used :
.append(<value>)adds an element at the end of the list.pop()removes the last element of the list and returns it.remove(<value>)removes the first occurence of a value (or raises aValueErrorif the value can't be found).insert(<index>, <value>)adds an element at the given index.index(<value>)returns the index of the first occurence of a value (or raises aValueErrorif the value can't be found).sort()modify the list to sort it ascendingly.reverse()modify the list to put it in reverse order.count(<value>)returns the number of occurence of a value in the list
list built-in function
the list function converts an object to a list.
in keyword
The in keyword has two purposes:
check if a value is present in a
sequence(list, range, string etc.), returns a Booliterate through a sequence in a
forloop
len built-in function
the len function returns the length of a sequence
del keyword
use the del keyword to delete an element with its index
Common built-in functions used with lists
max(<list>)returns the maximum value in a listmin(<list>)returns the minimum value in a list
Strings
/!\ aparté /!\
speaking of text, do you use the best font FOR YOU ?
Please check codingfont.com to find out 😃
Pssss, mine is Roboto Mono 😉
a string can be seen as a list of characters (because it is a sequence) ! You can access each of its characters via their index. You can also loop on it.
Two or more string literals (i.e. the ones enclosed between quotes) next to each other are automatically concatenated.
Common string methods
use dir to list the methods of this class
<string>.join(<list>)creates a new string with each element of<list>, separated by<string>.upper()returns the string entirely in ALL CAPS.lower()returns the string entirely in lowercase.capitalize()returns the string with a Uppercase at the beginning.split(<separator>)splits the string using the separator and returns a list of string.startswith(<value>)checks if the string starts with the value.endswith(<value>)checks if the string ends with the value.replace(<old>, <new>, [count=-1])returns a copy of the string where the<old>part is replaced by the<new>part. By default,countis at-1meaning that all occurences of<old>will be replaced. If you want only the first occurence ofoldto be replaced, then setcountas1.find(<sub>)returns the first index where thesubstring is found
Ellipsis
... in python is called ellipsis. It is a string literal.
One of its main purpose is placeholding (just like pass). For example if you declare a class without attribute (like a custome Exception for example), you can use the ellipsis as a placeholder.
But the no-op instruction pass is prefered and much older than the ellipsis so use pass instead 😃
Tuples
Tuples are like lists but are immutable and are written with parenthesis.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[62], line 3
1 # if we try to edit a tuple, we'll get an error
2 immut = (1, 2, 3)
----> 3 immut[0] = 35
TypeError: 'tuple' object does not support item assignment
Really immutable ?
/!\ a tuple is immutable, but one of its item CAN be mutable
Unpacking
a sequence can be unpacked into variables.
Unpacking is a powerful tool !
Dictionaries
A dict is a key/value datastructure, created by placing a sequence of elements within curly braces {}.
Keys of a dict needs to be immutable (int, float, string, tuple). But a dict is not immutable.
You can access an element using square brackets and the key. [<key>]
When the element is nested, combined multiple square brackets.
To add or edit an element, also use square brackets + the = assign operator.
Common dict methods
.keys()returns a list of all the keys.values()returns a list of all the values.items()returns a list of tuples which are the couples ,.get(<key>, [default])returns an element for a key, if the key does not exist,Noneis returned, except if adefaultis provided.setdefault(<key>, <value>)set a default value for a key if it's not already set.update({"four":4})merges two dictionaries
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[68], line 2
1 d.get("one")
----> 2 d["blabla"]
KeyError: 'blabla'
in keyword
the in keyword can be used to check if an element is a key of a dict.
del keyword
you can use the del keyword to delete a key in a dict.
trying to delete a key that doesn't exist raises a KeyError exception.
unpacking (again!)
Since python 3.5, you can now unpack elements in a dict, resulting in a merge or an addition !
Sets
a set is a collection of unique elements. You can add multiple times the same element, but there will be only one occurence of this element in the set.
a set can be instancied with the function set or with curly braces (like a dict) {}.
a set can contain only immutable elements (strings, tuples, ints...) (like the keys of a dict). Trying to add a mutable item will result in a TypeError unhashable type 👀
Like a mathematical set, we can do mathematical operations such as intersection (&), union (|), difference (-) ...
in keyword
the in keyword can be used to check if an element exists in a set, and to iterate.
pointers, pass-by-value, pass-by-reference
A little aparté to talk about how python variables are passed between functions.
Python is "pass-by-object-reference"
This is equivalent to “object references are passed by value".
The variable is not the object itself.
source : https://stackoverflow.com/a/986145
If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it as you want, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.
If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.
Some examples of memory usage
Let's dig deeper. Take a look at the following examples and try to guess the answer
answer
answer
remember, the is keywork check if both sides are the same objects (if they have the same address)
we can verify this claim by using the id function
now what about this example :
answer
but what if we want b to be a copy of a and not a reference to it ? 😉
we can use the .copy() method (or use a trick with slicing)
but be careful, with a "simple" copy like this, we don't clone the elements in the list, we just make new pointers (we can call them labels) to them.
if you modify the new list, elements in the old list will be affected too ! this is called a shallow copy.
Let's see two examples !
In this first example, we see that editing b, the copy of a, doesn't change a. But in the second example ...
Do you know why this happens ?
the <source>.copy() method iterate over the <source> and create a new reference for each of its element (so only for the first dimension). This behaviour (problem?) arises when those elements are mutable, like lists ! Because if we mutate those lists in the copy, it is in fact the same objects that are being edited.
See this pythontutor example to better visualize !
If we really want to clone the entire list, we must create a deep copy with the copy module and its function deepcopy()
Here's another exercice (trap ?)
What's the value of `some_numbers` ?
the variable some_numbers is passed by reference and linked to the l local variable. But this local variable l is reassigned to something else, so this doesn't affect some_numbers.
the previous example can be confusing because the local variable of the function has the same name as the other variable l.
we can rewrite it for more clarity.
Let's make sure it's understood 😃
answer
you choosed answer 1, well done !
answer 2 ? yikes ! please read this chapter again 😃 (or drop an email)
range
range is a powerful function (actually its not a function but that's for another time), which can be used in various ways :
generate a sequence of numbers from
0to<stop>-1withrange(<stop>)generate a sequence of numbers from
<start>to<stop>(with an optional<step>) withrange(<start>, <stop>, [step])
(Want to see its source code ? https://github.com/python/cpython/blob/5fcfdd87c9b5066a581d3ccb4b2fede938f343ec/Objects/rangeobject.c#L76)
Want to see its C source code ?
conditions
TODO if / elif / else break continue
!=
= < <=
1 < 3 < 5
loops
for
exercice 1 : create a program that prints this "graph" with n = 4 (number of lines).
solution exercice 1
or
exercice 2 : create a program that print this "pyramid" with height = 4.
solution exercice 2
else clause
the else clause in a for loop is used when for loop DOES NOT break.
It is equivalent to a if no break.
using index to loop
If you're using the index to access an element, you're doing it (probably) wrong.
But I still want the index for some reasons !!
enumerate
the enumerate function returns a pair of elements (index, value)
But what if I want only to use one element every three ?
while
while <condition>is executing as long as its<condition>isTruecontinueis used to go to the next iteration (like a skip)breakis used to stop the loopthe
elseblock is executed when the<condition>is no longerTrue
Looping over a dict
Exercice, try to edit the dict while iterating over it !
You will encounter a RuntimeError
/!\ But remember, be careful when mutating a variable while iterating over it /!\
functions (again!)
*args and **kwargs
When a final formal parameter of the form **name is present, it receives a dictionary (see Mapping Types — dict) containing all keyword arguments except for those corresponding to a formal parameter. This may be combined with a formal parameter of the form *name (described in the next subsection) which receives a tuple containing the positional arguments beyond the formal parameter list. (*name must occur before **name.)
type annotation
Function annotations are optional metadata information about the types used by user-defined functions.
Annotations are stored in the __annotations__ attribute of the function as a dictionary and have no effect on any other part of the function.
comprehensions
A comprehension is a short syntax to construct a sequence (such as lists, set, dictionary etc).
Usually on one-line (these are called oneliners) a comprehension "can" replace multiple lines of code. (But should it ??)
Exercice :
with a list of quantities and a list of corresponding fruits, combine those two lists into one dictionary named fruits_and_quantities using a comprehension, with the fruit name as key and the quantity as value., only if the quantity is not 0.
answer
/!\ BUT, comprehensions as you can see can become very complex and narrow.
A good practice when coding comprehensions is "your comprehension should be equal to a simple sentence".
For example, a list of names without 'f'.
A bad example would be a dict where the key is in the database and the value is not a in the GET query of the RSS url provided by the user if this URL is ...
Google in its python styling guide has some interesting recommendations
modules/packages/libraries/script
a
scriptis a python file designed to be executeda
moduleis a python file designed to be importeda
packageis a directory ofmodulesalong with a__init__.pya
librarydoesn't really exist in python, but can be understood as a collection ofpackages
example : the module name A.B designates a submodule named B in a package named A
importing
when you import a module, you change the global namespace.
Using dir() without any argument shows what’s in the global namespace.
When we import for example math this way import math, we place (or replace if it was already defined) math in the global namespace.
If we don't want to "pollute" our global namespace, we can select only certain elements of a module. For example we can only import pi from math with from math import pi. Out global namespace will now contain pi and not math.
If what we want to import has a name that is too generic for our usecase, for example now, we can rename our import with the as statement : from math import pi as math_pi.
Prefer importing the module entirely rateher than selecting only certain things from the module.
Also, use a tool like isort to automaticcaly sort your imports.
Relative imports
Do not use relative names in imports, use absolute imports.
That is, if your app has multiple folders (modules), do not use from ..app.database import db.
Python has some mechanisms to import from the top of your app. (PYTHONPATH, etc ...)
execution
ever wondered what this code does ?
Whenever the Python interpreter reads a source file, it does two things:
it sets a few special variables like name, and then
it executes all of the code found in the file.
Here's a script example :
Now, if I import this file calc.py in another file main.py, and try to execute the main.py file
here's what happens :
The code in the calc.py file is executed too !
The if __name__ == "__main__": code is used to tell python to execute this if block only if the script is called directly.
In our case, our calc.py file can be both a module and a script if we move the interactive code in a function or in the if block :
File handling
/!\ use the with statement, except if you really know what you're doing.
The with statement is a context manager (more on that later). Basically it creates a block-scope where code can be executed (like a if block), and as soon as the execution exits this block (during an error for example), some logic is executed.
For example, a naive way to open and close a text file in python is :
The problem with this naive way, is that if during the "do stuff" code, something bad happens and an exception is thrown, the file will not be closed !
To avoid this scenario, use the with statement.
.read() method
Be careful when using the .read() method on a file, if you don't specify a size (an optional argument of the read method), the entire content of the file will be returned in a single string. If this file is multiple gigabytes, your RAM won't survive.
There are multiple ways to read a file chunk by chunk to avoid memory exhaustion and slow performance.
Other kind of files
Now that you learned about the with statement, other kind of files can be used with this with statement.
Good practices
(I prefer the term good practices than best practices ¯\_(ツ)_/¯)
Data Structures
https://www.hackerrank.com/domains/data-structures
Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming. -- Rob PIKE (https://users.ece.utexas.edu/~adnan/pike.html)
TODO
exemple evolutif avec dabord des listes, puis dico puis classe puis dataclass
Context Manager
A context manager is an object that sets up a context for code to run in, enters the context, runs the code and then exits the context.
A context manager is usually called via the with statement.
Not using a context manager
Let's take a look at the following code.
What happens if during the do stuff an error occurs and the execution is stopped ? The file won't be closed !
Another alternative could be :
How to implement a contextmanager
A context manager is an object that implements the __enter__(self) and __exit__(self, exc_type, exc_value, exc_tb) methods.
The __exit__() method has the following arguments :
exc_typeis the exception class.exc_valueis the exception instance.exc_tbis the traceback object.
The exit method should return a boolean. If True any exception raised during the with statement will be ignored. If False (the default) the exception will be re-raised.
@contextmanager
A @contextmanager decorator is present in the contextlib lib. It can be used to turn a generator (a function that yields something ) into a context manager.
Decorator
A decorator is a function that takes in a function and extend its behaviour, for example it can check its arguments or its return value, measure its execution time ...
This simple decorator has a flaw, it will mess with the introspection of the object !
We must use another decorator, wraps, from the functools standard package.
Generators
TODO xxx
Exceptions
Analogy : Imagine that you order something on the web, and during the delivery you're not at home. Error handling in this context means that the delivery company should be able to deliver your package another time/place so you can have it.
TODO
Protocol
In Python a protocol is an informal interface. Protocols are either known as an accepted truth or defined in documentation and not strictly in code1. For example, any class that implements the __container__() special method is said to follow the "container protocol." While this is an accepted truth, there is no syntax in the Python language that declares a class as following a protocol. Python classes can also implement multiple protocols.
TODO
Design patterns
TODO
a design pattern is a general repeatable solution to a commonly occurring problem in software design. A design pattern isn't a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.
Iterator Pattern
TODO
Decorator Pattern
TODO
Strategy Pattern
TODO
State Pattern
TODO
Singleton Pattern
TODO
Template Pattern
TODO
Adapter Pattern
TODO
Facade Pattern
TODO
Flyweight Pattern
TODO
Command Pattern
TODO
Abstract Factory Pattern
TODO
Composite Pattern
TODO
Advanced
OOP
TODO
functional
TODO
Threading
TODO
GIL
Testing
TODO
env
TODO
todo cours recopies pas fini ou deja fait etc
affichage print signature d'une fonction help() function __dir__ method fstring
conditions if /elif / else == != > >= < <= continue saute à l’itération suivante break stoppe la boucle
boucle si vous utilisez des index, cest que vous le faites probablement pas bien for for i in range(len(colors)): print(colors[i])
dir() help() - how to use it + how does it work (docstrings) sorted() - sorted(, key)
fonction (vs procedure) signature portée LGI anonyme DRY passage d'arguments renvoi de résultats arguments positionnels vs. arguments par mots clés twitter_search("@obama", False, 20, True) twitter_search("@obama", retweets=False, numtweets=20, popular=True)
tuples NamedTuples (subclass of tuple) unpacking : p = 'pommes', 30, 1 produit, quantite, prix = p
dictionnaires fundamental relationships, linking, counting, grouping
fichier binaire modules / package docstring
iterators
context manager with
one liner : 1 ligne de code = 1 phrase en francais
bonnes pratiques pep8 (syntaxe) pep257 pep20
python : everything is an object
decorateurs try except comprehension generateurs magic methods
DRY YAGNI
classes interfaces conventions (snake case, globals in all-caps) "pythonic" code https://www.python.org/dev/peps/pep-0008/ https://google.github.io/styleguide/pyguide.html
Voici quelques conseils pour vous aider à concevoir un script Python.
Réfléchissez avec un papier, un crayon... et un cerveau (voire même plusieurs) ! Reformulez avec des mots en français (ou en anglais) les consignes qui vous ont été données ou le cahier des charges qui vous a été communiqué. Dessinez ou construisez des schémas si cela vous aide.
Découpez en fonctions chaque élément de votre programme. Vous pourrez ainsi tester chaque élément indépendamment du reste. Pensez à écrire les docstrings en même temps que vous écrivez vos fonctions.
Quand l’algorithme estc omplexe, commentez votre code pour expliquer votre raisonnement. Utiliser des fonctions(ou méthodes) encore plus petites peut aussi être une solution.
Documentez-vous. L’algorithme dont vous avez besoin existe-t-il déjà dans un autre module ? Existe-t-il sous la forme de pseudo-code ? De quels outils mathématiques avez-vous besoin dans votre algorithme ?
Si vous créez ou manipulez une entité cohérente avec des propriétés propres, essayez de construire une classe.
Utilisez des noms de variables explicites, qui signifient quelquechose. En lisant votre code, on doit comprendre ce que vous faites. Choisir des noms de variables pertinents permet aussi de réduire les commentaires.
Quand vous construisez une structure de données complexe (par exemple une liste de dictionnaires contenant d’autres objets), documentez et illustrez l’organisation de cette structure de données sur un exemple simple.
Testez toujours votre code sur un jeu de données simple pour pouvoir comprendre rapidement ce qui se passe. Par exemple, une séquence de 1000 bases est plus facile à gérer que le génome humain ! Cela vous permettra également de retrouver plus facilement une erreur lorsque votre programme ne fait pas ce que vous souhaitez.
Lorsque votre programme « plante », lisez le message d’erreur. Python tente de vous expliquer ce qui ne va pas. Le numéro de la ligne qui pose problème est aussi indiqué.
Discutez avec des gens. Faites tester votre programme par d’autres. Les instructions d’utilisation sont-elles claires ?
Si vous distribuez votre code :
Rédigez une documentation claire.
Testez votre programme (jetez un œil aux tests unitaires 10).
Précisez une licence d’utilisation. Voir par exemple le site Choose an open source license
If you are ever wondering how these structures work, have a look at the following source: https://github.com/python/cpython/blob/main/Lib/collections/__init__.py
