web-dev-qa-db-fra.com

Utiliser setattr () dans python

Je cherche quelqu'un pour expliquer les bases de l'utilisation, et ne pas utiliser setattr().

Mon problème est apparu en essayant d'utiliser une méthode/fonction de classe pour renvoyer des données qui étaient ensuite insérées dans une autre méthode/fonction. Peut-être qu'une approche plus simple serait bien meilleure dans ce cas, mais j'essaie de comprendre comment les classes fonctionnent/sont utilisées. Ce problème semble dépendre de setattr(), et je tente d’en faire un usage assez simple.

Bien que ce ne soit pas tout à fait le même problème, je suivais Python The Hard Way, ex42 - the while loop @ lines 18-41.

J'ai essayé d'écrire une \__init__(), et d'utiliser plutôt getattr(), pensant qu'il fallait peut-être quelque chose dans l'espace de noms de la classe, mais cela ne semble pas aider.

#! /bin/python2.6

class HolyGrail(object):

    def __init__(self):
        self.start = 'start_at_init'

    # function definition in question:
    # TypeError: 'str' object is not callable

    def run_it(self):
        start = setattr(self, 'name', 'get_thing')
        start = self.name

        # Something wrong here?
        value_returned = start() #I believe this == self.get_thing()
        use_it(value_returned)

    """
    # alternate function definitions
    # NameError: global name 'start' is not defined

    def __init__(self):
        self.start = 'get_thing'

    def run_it(self):
        go_do_it = getattr(self, start)
        first_output = go_do_it()
        use_it(first_output)
    """

    def get_thing(self):
        return "The Knights Who Say ... Ni!"

    def use_it(self, x):
        print x
        print "We want a shrubbery!"

my_instance = HolyGrail()
my_instance.run_it()

@Karl Knechtel, @Amber, @Chris Morgan, merci pour votre aide.

Je pense que je peux maintenant expliquer ma propre réponse! Cela nécessitait une meilleure compréhension de soi en tant qu'objet pour moi. C'est un nom d'instance qui est marqué avec des éléments tels que des attributs.

La classe pourrait être une ville, et ensuite. getattr cherche une maison en utilisant son nom, vous êtes donc prêt à l'appeler sous peu et vous propose un endroit différent si vous ne la trouvez pas --Avec getattr un 'nom 'existe et vous allez le trouver. Fait passer l'étape d'une fonction à une autre dynamique En prime, vous pouvez avoir une valeur par défaut, utile pour obtenir une méthode par défaut de secours - la connexion a échoué ou quelque chose?

setattr construit une maison et lui donne un nom afin que vous puissiez l'appeler plus tard. Vous pouvez potentiellement reconstruire cette maison ou aller dans un endroit particulier si vous ne pouvez pas la trouver. --setattr donne un nom d'attribut et donne ou modifie sa valeur pour qu'il soit appelé ultérieurement. Peut-être qu'un utilisateur désactive le son, alors les méthodes futures ne génèrent aucun son.

J'aurais pu écrire ma fonction de différentes façons, mais il n'est pas nécessaire de changer d'attribut:

def run_it(self):
    yo = getattr(self, 'get_thing')
    answer = yo()
    setattr(self, 'deal_accepted', self.use_it) #really ott
    no = getattr(self, 'deal_accepted')
    no(answer)

Code correctement corrigé:

def run_it(self):
    value_returned = self.get_thing()
    self.use_it(value_returned)
54
bounce

Vous définissez self.name au chaîne"get_thing", pas la fonction get_thing.

Si tu veux self.name pour être une fonction, alors vous devriez la définir sur une:

setattr(self, 'name', self.get_thing)

Cependant, cela est totalement inutile pour votre autre code, car vous pouvez l'appeler directement:

value_returned = self.get_thing()
64
Amber

Les documents Python disent tout ce qui doit être dit, autant que je sache.

setattr ( objet , nom , valeur )

C'est la contrepartie de getattr() . Les arguments sont un objet, une chaîne et une valeur arbitraire. La chaîne peut nommer un attribut existant ou un nouvel attribut. La fonction attribue la valeur à l'attribut, à condition que l'objet le permette. Par exemple, setattr(x, 'foobar', 123) est équivalent à x.foobar = 123.

Si cela ne suffit pas, expliquez ce que vous ne comprenez pas.

74
Chris Morgan

Setattr: Nous utilisons setattr pour ajouter un attribut à notre instance de classe. Nous passons l'instance de la classe, le nom de l'attribut et la valeur. et avec getattr on retrive ces valeurs

Par exemple

Employee = type("Employee", (object,), dict())

employee = Employee()

# Set salary to 1000
setattr(employee,"salary", 1000 )

# Get the Salary
value = getattr(employee, "salary")

print(value)
11
kuldeep Mishra

Supposons que vous souhaitiez attribuer des attributs à une instance qui n'était auparavant pas écrite dans le code. La setattr() ne fait que cela. Il faut l'instance de la classe self et la clé et la valeur pour définir.

class Example:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
4
Amar Bir Singh

Pour ajouter aux autres réponses, un cas d'utilisation courant que j'ai trouvé pour setattr() est l'utilisation de configs. Il est courant d’analyser les configs d’un fichier (fichier .ini ou autre) dans un dictionnaire. Donc, vous vous retrouvez avec quelque chose comme:

configs = {'memory': 2.5, 'colour': 'red', 'charge': 0, ... }

Si vous souhaitez ensuite affecter ces configurations à une classe à stocker et à faire circuler, vous pouvez effectuer une affectation simple:

MyClass.memory = configs['memory']
MyClass.colour = configs['colour']
MyClass.charge = configs['charge']
...

Cependant, il est beaucoup plus facile et moins bavard de parcourir les configs, et setattr() comme ceci:

for name, val in configs.items():
    setattr(MyClass, name, val)

Tant que vos clés de dictionnaire ont les noms propres, cela fonctionne très bien et reste agréable et ordonné.

* Notez que les clés dict doivent être des chaînes car ce seront les noms des objets de classe.

0
HoboProber