我对Python比较陌生,并且存在不可变变量的问题。
我正在尝试更改类属性的值(例如car.color)。困难在于,我不能使用汽车的命名空间来做这件事。
到目前为止,我没有找到令人满意的答案。在下面的代码中,我试图总结我发现的可能解决方案(workarrounds)及其缺点:
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
实际上,函数setattr()在内部完全按照我的意愿行事。但它适用于字符串参数。 我试着研究这个函数,但它似乎是用C ++编写的。
所以我必须使用C ++来解决这个问题吗? 或者有一种Pythionic方式吗?
答案 0 :(得分:5)
问题是您正在尝试从类外部重新定义实例的值。由于在__init__
中您使用self
定义变量,因此它们仅适用于该实例。这是一个类的重点 - 它是使它们可扩展和可重用的原因。
理想情况下,您可以在类中创建一个方法来更新这些属性,但是,如果您确实需要从外部函数更新类,则必须将其定义为类级别变量。例如:
class Car:
def __init__(self):
Car.color = "green"
现在可以使用更新
def change_attribute(attribute, value):
"In this function I can not access car.color directly"
Car.color=value
在课外,因为您尚未将其分配给一个特定实例。然而,这样做会带来问题。由于我们没有单独的实例变量,如果我们尝试重新实例化该类,我们就会陷入先前改变的状态,即 如果名称 ==“主要”:
car1 = Car()
car2 = Car()
change_attribute(car1.color, "red")
print(car1.color) # Prints red
print(car2.color) # Prints red
change_attribute(car2.color, "blue")
print(car1.color) # Prints blue
print(car2.color) # Prints blue
这就是为什么类本身应该是自包含的并且意图是不可变的 - 实例本身应该被更改。