Python >> Tutoriel Python >  >> Python

dir() contre __dir__() – Quelle est la différence ?

Formulation du problème

Quelle est la différence entre le dir() intégré fonction et __dir__ méthode dunder en Python ?

Réponse rapide

La fonction intégrée de Python dir(object) renvoie une liste des noms d'attributs et des noms de méthodes de l'objet. Le dir() la fonction est un wrapper autour du __dir__() car elle appelle en interne la méthode dunder de l'objet object.__dir__() . Mais les deux ont des fonctionnalités différentes car dir() effectue des tâches supplémentaires sur la sortie de object.__dir__() comme le tri de la liste de sortie.

Dans l'exemple minimal suivant, vous écrasez la méthode dunder d'un objet __dir__() . En appelant le dir() , vous voyez que la sortie est la même, mais elle est maintenant triée :

class Dummy:
    def __dir__(self):
        return ['bob', 'alice']


print(dir(Dummy()))
# ['alice', 'bob']

Au lieu de la liste ['bob', 'alice'] vous obtenez la liste triée ['alice', 'bob'] donc un traitement supplémentaire doit avoir été effectué par le dir(Dummy()) méthode sur la sortie du Dummy().__dir__() appel de méthode.

En plus du tri, le dir() la fonction effectue également un peu de ménage au cas où le __dir__() la méthode n'est pas définie par la classe. Voici la partie pertinente de la documentation expliquant cette relation :

"Si l'objet ne fournit pas __dir__() , la fonction fait de son mieux pour recueillir des informations à partir du __dict__ de l'objet attribut, s'il est défini, et de son objet type.

Cela signifie que le dir() la fonction est une fonction de niveau supérieur qui effectue un traitement avancé en plus du __dir__() méthode, principalement pour des raisons de convivialité. Mais si vous avez une longue liste de noms d'attributs, vous n'aurez peut-être pas besoin de dépenser des ressources coûteuses pour le tri et vous devriez vous fier au object.__dir__() plutôt dans des environnements sensibles aux performances.

Exemple de voiture

Dans l'exemple suivant, vous voyez la sortie par défaut du dir() et __dir__() méthodes dans un contexte plus pratique :

class Car:

    def __init__(self, color, speed):
        self.color = color
        self.speed = speed

    def accelerate(self):
        self.speed += 10

    def print_color(self):
        print(self.color)

    def print_speed(self):
        print(self.speed)


porsche = Car('red', 110)
print(dir(porsche))
print(porsche.__dir__())

Voici le résultat de cet extrait de code :

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'accelerate', 'color', 'print_color', 'print_speed', 'speed']
['color', 'speed', '__module__', '__init__', 'accelerate', 'print_color', 'print_speed', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']

Vous pouvez voir que la liste de noms par défaut est beaucoup plus longue :elle contient tous les noms explicitement et implicitement définis pour un objet donné. Par exemple, le color et speed les attributs sont là (définis explicitement), et le __str__ et les fonctions __lt__ sont là aussi (définies implicitement pour tout objet personnalisé).

Passons à l'arrière-plan de la méthode dir() - chaque codeur Python de niveau avancé devrait comprendre cela ! 🙂

Répertoire d'arrière-plan()

Si utilisé sans argument , le dir() intégré de Python function renvoie les noms de fonction et de variable définis dans la portée locale —l'espace de noms de votre module actuel. Si utilisé avec un argument d'objet , dir(object) renvoie une liste de noms d'attributs et de méthodes définis dans la portée de l'objet . Ainsi, dir() renvoie tous les noms dans une portée donnée.

Syntax: 
dir() -> names defined in the local scope/namespace.  
dir(object) -> names defined for the object. 
Arguments object L'objet pour lequel les noms doivent être retournés.
Valeur de retour list Renvoie tous les noms définis dans l'espace de noms de l'objet spécifié. Si aucun argument d'objet n'est donné, il renvoie les noms définis dans l'espace de noms local du module dans lequel vous exécutez le code.

Vous pouvez également regarder ma vidéo explicative pour en savoir encore plus !