exécuter une commande shell, récupérer le code retour et la sortie

Un object est une entité possédant un type, un état, et un comportement.
Un object correspondant généralement à une entité du monde réel, mais
cette entité peut être abstraite.
On parle aussi d'**instance**.

On parle aussi d”

On parle aussi d'

**état d'un objet** : ensemble de propriétés auxquelles sont associées des
valeurs.

 : ensemble de propriétés auxquelles sont associées des
valeurs.

Les variables de l'objet sont appelées des **attributs**.
le comportement d'un :term:`objet` :

relation "est une espèce de " utilisée entre une classe et une autre classe

relation « est une espèce de  » utilisée entre une classe et une autre classe

est une espèce de (classe par rapport à classe, :term:`heritage`)

instance de classe : on peut créer des objets à partir d'un type "classe"
(une classe est instanciable)

instance de classe : on peut créer des objets à partir d’un type « classe »

>>> class A: pass
...
>>> class B(A): pass
...
>>> b = B()
>>> type(b) == B
>>> isinstance(b, A) == True

>>> o = object()
>>> o
<object object at 0x7f77c9cda0d0>
>>> class C(object): pass
...
>>> class C: pass
...
>>> c = C()
>>> c.a = 3
>>> c.a
3
>>> vars(c)
{'a': 3}
>>> c.__dict__
{'a': 3}
>>> C.__dict__
{'__module__': '__main__', '__doc__': None}
>>> C.c = 5
{'c': 5, '__module__': '__main__', '__doc__': None}
>>> c.c
5
>>> c.z = 3
>>> c.z
3
{'a': 3, 'z': 3}
>>> class MaKlass:
...   def unefonction(self, x):
...     print x
...
>>> MaKlass.__dict__
{'__module__': '__main__', '__doc__': None, 'unefonction': <function unefonction at 0x7f77c5b0c488>}
>>> k = MaKlass()
>>> k.__dict__
{}
>>> def autrefonc(self, x)
  File "<stdin>", line 1
    def autrefonc(self, x)
                         ^
SyntaxError: invalid syntax
>>> def autrefonc(self, x):
...   print x
...
>>> k.autrefonc = autrefonc
{'autrefonc': <function autrefonc at 0x7f77c5b0c500>}
>>> MaKlass.unefonction(k, "toto")
toto
>>> k.unefonction("toto")
toto
>>> MaKlass.toto = "test"
>>> k.toto
'test'
>>>

>>> class A(object): pass
...
>>> A.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'A' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})
>>> class B(A):
...   b = 3
...
>>> class C(B):
...   c = 2
...
>>> c = C()
>>> o = C()
>>> o.__dict__
{}
>>> o.c
2
>>> o.b
3
>>> o.__class__
<class '__main__.C'>
>>> o.__class__.__dict__
dict_proxy({'__module__': '__main__', 'c': 2, '__doc__': None})
>>>

...
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
...
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A, B): pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution
order (MRO) for bases A, B
>>>

attributs et méthodes vus comme des ajouts dans l'espace de nommage

attributs et méthodes vus comme des ajouts dans l’espace de nommage

>>> a.a = 2
>>> def function(x):
...   print x
...
>>> a.f = function
>>> a.f("hello")
hello
>>>

affichage d'une calculette, il faut créer un type `Touche`
qui contient deux désignations : `Chiffre` et `operation`::

type operation = Plus | Moins | Divise
type touche = Chiffre of int | Memoire | Op of operation

soit, on définit un type touche, soit on ne définit pas ce type::

soit, on définit un type touche, soit on ne définit pas ce type:

type memoire = Memoire
type chiffre = Chiffre

les structures de données (int, str, list, dict...) : types de base

les structures de données (int, str, list, dict…) : types de base

class NotFoundError(Exception): 
    pass

class MaClasse:
    pass

class MaClasseDeux:
    pass
    
binding = dict(un=MaClasse, deux=MaClasseDeux)

def ma_factory(key):
    if key in binding:
        return binding[key]()
    else:
        return NotFoundError("keskece?")
        
class Wrap(object):
    def __init__(self, name, wrap):
        self.slots = ('_name', '_w')
        self._name = name or "wrapped_element"
        self._w = wrap

    def __getattr__(self, name):
        if name in self.slots:
            return getattr(self, name)
        else:
            return getattr(self._w, name)

#    def get_w(self, name):
#        return getattr(self._w, name)

#    def set_w(self, name, value):
#        return setattr(self._w, name, value)

#    _w = property (get_w, set_w)

    def __repr__(self):
        return "[W_Element %s]"% repr(self._name)

>>> class O:
...   pass
...
>>> o = O()
>>> o.a = "blah"
>>>
>>> from wrap import Wrap
>>> w = Wrap("monwrap", o)
>>> w._name
'monwrap'
>>> w._w
<__main__.O instance at 0x7fbf177aaa28>
>>> w._w.a
'blah'
>>> w.a
'blah'
>>> w.u
  File "wrap.py", line 11, in __getattr__
    return getattr(self._w, name)
AttributeError: O instance has no attribute 'u'
>>>

liste = ['blah', 'blih', 'bluh']
iterateur = liste.__iter__()
print iterateur.next()
#Traceback (most recent call last):
#  File '<stdin>', line 1, in <module>;
#StopIteration

class Iterateur:
    i = 0
    def next(self):
            if self.i <= 10: raise StopIteration
            self.i += 1
            return 2**self.i
    def __iter__(self): return self

iterateur = Iterateur()
for i in iterateur: print i

def helloworld(ob):
    print "Hello world"
    return ob

@helloworld
def myfunc():
    print "my function"

myfunc()
print myfunc

>>> def deco(func):
...    func.attr = 'decorated'
...    return func
...
>>> @deco
... def f(): pass
...
>>> f.attr
'decorated'
>>>

>>> class A(object):
...   @staticmethod
...   def my_class_method(cls):
...      # do stuff here

>>> class A:
...   pass
...
>>> type(A)
<type 'classobj'>
>>> class B(object): pass
...
>>> type(B)
<type 'type'>
>>> help(type)

>>> type(object)
>>> type(type)
>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
>>>

class MaMetaClasse(type):
  """Exemple d'une métaclasse."""
  def __new__(metacls, nom, bases, dict):
      """Création de notre classe."""
      print("On crée la classe {}".format(nom))
      return type.__new__(metacls, nom, bases, dict)

class MaClasse(object):
  __metaclass__ = MaMetaClasse

exemple : forcer l'implémentation d'un singleton avec les métaclasses

exemple : forcer l’implémentation d’un singleton avec les métaclasses

class Singleton(type):
  instance = None
  def __call__(cls, *args, **kw):
      if not cls.instance:
           cls.instance = super(Singleton, cls).__call__(*args, **kw)
      return cls.instance

class ASingleton(object):
  __metaclass__ = Singleton

  a = ASingleton()
  b = ASingleton()
  assert a is b
  print(a.__class__.__name__, b.__class__.__name__)

  class BSingleton(object):
      __metaclass__ = Singleton

  c = BSingleton()
  d = BSingleton()
  assert c is d
  print(c.__class__.__name__, d.__class__.__name__)
  assert c is not a

En python un type et une classe c'est la même chose. Une classe
est un type standard. En python tout est objet, et tout provient d'un seul objet
(qui s'appelle ``object``).

En python un type et une classe c’est la même chose. Une classe
est un type standard. En python tout est objet, et tout provient d’un seul objet
(qui s’appelle 

(qui s'appelle 

encapsulation (cacher les attributs (variables d'état)) d'un objet.

encapsulation (cacher les attributs (variables d’état)) d’un objet.

interfaces : chaque aspect d'une classe peut être vu comme une interface.

interfaces : chaque aspect d’une classe peut être vu comme une interface.

Une interface décrit un ensemble de comportements.
on peut considérer une interface comme un protocole d'utilisation d'un objet
dans un contexte donné.

on peut considérer une interface comme un protocole d’utilisation d’un objet

on peut alors créer des outils qui sauront traiter n'importe quel objet
pourvu qu'il respecte une ensemble d'interfaces.

on peut alors créer des outils qui sauront traiter n’importe quel objet
pourvu qu’il respecte une ensemble d’interfaces.

class Voiture(Prix, Turbo):
    def __init__(self, constructeur, vitesse_max=160):
        self.constructeur = constructeur
        self.vitesse_max = vitesse_max

    def roule(self):
        return "vroummm"

    def signaletique(self):
        return "constructeur : {0}, vitesse_max {1}".format(self.constructeur,
            self.vitesse_max)

>>> ma_voiture = Voiture("ma_marque", "150km/h")
>>> ma_voiture.roule()
'vroummm'
>>> ma_voiture.signaletique()
'constructeur : ma_marque, vitesse_max 150km/h'

polymorphisme : un objet apparait comme une instance d'une classe parente

polymorphisme : un objet apparait comme une instance d’une classe parente

class Turbo(object):
    def turbo(self):
        return "VRRRRROUUUMMM"

>>> v = DoDoche("marque", 160)
>>> v.get_prix()
'7000'
>>> isinstance(v, Prix)
True
>>>

la fonction ``achete_voiture()`` sera appelée indépendamment du type de l'objet,
du moment que l'objet a une méthode `get_prix()`, c'est le duck typing, qu'il
est préférable de ramener au polymorphisme d'objet, ou bien utiliser les :mod:`abc`
(abstract base classes).

 sera appelée indépendamment du type de l’objet,
du moment que l’objet a une méthode 

 sera appelée indépendamment du type de l'objet,
du moment que l'objet a une méthode 

, c’est le duck typing, qu’il
est préférable de ramener au polymorphisme d’objet, ou bien utiliser les 

, c'est le duck typing, qu'il
est préférable de ramener au polymorphisme d'objet, ou bien utiliser les 

def achete_voiture(voiture):
    if not hasattr(voiture, "get_prix"):
        raise TypeError("pas le bon type")
    return "prix de la voiture: {0} euros".format(voiture.get_prix())

class Prix(object):
    def get_prix(self):
        raise NotImplementedError

class DoDoche(Voiture):
        return "4000"

un attribut est lui-même un objet (ce qui est fréquent en python)...

un attribut est lui-même un objet (ce qui est fréquent en python)…

la fonction "property" est un élément du design de python lui-même

la fonction « property » est un élément du design de python lui-même

Les exceptions permettent de récupérer des situations où le calcul ne peut pas se poursuivre.
Dans ces cas, un récupérateur d'exceptions permet de continuer le calcul
sachant qu'une des branches a échoué.

Dans ces cas, un récupérateur d’exceptions permet de continuer le calcul
sachant qu’une des branches a échoué.

>>> assert 2 == 1
AssertionError

règle du Samouraï : une fonction doit renvoyer le résultat escompté
ou bien lever une exception

>>> def function_raise(x):
...   if not type(x) == int:
...     raise TypeError("Pas le bon type")
...   else:
...     return x + 1
...
>>> try:
...   e = function_raise("une string")
... except TypeError, e:
...   print e
...
Pas le bon type
>>

la fonction doit renvoyer des valeurs du même type (ou bien ``None``)

>>> try:
...   ma_func()
...   do_something()
... except Exception, e:
...   do_somethin_else()
...

Exemple de programme utilisant massivement la programmation par exceptions :
`tiramisu`_

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
     +-- ImportWarning
     +-- UnicodeWarning
     +-- BytesWarning

No role entry for "literal" in module "docutils.parsers.rst.languages.fr".
Using English fallback for role "literal".

No role entry for « literal » in module « docutils.parsers.rst.languages.fr ».
Using English fallback for role « literal ».

Utiliser la pile d'appels, elle se lit de bas en haut. Il est possible de
provoquer cette pile d'appels.

Utiliser la pile d’appels, elle se lit de bas en haut. Il est possible de
provoquer cette pile d’appels.

try:
    ...
except:
    import traceback
    traceback.print_exc()

else:
    bla bla
finally:
    bla bla

ne **jamais** briser la pile d'appels sans savoir précisément
ce que l'on fait, et remonter une autre exception

 briser la pile d’appels sans savoir précisément
ce que l’on fait, et remonter une autre exception

 briser la pile d'appels sans savoir précisément

...   if x == 1: raise TypeError("pas le bon type")
...   else: return "ok"
...
>>> def function2(x):
...   try:
...     return "c'est " + function(x)
...   except TypeError, e:
...     raise AssertionError("on a une autre exception là")
...
>>> try:
...   function2(1)
...   print e
...
on a une autre exception là
>>>

Le raise (ou le re-raise) est souvent utilisé pour lever une exception métier
et cacher une exception système de bas niveau.

try:
  add_s(dn, listdata)
except ldap.LDAPError, err:
  raise MyOwnError(msg + str(err))
except Exception:
  pass

"user defined exceptions"

# Exceptions for an Option
class PropertiesOptionError(AttributeError):
    "attempt to access to an option with a property that is not allowed"
    def __init__(self, msg, proptype):
        self.proptype = proptype
        super(PropertiesOptionError, self).__init__(msg)

#____________________________________________________________
# Exceptions for a Config
class ConfigError(Exception):
    """attempt to change an option's owner without a value
    or in case of `_cfgimpl_descr` is None
    or if a calculation cannot be carried out"""
    pass

class ContextError(Exception):
    """context needed but not given
    """
    pass

class ConflictError(Exception):
    "duplicate options are present in a single config"
    pass

# miscellaneous exceptions
class RequirementError(Exception):
    """a recursive loop occurs in the requirements tree
    requires
    """
    pass

class SlaveError(Exception):
    "problem with a slave's value length"
    pass

class ConstError(TypeError):
    "no uniq value in _NameSpace"
    pass

Créer le plus possible ses propres exceptions spécifiques au programme
La programmation par exception peut vite devenir un style de programmation
très utilisé. C'est assez agréable mais le réserver pour la gestion d'une situation
particulière, que ça reste une intervention pour les cas non gérés par le programme
(en général).

très utilisé. C’est assez agréable mais le réserver pour la gestion d’une situation

faire un petit projet d'interpréteur ligne de commande du jeu C+/C-

faire un petit projet d’interpréteur ligne de commande du jeu C+/C-

(raw_input renvoie une string, input essayes d'évaluer, soyez prudent...)

(raw_input renvoie une string, input essayes d’évaluer, soyez prudent…)

>>> from subprocess import call
>>> filename = input("quel fichier voulez-vous afficher ?\n")
>>> call("cat " + filename, shell=True)

>>>
>>> fh = file('test', 'w')
>>> fh.write('hello world')
>>> fh.close()
>>> content = file('test', 'r').read()
>>> content
'hello world'
>>>

Peu après l'âge de bronze vint le temps de l'interpréteur ligne de commande,
c'est-à-dire quelque chose de plus spécifique que **l'application ligne de commande**,
ou que l'utilitaire ligne de commande.

Peu après l’âge de bronze vint le temps de l’interpréteur ligne de commande,
c’est-à-dire quelque chose de plus spécifique que 

c'est-à-dire quelque chose de plus spécifique que 

Le shell unix est un bon exemple d'interpréteur ligne de commande.

Le shell unix est un bon exemple d’interpréteur ligne de commande.

Un utilitaire ligne de commande est un programme unix-like qui prend toutes
les entrées d'un coup, et qui vous renvoie une sortie d'un coup.

les entrées d’un coup, et qui vous renvoie une sortie d’un coup.

#!/usr/bin/env python
# -*- coding: utf8 -*-
"""Command line interpreter
"""
import cmd

# ____________________________________________________________
# this Cli is a model of a basic use of a simple cmd
class Cli(cmd.Cmd):
    def __init__(self):
        cmd.Cmd.__init__(self)
        self.doc_header = "Documented commands (type help <command>):"
        self.undoc_header = "Undocumented commands"
        self.prompt = "#Prompt> "
        self.intro  = """cli (command line interpreter)
(type help or ? for commands list)"""
        self.ruler = "-"
        
    def emptyline(self):
        print "Type 'exit' to finish withe the session or type ? for help."

    def default(self, line):
        print "unknown command prefix" 
        print "*** unknown syntax : %s (type 'help' for help for a list of valid commands)"%line
        self.emptyline()

    def do_exit(self, line):
        """Exits from the console"""
        return True

    def do_quit(self, line):

    def do_EOF(self, args):
        """Exit on system end of file character"""

# commands pre and post actions
#    def precmd(self, line):
#        return line
#    def postcmd(self, stop, line):
#        # if there is a problem, just return True : it stops everythings
#        stop = True
#        return stop # quit if stop == True
# program pre and post actions
#    def preloop(self):
#        # action for the beginning of the program
#        pass

#    def postloop(self):
#        # action for the end of the program
#        print "exit cli"

class HelloCli(Cli):

    def input_hello(self, line):
        return line.replace(",", " and ")

    def output_hello(self, result):
        print result

    def do_hello(self, line):
        self.output_hello("hello, " + self.input_hello(line))
        #return False # if you want to stay into the cli
        return True # if you want to exit

if __name__ == '__main__':
    prompt = HelloCli()
    prompt.cmdloop("intro, modifies Cmd.intro")

>>> from cli import Cli
>>> prompt = Cli()
>>> prompt.cmdloop()
cli (command line interpreter)
(type help or ? for commands list)
#Prompt> ?

Documented commands (type help <command>):
==========================================
EOF  exit

Undocumented commands:
======================
cmd  help  quit

#Prompt>

>>> class Prompt(Cli):
...   def do_hello(self, line):
...      print "hello %s", line
...
>>> prompt = Prompt()
#Prompt> ?

EOF  exit

cmd  hello  help  quit

#Prompt> hello world

>>> if "a":
...   print "a"
...
a
>>> if "":
...   print "hell"
...
>>> a = 2
>>> if a == 1:
...   print "un"
... else:
...   print "deux"
...
deux
>>>

>>> for i in range(10):
...   print i
...
0
1
2
3
4
5
6
7
8
9
>>>
>>> l = range(10)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> i = 10
>>> while i != 0:
...  print i
...  i = i -1
...
10
9
8
7
6
5
4
3
2
1
>>>

>>> def blabla(x):
...   """fonction qui printe"""
...   print x
...
>>>

>>> def ma_func(x):
...   "écrit quelque chose dans un fichier"
...
>>> ma_func("a")
>>> print ma_func("a")
None
>>>

...   return None

arité d'une fonction:

  - paramètre non nommé
  - paramètre nommé

>>> def ma_fonction(*args, **kwargs):
...   print "arguments : ", str(args)
...   print "argumments nommés", str(kwargs)
...
>>> ma_fonction("toto", "titi", tutu=2, tata=3)
arguments :  ('toto', 'titi')
argumments nommés {'tata': 3, 'tutu': 2}
>>>

signature d'une fonction : ça peut renvoyer n'importe quoi (tout ce qu'on veut)

signature d’une fonction : ça peut renvoyer n’importe quoi (tout ce qu’on veut)

permet de renvoyer le résultat d'une fonction en plusieurs étape
à l'aide d'un générateur

permet de renvoyer le résultat d’une fonction en plusieurs étape
à l’aide d’un générateur

>>> def ma_fonction():
...   for i in range(10):
...     yield i
...
>>> for i in ma_fonction():
...   print i
...
0
1
2
3
4
5
6
7
8
9
>>>

>>> def toto(x):
...   print vars()
...
>>> toto("sdfsdf")
{'x': 'sdfsdf'}
>>> class A(object):pass
...
>>> a = A()
>>> a.a = "titi"
>>> a.b = "toto"
>>> vars(a)
{'a': 'titi', 'b': 'toto'}

puisque tout est objet en python, ``vars(mon_objet)`` est équivalent à
``mon_objet.__dict__``

les compréhensions de listes permettent de générer de nouvelles listes

>>> [ 2*i for i in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>

>>> [(i, j) for i in range(2,5) for j in range (4,8)]
[(2, 4), (2, 5), (2, 6), (2, 7), (3, 4), (3, 5), (3, 6), (3, 7), (4, 4), (4, 5), (4, 6), (4, 7)]
>>>

>>> expr = (2*i for i in range(10))
>>> expr
<generator object <genexpr> at 0x7ff9efa77cd0>
>>> for e in expr:
...   print e
...
0
2
4
6
8
10
12
14
16
18
>>>

écrire un test unitaire avec `py.test` pour la fonction suivante

py.test --tb=no
py.test --tb=short
py.test -x (dernière erreur)
py.test -s  (c'est comme nocapture en fait)
py.test -x --nocapture --pdb
py.test -xl --pdb

py.test -k test_simple

import pytest
def test_function():
    ...
        pytest.set_trace()    # invoke PDB debugger and tracing

Remarquons que :mod:`pdb` utilise le module :mod:`cmd`, voir :ref:`cmdlabel` qu'on a déjà vu précedemment

(Pdb) h

Documented commands (type help <topic>):
========================================
EOF    bt         cont      enable  jump  pp       run      unt
a      c          continue  exit    l     q        s        until
alias  cl         d         h       list  quit     step     up
args   clear      debug     help    n     r        tbreak   w
b      commands   disable   ignore  next  restart  u        whatis
break  condition  down      j       p     return   unalias  where

Miscellaneous help topics:
==========================
exec  pdb

retval  rv

(Pdb)

Les tests automatiques sont un complément à la déclaration des types.

que les unités (fonctions, objets...) réagissent bien à une entrée spécifique

que les unités (fonctions, objets…) réagissent bien à une entrée spécifique

que le code se comporte de la manière attendue dans des environnements différents
(systèmes d'exploitation, etc...)

(systèmes d’exploitation, etc…)

la :doc:`stdlib` propose le module :mod:`unittest` et unittest2.

:mod:`py.test` est **le plus simple** (plus simple que unittest)

def test_simple():
    "test si ma_fontion renvoie bien 3"
    assert ma_fontion(2) == 3

`unittest` necessite de faire sytématiquement une classe, puis `assertEqual()`

:mod:`doctest` est plus simple mais charge trop les docstrings

écrire un fichier commençant par `test_` qui teste les fonctions du fichier

>>> t = (1,2,3)
>>> l = [1,2,3]
>>> d = {'a': 2, 'b':3, 'c':4}
>>>
>>> l = ['e','p','q','t']
>>> l.pop()
't'
>>> l
['e', 'p', 'q']
>>> l
>>> l.pop(1)
'p'
>>> l
['e', 'q']
>>>
exercice
-------------

>>> [str(i) for i in l]
['1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> l2 = []
>>> for i in l:
...   l2.append(str(i))
...
>>> l2
>>>
>>> l = range(1,9)
>>> l2 = [str(i) for i in l]
>>> "-".join(l2)
'1-2-3-4-5-6-7-8'
>>> s= "-"
>>> l2.extend(range(20))
>>> l2
['1', '2', 'sdfsdf', '3', '4', '5', '6', '7', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> l + l2
[1, 2, 3, 4, 5, 6, 7, 8, '1', '2', 'sdfsdf', '3', '4', '5', '6', '7', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> l.extend(l2)
KeyboardInterrupt
>>> l = []
>>> l = list()
>>> list
<type 'list'>
>>> list()
[]
>>> list(range(2))
[0, 1]
>>> tuple
<type 'tuple'>
>>> t
(1, 2, 3)
>>> list(t)
[1, 2, 3]
>>> t
(1, 2, 3)
>>> type(t)
>>>

utiliser get plutôt que l'accès par items lorsque l'on n'est pas sûr

utiliser get plutôt que l’accès par items lorsque l’on n’est pas sûr

>>> d = {}
>>> d.get('toto')
>>> d['toto'] ='titi'
'titi'
>>> print d.get('toto')
titi
>>> print d.get('to')
None
>>> d['tot']
KeyError: 'tot'
>>>
>>>

>>> x=dict(a=23,b=45,c=67,d=89)
>>> x
{'a': 23, 'c': 67, 'b': 45, 'd': 89}
>>> y=dict.fromkeys(range(4), 'ho')
>>> y
{0: 'ho', 1: 'ho', 2: 'ho', 3: 'ho'}

>>> x.pop('c')
67
>>> x
{'a': 23, 'b': 45, 'd': 89}
>>> x.pop('z')
  File "<stdin>", line 1, in ?
KeyError: 'z'
>>> x.pop('z', 55)
55

>>> for x in enumerate('ciao'): print x
...
(0, 'c')
(1, 'i')
(2, 'a')
(3, 'o')
>>>

>>> 1,
(1,)
>>> (1,)
(1,)
>>> (1)
1
>>> ()
()
>>> tuple()
()
>>> value = 1,
>>> value
(1,)

def remove_duplicates(lst):
    ...

l = [4, 7, 30, "hello", 7, "world", 30, 7]
remove_duplicates(l)
assert l == [4, 7, 30, "hello", "world"]

class Sorter:
    def sort(self, list):
        for i in range(len(list) - 1):
            for j in range(i, len(list)):
                if self.compareItems(list[i], list[j]):
                    list[i], list[j] = list[j], list[i]

    def getName(self):
        return "Trieur de liste"

    def getDescription(self):
        
    def compareItems(self, item1, item2):

class AscendantSorter(Sorter):
        return item1 >= item2
        return "Tri par ordre normal"
        return "Ascendant"

class DescendantSorter(Sorter):
        return item1 <= item2
        return "Tri par ordre inverse"

    list = ['b', 'e', 'a', 'c', 'z']
    s = AscendantSorter()
    s.sort(list)
    print list
    s = DescendantSorter()
    print list

>>> 'a' in d
True
>>> t[1]
2
>>>
...   print i
...
1
2
3
>>>
>>> for i in d:
...   print i
...
a
c
b
>>>
>>> for key, value in d.items():
...  print key, " : ", value
...
a  :  2
c  :  4
b  :  3
>>>

en python, **pas besoin de déclaration de type**. Qu'est-ce que ça veut dire ?

>>> type(1)
<type 'int'>
>>>
>>> dir(3)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',
'__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__',
'__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__',
'__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__',
'__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__',
'__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__',
'__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__',
'__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__',
'__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__',
'__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__',
'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
>>>
>>> type(3)
>>>

Manipulations non supportées

>>> e["a"]
TypeError: unsubscriptable object
>>> e.append("a")
AttributeError: 'Set' object has no attribute 'append'

>>> e = set()
>>> e
Set([])
>>> e = set("toto")
>>> e
Set(['t', 'o'])
>>> d = {"a":1,"b":2}
>>> f = set(d)
>>> f
Set(['a', 'b'])

>>> "a" in i
True
>>> len(h)
4
>>> for u in h:
...   print u
...
a
b
t
o
>>> e.add("a")
>>> e
Set(['a'])
>>> for i in range(5):
...   e.add(i)
...
>>> e
Set(['a', 0, 2, 3, 4, 1])
>>> e.add("b", "c")
TypeError: add() takes exactly 2 arguments (3 given)
...
>>> e
# Suppression :
>>> f = e.copy()
>>> f
>>> f.remove(0)

>>> v = sets.Set()

>>> e.issubset(f)
False
>>> f.issubset(e)
True
>>> e.issuperset(f)
True
>>> f &lt; e
True
>>> f &gt; e
False
>>> e
Set(['a', 0, 2, 3, 4, 1, ImmutableSet(['p'])])
>>> e.copy()
>>> e.remove(3)
>>> e
Set(['a', 0, 2, 4, 1, ImmutableSet(['p'])])
>>> 0 in e
True
>>> e.pop()
'a'
>>> e
Set([0, 2, 4, 1, ImmutableSet(['p'])])
0
>>> e.discard(4)
>>> e
Set([2, 1, ImmutableSet(['p'])])
>>> e.discard("p")
>>> e
>>> e.discard(sets.Set("p"))
>>> e
Set([2, 1])
>>>
>>> e -= f
>>> e
Set([])
>>> f
Set(['a', 2, 3, 4, 1])
>>>
>>> e.clear()
>>> e
Set([])
>>>
# copy
>>> h == e
False
>>> h != e
True
>>> u = h.copy()
>>> u
Set(['a', 'b', 't', 'o'])

#Pas d'opération "+" :
>>> h = e + f
TypeError: unsupported operand type(s) for +: 'Set' and 'Set'
#La réunion :
>>> g = e or f
>>> g
autre notation :
>>> h | e
>>> h & e
>>>
Le complémentaire :
>>> h = e ^ f
>>> h
La différence :
>>> i = h - e
>>> i
L'intersection, la réunion, le complémentaire :
>>> f
>>> f & e
Set(['a', 1, 2, 3, 4])
>>> f | e
Set(['a', 1, 2, 3, 4, 0])
>>> f ^ e
Set([0])

def addition_forte(x, y):
  return int(x) + int(y)

def addition_faible(x, y):
  return x + y

dans `addition_faible`, il n'y a pas de casting de type, on n'essaye pas
de transformer ça en un type donné, c'est-à-dire que si `x` et `y` sont
compatible, ça marche. Le typage est fort, on demande des types

, il n’y a pas de casting de type, on n’essaye pas
de transformer ça en un type donné, c’est-à-dire que si 

, il n'y a pas de casting de type, on n'essaye pas
de transformer ça en un type donné, c'est-à-dire que si 

 sont

>>> addition_faible("1", 4)
TypeError: cannot concatenate 'str' and 'int' objects

>>> addition_forte("1", 4)

Remarquons que `addition_faible` renvoie forcément un type `int` tandis
que `addition_forte` peut renvoyer un autre type, ceci est dû au
polymorphisme paramétrique.

 peut renvoyer un autre type, ceci est dû au

le typage

- typage fort

  - statique : déclaration ou bien inférence (déduction) lisible dans le source
    (exemple : java)

  - typage dynamique : une variable est typée en fonction de son contenu

- typage faible :

  - une donnée n'aura pas spécialement de type : les nombres, les chaînes de
    caractères, les booléens, etc. seront tous des scalaires et ne seront
    différenciés que par leur valeur et par le contexte de leur utilisation

typage fort

- statique : déclaration ou bien inférence (déduction) lisible dans le source
  (exemple : java)

- typage dynamique : une variable est typée en fonction de son contenu

statique : déclaration ou bien inférence (déduction) lisible dans le source
(exemple : java)

typage dynamique : une variable est typée en fonction de son contenu

typage faible :

- une donnée n'aura pas spécialement de type : les nombres, les chaînes de
  caractères, les booléens, etc. seront tous des scalaires et ne seront
  différenciés que par leur valeur et par le contexte de leur utilisation

une donnée n'aura pas spécialement de type : les nombres, les chaînes de
caractères, les booléens, etc. seront tous des scalaires et ne seront
différenciés que par leur valeur et par le contexte de leur utilisation

une donnée n’aura pas spécialement de type : les nombres, les chaînes de

>>> class MyClass(object):
  def __init__(self):
      pass
>>> a = MyClass()
>>> type(a) == MyClass
True
>>> type(a) == object
False
>>> isinstance(a, MyClass)
True
>>> isinstance(a, object)
True
>>>

Dans la **PEP 8**, Guido demande explicitement d'utiliser isinstance et non type

citation :

Object type comparisons should always use isinstance() instead
of comparing types directly.

  Yes: if isinstance(obj, int):

  No:  if type(obj) is int:

En python 2.X : deux types : `str` et `unicode` (en python 3 ces types sont unifiés)

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0:
ordinal not in range(128)

>>> u.encode("utf-8")
'\xc3\xa9\xc3\xa8\xc3\xa0 bla'
>>> print u.encode("utf-8")
éèà bla
>>>

manips importantes de traitement unicode (si on n'est pas en python 3)

manips importantes de traitement unicode (si on n’est pas en python 3)

>>> u = u"ésdsfè"
>>> u
u'\xe9sdsf\xe8'
>>> print u
ésdsfè
>>> str(u)
'\xc3\xa9sdsf\xc3\xa8'
>>> s = u.encode("utf-8")
>>> type(s)
<type 'str'>
>>>

if type(s) == unicode #types.UnicodeType:
    bla bla

if type(s) == str:
    rien à faire

>>> import unicodedata
>>> s = u"un été même pas chaud"
>>> import unicodedata as U
>>> s2 = ''.join(U.normalize('NFD', x)[0] for x in s)
>>> s2
u'un ete meme pas chaud'
>>>

>>> import re
>>> import string
>>> rgx = re.compile('[%s]' % string.punctuation)
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

python est un langage dynamiquement typé. qu'est-ce que cela signifie ?

python est un langage dynamiquement typé. qu’est-ce que cela signifie ?

pas de déclaration des types (attention différent de l'inférence de types): les variables n'ont pas
de type fixé, ce qui signifie que le type est fixé au moment de l'affectation
(pendant le rutime).

pas de déclaration des types (attention différent de l’inférence de types): les variables n’ont pas
de type fixé, ce qui signifie que le type est fixé au moment de l’affectation

pas de déclaration des variables (une variable est créée au moyen de la première
affectation).

dans la console créer un objet de type integer, float, string, liste, dictionnaire

>>> l = ['a', 'b', 'c', 'd']
>>> p = [l, 'e']
>>> p
[['a', 'b', 'c', 'd'], 'e']
>>> l = ['i', 'j']
>>> p
>>> l
['i', 'j']

l'interpréteur python comme calculette, les opérations numériques

l’interpréteur python comme calculette, les opérations numériques

>>> x = 1
>>> y =2
>>> x > y
False
>>> x == y
False
>>> x != y
True

>>> s = "bla bla"
'bla bla'
>>> s = 'bla bla'
'bla bla'
>>> s = " 'bli bli' "
>>> s
" 'bli bli' "
>>> s = """ sdfsdf "bla bla" sdfsdf"""
>>> s
' sdfsdf "bla bla" sdfsdf'
>>>
>>> m = "hu hu"
>>> s + m
'bla blahu hu'
>>> m * 3
'hu huhu huhu hu'
>>>
>>> len(m)
5
>>>
>>> m[3]
'h'
>>> m[3:5]
'hu'
>>>

>>> s= 'a'
>>> dir(s)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> t = "abc"
>>> t.startswith("a")
True
>>> l = ['a', 'b', 'c']
>>> "-".join(l)
'a-b-c'
>>>

>>> s = "sdf dfdfdf blah bla df"
>>> re.findall(r'\w*', s)
['sdf', '', 'dfdfdf', '', 'blah', '', 'bla', '', 'df', '']
>>> re.findall(r'df*', s)
['df', 'df', 'df', 'df', 'df']
>>>