Corrigé de l'examen de la session 2 (7.06)


Exercice 1.

Surcharger les dictionnaires Python, construire une classe : class Ndict(dict) dont les instances se comportent comme l'héritage le précise, par ex. x=Ndict(); x['a']=42; print(x['a']) – est légal. Cependant, si on accède à une entrée inexistante, par ex. x['quoi'], où on n'a jamais défini cet élément, l'instance devra retourner la clé elle-même, ici la chaîne \stt{'quoi'}. Attention, la créaction de l'instance pourra être comme ci-dessus, ce qui votre classe doit interpréter comme dictionnaire vide, ou prendre un dictionnaire standard existant, p. ex. dd=Ndict({'x':77,'alpha':'beta'}).

Solution

class Ndict(dict):
    def __init__(self,dct={}):
        dict.__init__(self,dct)
    def __getitem__(self,cl):
        try:
            x=dict.__getitem__(self,cl)
        except KeyError:
            x=cl
        return x
        
da=Ndict()
da['a']=42


Exercice 2.

Construire une classe, disons, Bin, qui représente des nombres binaires. Une instance de \stt{Bin} contient une liste de chiffres, par ex. [1,0,0,1,1,0,1], ce qui représente 77. Construire les méthodes suivantes :

  1. L'initialisation avec un entier normal, x=Bin(13) doit construire l'objet avec la liste interne : [1,1,0,1]. Vous devez donc savoir comment convertir un nombre en binaire ; le dernier chiffre c'est le reste de la division par 2, et la construction des chiffres précédants utilise la récursion sur le quotient.
  2. Affichage comme un nombre entier normal (la reconstruction d'un entier).
  3. L'addition de deux entiers binaires, par exemple : Bin(4)+Bin(14) doit produire un objet contenant la liste [1,0,0,1,0]. Conseil (on peut aussi le faire autrement, la récursivité vous aidera) : ajoutez chiffre par chiffre les deux listes des nombres Bin, co que produira [1, 2, 1, 0], et ensuite parcourez la liste – résultat encore une fois afin de propager la retenue, et ainsi normaliser le résultat. Attention, la retenue se propage de droite vers la gauche, donc il faut parcourir la liste "à l'envers", ou utiliser la récursivité, etc.

Solution

def lplus(l1,l2):
    if l1==[]: return l2
    if l2==[]: return l1
    return lplus(l1[:-1],l2[:-1])+[l1[-1]+l2[-1]]
def nrm(l,c):
    if l==[]:
        if c:
            return [1]
        else: return []
    x=c+l[-1]
    if x<2:
        return nrm(l[:-1],0)+[x]
    else:
        return nrm(l[:-1],1)+[x-2]

class Bin(object):
    def __init__(self,n):
        l=[]
        while n!=0:
            n,r=divmod(n,2)
            l.insert(0,r)
        self.l=l
    def __repr__(self):
        return "Bin("+str(self.l)+")"
    def toint(self):
        x=0
        for i in self.l:
            x=2*x+i
        return x
   
    def __add__(self,a):
        r=nrm(lplus(self.l,a.l),0)
        v=Bin(0); v.l=r
        return v
     


Exercice 3.

[Un filtre numérique]. Soient a et b deux nombres réels, et gen un flot (générateur ou autre itérateur, de longueur non-spécifiée, finie ou non), qui fournit la séquence de nombres \(x_0, x_1, x_2, \ldots{} x_n, \ldots\) . Écrire une fonction – générateur filtr(a,b,gen) qui transforme le flot d'origine, en construisant la séquence \(y_0, y_1, \ldots, y_n,\ldots \) telle que \(y_n = a\cdot y_{n-1} + b\cdot x_n\). (La première valeur de \(y\) est, disons, \(x_0\)).

Solution

def ranstr():
    while True:
        yield random()
gen=ranstr()  # par exemple...

def filtr(a,b,gen):
    y=next(gen)
    yield y
    for x in gen:
        y=a*y+b*x
        yield y

f=filtr(0.8,0.2,gen)


Exercice 4.

[Un décorateur]. Une fonction non spécifiée ici, fn(a0,a1,a2,...) (nombre d'arguments arbitraire : c'est une condition obligatoire) construit et retourne une chaîne de caractères. Les détails sont sans importance, vous ne toucherez pas cette fonction ...
Construire un décorateur parametré : def tagit(bal): ... agissant sur une telle fonction :

@tagit(bal)
def fn(...):
   ...
   return s
de manière à ce que la fonction transformée retourne la chaîne-résultat d'origine, balisée par des constructions dans le style HTML, ... . Ici "bal" n'est qu'un symbole - forme, ceci doit être une chaîne concrète. Par ex., si la fonction d'origine retourne "bonjour", et la décoration est : @tagit("div"), alors la fonction transformée doit retourner "<div>bonjour</div>". La décoration @tagit("p") engendrera "<p>bonjour</p>", etc.

Solution

def tagit(bal):
    def decor(fun):
        pre="<"+bal+">"
        post=""
        def aux(*x):
            return pre+fun(*x)+post
        return aux
    return decor
                
@tagit("strong")
def fu(*x):
    return str(x)

print(fu("bonjour", "tout", "le", "monde"))

# =>>>  <strong>('bonjour', 'tout', 'le', 'monde')</strong>

Retour