Appliquer automatiquement des décorateurs avec de l'héritage

Est-ce possible ?

L'auteur de ce sujet a trouvé une solution à son problème.
Staff
Auteur du sujet

Bonjour à tous,

Je travaille actuellement sur un programme un peu spécial qui content un ensemble des classes toutes héritants d'une même classe A.

Par exemple ça donnerai cela :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class A(object):

    def func1(self):
        pass

    def func2(self):
        pass


class B(A):

    def func2(self):
        pass

Ce que je veux c'est appliquer automatiquement un décorateur sur func1() et func2() dans toutes mes classes héritant de A sans avoir à le préciser dans la classe héritée.

Est-ce possible ? Si oui je suppose que la syntaxe doit être quelque chose comme :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class A(object):

    def func1(self):
        pass

    def func2(self):
        pass

    def quelque_chose(self):
        """Tout se passe ici"""
        pass

Merci d'avance :)

"I think that it’s extraordinarily important that we in computer science keep fun in computing." – Alan J. Perlis

+0 -0
Staff

Le mot clé que tu cherche est plutôt meta-classe. Ça te permetrait de le faire implicitement.

Si tu veux le faire explicitement, en Python 3 tu peux facilement récupérer toutes les classes qui héritent d'une autre et donc tu peux appliquer ta transformation

+3 -0

Cette réponse a aidé l'auteur du sujet

Je penche aussi pour une métaclasse. Exemple simplifié :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Meta(type):

    @staticmethod
    def decorate(func):
        def wrapper(*args, **kwargs):
            print('call %s' % (func.__qualname__))
            return func(*args, **kwargs)
        return wrapper

    def __new__(mcls, name, bases, attrs):
        for k, attr in attrs.items():
            # choix de ce qu'on veut décorer, ici tous les callables
            if hasattr(attr, '__call__'):
                attrs[k] = mcls.decorate(attr)
        return super().__new__(mcls, name, bases, attrs)


# base class
class A(metaclass=Meta):
    def foo(self):
        pass


class B(A):
    def foo(self):
        pass

    def bar(self):
        pass

Et à l'utilisation :

1
2
3
4
5
6
7
8
>>> a = A()
>>> a.foo()
call A.foo
>>> b = B()
>>> b.foo()
call B.foo
>>> b.bar()
call B.bar

Édité par yoch

+2 -0
Staff
Auteur du sujet

Merci à tous les deux, le code de yoch m'a permis de perfectionner le mien c'est parfait.

Sujet clos :)

"I think that it’s extraordinarily important that we in computer science keep fun in computing." – Alan J. Perlis

+0 -0
Staff

Attention cependant, les meta-classes comme ça (et même ce que tu recherche à faire, appliquer un décorateur) ça fait un peu magie-noir et ça rend le code difficile à comprendre et à déboguer. A utiliser avec parcimonie.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte