2017-02-21 2 views
0

J'espère que vous allez bien. Cette question est vraiment de se débarrasser de la référence à la classe de base.Référez-vous à la méthode de la classe parent sans le nom de la classe parent

Fondamentalement, je veux collecter toutes les méthodes d'une méthode de classe enfant au niveau de la classe au lieu du niveau de l'instance, en utilisant une méthode de classe parente. Cependant, on m'a dit que le nom de la classe de base est vraiment long.

La première pièce fonctionne mais est vraiment ennuyante à cause du nom long. Même dans la version propre, je dois faire A.eat à chaque fois. Je promets que les gens ne définiront pas une autre méthode «mange» dans n'importe quel enfant comme B. Puis-je réellement me débarrasser de la référence de la classe de base afin que je puisse utiliser @eat?

class IDontWantToDoThisButNameHasToBeThisLong(object): 

    a = [] 

    @classmethod 
    def eat(cls, func): 
    cls.a.append(func) 


class B(IDontWantToDoThisButNameHasToBeThisLong): 

    @IDontWantToDoThisButNameHasToBeThisLong.eat 
    def apple(self, x): 
    print x 

    IDontWantToDoThisButNameHasToBeThisLong.eat(lambda x: x+1) 

x = B() 

IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1) 

print IDontWantToDoThisButNameHasToBeThisLong.a[1](1) 

propre version:

class A(object): 

    a = [] 

    @classmethod 
    def eat(cls, func): 
    cls.a.append(func) 


class B(A): 

    @A.eat 
    def apple(self, x): 
    print x 

    A.eat(lambda x: x+1) 

x = B() 

A.a[0](x, 1) 
print A.a[1](1) 

Sincèrement,

Répondre

0

La classe IDontWantToDoThisButNameHasToBeThisLong est vraiment juste un objet. En python, la plupart des chosesa sont un objet, donc nous pouvons assigner n'importe quoi à une variable, y compris une classe.

Ce que vous pouvez faire ici est quelque chose comme le

suivant
class IDontWantToDoThisButNameHasToBeThisLong(object): 

    a = [] 

    @classmethod 
    def eat(cls, func): 
     cls.a.append(func) 

A = IDontWantToDoThisButNameHasToBeThisLong 


class B(A): 

    @A.eat 
    def apple(self, x): 
     print x 

    A.eat(lambda x: x+1) 

x = B() 

IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)   
A.a[0](x, 1) 

print IDontWantToDoThisButNameHasToBeThisLong.a[1](1) 
0

Il n'y a pas une solution parfaite pour ce que vous voulez faire, mais il y a quelques approches différentes qui pourraient être assez bon.

Pour commencer par le plus simple, vous pouvez donner à votre longue classe un nom plus court avant d'utiliser la méthode de classe dans les classes d'enfants:

class IDontWantToDoThisButNameHasToBeThisLong(object): 
    ... 

A = IDontWantToDoThisButNameHasToBeThisLong 

# later code can use A.whatever() 

Une autre option serait de déplacer le décorateur de la classe avec la longue name, de sorte que votre code plus récent se réfère directement à lui comme une méthode globale, plutôt que d'une classe. Il faudrait pour cela qu'il soit remanié légèrement (qui pourrait casser des choses si jamais vous l'intention qu'il y ait plusieurs différentes listes a qui sont accessibles par le même décorateur appelé via différentes classes):

class IDontWantToDoThisButNameHasToBeThisLong(object): 
    a = [] 

def eat(func): 
    IDontWantToDoThisButNameHasToBeThisLong.a.append(func) # only need to use the name once 
    return func # I suspect you want this too (a decorator should return a callable) 

# later code can use @eat as a decorator, without referring to the long class name 

Un hybride de ces deux approches pourraient être de laisser la définition de la méthode de classe existante intacte, mais pour créer un autre nom global pour la méthode liée qui est plus facile d'accès:

eat = IDontWantToDoThisButNameHasToBeThisLong.eat 

Une approche finale possible serait d'utiliser la programmation colombophile avec métaclasses, ou (si vous utilisez Python 3.6) __init_subclass__ ou similaire, à achi veillez à l'objectif que vous avez en tête sans avoir besoin d'utiliser une méthode de classe en tant que décorateur. Je ne vais pas inclure de code pour cela, car la meilleure façon de le faire dépend probablement de plus de détails de votre conception que ce que vous avez montré dans votre exemple.