Python 通过引用更改类属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44046920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 23:40:40  来源:igfitidea点击:

Changing class attributes by reference

pythonattributesmutable

提问by Jan

I'm relatively new to Python and have problems with immutable variables.

我对 Python 比较陌生,并且对不可变变量有问题。

I'm trying to change the value of a class attribute (e.g. car.color). The difficulty is, that I can not use the namespace of car for doing this.

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

Up to now I did not find a satisvying answer to my questions. In the code below I tried to summarize the possible solutions (workarrounds) I found and their disadvantages:

到目前为止,我没有找到满意的答案。在下面的代码中,我试图总结我发现的可能的解决方案(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

Actually the function setattr() is internally exactly doing what I want. But it works with a string argument. I tried to look into this function but it seems to be written in C++.

实际上,函数 setattr() 在内部完全符合我的要求。但它适用于字符串参数。我试图研究这个函数,但它似乎是用 C++ 编写的。

So do I have to use C++ to solve this problem without a workarround? Or is there a Pythionic way of doing this?

那么我是否必须使用 C++ 来解决这个问题而没有解决方法?或者是否有一种 Pythionic 方法可以做到这一点?

回答by Mogarrr

The problem is you are trying to redefine the value of an instance from outside of the class. Since in __init__you are defining your variables with self, they are only available for that instance. This is the point of a class - it's what makes them extensible and reusable.

问题是您正试图从类外部重新定义实例的值。由于__init__您使用 定义变量self,因此它们仅适用于该实例。这就是类的意义所在——它使它们具有可扩展性和可重用性。

Ideally, you would make a method withinthe class that would update those attributes, however, if you really need to update the class from an external function, you will have to define it as a class level variable. For instance:

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

class Car:

    def __init__(self):
        Car.color = "green"

can now be updated using:

现在可以使用以下方法更新:

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

outside of the class because you have not assigned it to one specific instance. Doing this presents a problem, however. Since we don't have a separate instance variable, if we try to re-instantiate the class, we are stuck with what was previously changed, i.e. if name== "main":

在课堂之外,因为您没有将它分配给一个特定的实例。然而,这样做会带来问题。由于我们没有单独的实例变量,如果我们尝试重新实例化该类,我们会被先前更改的内容所困扰,即如果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

This is why classes themselves should be self contained and are meant to be immutable - the instance itself should be changed.

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