Modification des attributs de classe par référence
Je suis relativement nouveau à Python et ont des problèmes avec immuables variables.
Je suis en train de modifier la valeur d'un attribut de classe (voiture, par exemple.de la couleur). La difficulté est que je ne peux pas utiliser l'espace de noms de la voiture pour le faire.
Jusqu'à maintenant, je n'ai pas trouvé un satisvying de réponse à mes questions. Dans le code ci-dessous j'ai essayé de résumer les solutions possibles (workarrounds) j'ai trouvé et leurs inconvénients:
class Car:
def __init__(self):
self.color = "green"
self.color_list = ["green"]
self.color_attrib = "green"
self.name = "VW Golf"
"""
and many more attributes...
"""
def makesetter(self, attribute):
def set_value(value):
attribute=value
return set_value
def set_color(self, value):
"in this function I directly have access to car.color and can change its value: "
self.color = value
def set_attrib(self, attribute_string, value):
setattr(self,attribute_string,value)
def change_attribute(attribute, value):
"In this function I can not access car.color directly"
attribute=value
def change_attribute_list(attribute, value):
"In this function I can not access car.color directly"
attribute[0] = value
if __name__ == "__main__":
car1 = Car()
change_attribute(car1.color, "red")
print(car1.color) # Color does not change because car1.color is immutable
g = car1.makesetter(car1.color)
g("red")
print(car1.color) # Color does not change because car1.color is immutable
change_attribute_list(car1.color_list, "red")
print(car1.color_list) # Color changes but seems like a workarround
# Disadvantage: in the namespace of car1, the user has to use a list to access a string value "car1.color_list[0]"
car1.set_color("red")
print(car1.color) # Color changes but seems like a workarround
# Disadvantage: Car needs a setter function for each attribute
car1.set_attrib("color_attrib","red")
print(car1.color_attrib) # Color changes but seems like a workarround
# Disadvantage: Attribute has to be passed as string & no auto completion while coding
En fait la fonction setattr() est à l'intérieur exactement de faire ce que je veux. Mais il fonctionne avec un argument de type chaîne.
J'ai essayé de regarder dans cette fonction, mais il semble être écrit en C++.
Donc dois-je utiliser C++ pour résoudre ce problème sans une workarround?
Ou est-il un Pythionic façon de faire cela?
- Vous envoyer la voiture de l'objet lui-même de la fonction et de modifier l'attribut y acheter à l'aide de l'objet voiture dict, ou de définir une méthode à l'intérieur de la classe qui prend soin de changer l'attribut.
- Serait-il possible pour vous de faire
def change_attribute(obj, attribute, value): obj.__dict__[attribute] = value
? Qui allait changer l'immuable objet directement sur la source. Et vous n'avez qu'à l'appeler par l'intermédiairechange_attribute(car1, 'color', 'blue')
- Aussi qu'est-ce que l'application de votre choix?
- Je voudrais l'utiliser dans un treeview modèle. Je ré-implémenté la fonction data() pour accéder à toutes les voitures attributs. L'arborescence doit toujours montrer exactement les données de la voiture. Par conséquent, je tiens à sauver la référence à la voiture.la couleur comme treeview.set_data(voiture.couleur, Qt.D'affichage). Lorsque treeview obtient des données() pour le dessin, il est toujours afficher les données dans la voiture.couleur. Mais en effet, il indique toujours "vert", la valeur initiale.
- Pavan: c'est possible, mais alors je dois écrire une fonction pour chaque attribut. Cette coutures comme une solution de contournement pour moi. @Torxed: possible, mais j'ai l'inconvénient de l'utilisation d'une chaîne de l'attribut.
- Que voulez-vous dire, vous ne pouvez pas utiliser l'espace de noms? Qu'est-ce que la prévention de votre écriture
car1.color = "red"
ousetattr(car1, "color", "red")
?
Vous devez vous connecter pour publier un commentaire.
Le problème, c'est que vous essayez de redéfinir la valeur d'une instance de l'extérieur de la classe. Depuis dans
__init__
vous de définir vos variables avecself
, ils ne sont disponibles que pour cette instance. C'est le point d'une classe - c'est ce qui les rend extensible et réutilisable.Idéalement, vous feriez une méthode dans la classe qui permettrait de mettre à jour ces attributs, cependant, si vous avez vraiment besoin de mettre à jour la classe à partir d'une fonction externe, vous aurez à le définir comme une classe de niveau variable. Par exemple:
peut maintenant être mis à jour en utilisant:
à l'extérieur de la classe parce que vous n'avez pas attribué à une instance spécifique. Ce faisant, présente cependant un problème. Puisque nous n'avons pas une instance distincte de la variable, si nous essayons de nous ré-instancier la classe, nous sommes coincés avec ce qui avait déjà été modifiée, c'est à dire
si nom == "principal":
C'est pourquoi les classes elles-mêmes doivent être autonomes et sont destinés à être immuable - l'instance elle-même qui doit être changé.
def __init__(self): self.Attributes = { 'Color': '', 'Make': '', 'Model': '' }
Puis la mise à jour avec une fonction:def _updateColor(self): currentColor = self.Attributes['Color'] #This would get a list of colors # Do stuff to specify a new color self.Attributes['Color'] = newColor
Alors vous pouvez tout mettre à jour et de le stocker dans un dictionnaire directement.