2017-09-26 7 views
0

Donc, dans le paquet docutils de python, il y a une classe (Image) qui a une méthode (align). Comme je l'ai compris, les méthodes prennent self comme premier argument à moins qu'elles ne soient décorées comme @classmethod ou @staticmethod, mais align ne le fait pas. Le code correspondant est copié ci-dessous (full code here).Méthodes d'instance et méthodes statiques dans les classes python

class Image(Directive): 

    def align(argument): 
     # This is not callable as self.align. We cannot make it a 
     # staticmethod because we're saving an unbound method in 
     # option_spec below. 
     return directives.choice(argument, Image.align_values) 

J'utilise ce code comme base pour mes propres fins, et je l'ai essayé à la fois de donner aligner un argument en soi et en le transformant en une méthode statique (après avoir changé le nom afin de ne pas entrer en conflit avec l'auto .align), mais a eu des erreurs avec l'une ou l'autre approche. Que se passe-t-il?

+0

Pourriez-vous indiquer quelle erreur obtenez-vous? – MaLiN2223

+0

avec @staticmethod: l'objet 'staticmethod' n'est pas appelable. Avec 'self' ajouté: align_option() missing 1 argument positionnel requis: 'arg'. – vorpal

+0

En fait, ceci est documenté: "Ceci n'est pas callable sous self.align, nous ne pouvons pas en faire une méthode statique car nous sauvegardons une méthode non liée dans option_spec ci-dessous." –

Répondre

2

Il n'est pas nécessaire de nommer le premier argument self; c'est juste une convention. Dans le code suivant

i = Image() 
i.align() 

la méthode align sera appelée avec le paramètre argument faisant référence à l'objet i.

La fonction suivante se comporter de manière identique:

def align(self): 
    return directives.choice(self, Image.align_values) 

(remplaçant simplement argument avec le self plus commun).


Dans ce contexte, la fonction align n'a jamais été destiné à être une méthode; l'auteur semble simplement définir une fonction à stocker dans le dictionnaire options_spec. L'effet recherché aurait pu être atteint sans polluer l'espace de la classe en supprimant le nom après la référence de fonction a été enregistrée:

option_spec = {'alt': directives.unchanged, 
       'height': directives.length_or_unitless, 
       'width': directives.length_or_percentage_or_unitless, 
       'scale': directives.percentage, 
       'align': align, 
       'name': directives.unchanged, 
       'target': directives.unchanged_required, 
       'class': directives.class_option} 
del align 

ou en renonçant à la déclaration def — c'est une fonction très simple — et en utilisant une expression lambda pour créer la fonction.

option_spec = {'alt': directives.unchanged, 
       'height': directives.length_or_unitless, 
       'width': directives.length_or_percentage_or_unitless, 
       'scale': directives.percentage, 
       'align': lambda x: directives.choice(x, Image.align_values) 
       'name': directives.unchanged, 
       'target': directives.unchanged_required, 
       'class': directives.class_option} 
+0

C'est ce que je pensais, mais, au moins, je comprends le code, ce qui est passé pour aligner IS est un véritable argument (en particulier, quel que soit l'utilisateur entré pour l'option align) plutôt que simplement avec un nom différent. La fonction directives.choice vérifie si l'argument 1 est membre de l'argument the tupple 2. Puisque Image.align_values ​​est un ensemble de chaînes, cela signifie que l'argument 1 doit être une chaîne plutôt qu'une instance de classe Image. – vorpal

+1

Ah, techniquement c'est une méthode d'instance *, mais * elle n'est jamais destinée à être utilisée comme telle. Au lieu de cela, la fonction est stockée dans un 'dict' (' option_spec'), où est seulement utilisé comme une fonction régulière. Quelque chose comme 'i.option_spec ['align'] (foo)'. – chepner

+1

Cela aurait probablement été une bonne idée d'ajouter 'del align' après avoir enregistré la référence dans le' dict' afin que le nom soit supprimé du corps de l'instruction 'class', ce qui l'empêche d'être stocké comme attribut du classe. Ensuite, il n'y aurait pas de pseudo-méthode nommée 'align'. – chepner