通过引用更改类属性

Jan*_*Jan 8 python attributes mutable

我对Python相对较新,并且对不可变变量有疑问。

我正在尝试更改类属性的值(例如car.color)。困难在于,我无法使用car的命名空间来执行此操作。

到目前为止,我还没有找到令人满意的答案。在下面的代码中,我试图总结发现的可能解决方案(工作环境)及其缺点:

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
Run Code Online (Sandbox Code Playgroud)

实际上,函数setattr()在内部完全可以实现我想要的功能。但是它可以使用字符串参数。我试图研究此功能,但它似乎是用C ++编写的。

那么,我是否必须使用C ++来解决此问题而无需进行工作?还是有一种Pythionic的方式来做到这一点?

Mog*_*rrr 9

问题是您正在尝试从类外部重新定义实例的值。由于在__init__中使用定义变量self,因此变量仅可用于该实例。这就是课程的重点-这就是使它们具有可扩展性和可重用性的原因。

理想情况下,您将创建一个用于更新这些属性的方法,但是,如果您确实需要从外部函数更新该类,则必须将其定义为类级变量。例如:

class Car:

    def __init__(self):
        Car.color = "green"
Run Code Online (Sandbox Code Playgroud)

现在可以使用以下命令进行更新:

def change_attribute(attribute, value):
    "In this function I can not access car.color directly"
    Car.color=value
Run Code Online (Sandbox Code Playgroud)

在类之外,因为您尚未将其分配给一个特定实例。但是,这样做会带来问题。由于我们没有单独的实例变量,因此,如果我们尝试重新实例化该类,那么我们将停留在先前更改的内容上,即如果name ==“ main ”:

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
Run Code Online (Sandbox Code Playgroud)

这就是为什么类本身应该是自包含的,并且是不可变的-实例本身应该更改。