【问题标题】:How to define new attribute in python class?如何在python类中定义新属性?
【发布时间】:2022-11-12 00:44:40
【问题描述】:

我写了一个类,它有 3 个隐藏属性:

class Car():
    def __init__(self, name, model, brand):
        self.__name = name
        self.__model = model
        self.__brand = brand

是否可以为此类创建一个方法来设置新属性(发布者)? 我写了这个,但我没有得到结果:

    def set_publisher(self, publisher):
        self.__publisher = publisher


b1 = Car(name="X", model="Y", brand="Z")
publisher="D"
b1.set_publisher(publisher)

错误:

AttributeError: 'Car' object has no attribute 'set_publisher'

【问题讨论】:

  • 它没有属性set_publisher。但是一旦你调用了set_publisher(),它就应该有一个__publisher 属性。
  • 是否可以不在 __init__() 中定义发布者?
  • 我转载了你的问题。尝试使用以单个下划线(不是 2)为前缀的变量。当用_publisher 替换__publisher 时,它对我有用。我相信双下划线前缀的变量是保留的。除非你真的想要__ 变量。
  • 奇怪的。你能仔细检查缩进吗? set_publisher() 函数是否属于该类?一个简单的缩进错误可能会导致该问题。我试过了。
  • @0x0fba __publisher 不是保留的(__publisher__ 是保留的,后面也有下划线)。但是,当一个下划线将其标记为“不是公共接口的一部分”就足够了时,人们经常使用受名称修饰的名称。

标签: python python-3.x


【解决方案1】:

如果set_publisher 被正确定义为实例方法,则没有问题。

class Car:
    def __init__(self, name, model, brand):
        self.__name = name
        self.__model = model
        self.__brand = brand

    def set_publisher(self, publisher):
        self.__publisher = publisher

但是,如果 setter 只允许将任何值直接分配给属性,那么为什么还要隐藏它呢?只需将 publisher 设为公共属性:

class Car:
    def __init__(self, name, model, brand, publisher=None):
        self.__name = name
        self.__model = model
        self.__brand = brand
        self.publisher = None  # Define but None is usually better than undefined

c = Car("Dave", "Model T", "Ford")
c.publisher = "Henry"

如果您稍后决定对如何(或是否)设置发布者施加进一步的限制,您可以将其替换为属性而不更改类的接口。

class Car:
    def __init__(self, name, model, brand, publisher=None):
        self.__name = name
        self.__model = model
        self.__brand = brand
        self._publisher = None

    @property
    def publisher(self):
        return self._publisher

    @publisher.setter
    def publisher(self, value):
        # If you want to examine value and reject it,
        # do so and raise a ValueError. You can modify
        # value before assigning it as well.

        if value == "Bob":
            raise ValueError("Bob is not a publisher")
        if value == "Alice":
            # Alice changed her name a while ago
            value = "Carol"
        self._publisher = value

c = Car("Dave", "Model T", "Ford")
c.publisher = "Henry"  # OK
c.publisher = "Alice"  # assert c.publisher == "Carol"
c.publisher = "Bob"  # ValueError

【讨论】:

  • Nitpick:set_publisher 将是一个方法(或“实例方法”或“类上的方法”),而不是类方法(这完全是另一回事,由@classmethod 生成)。
  • 我可以争论“类方法”和classmethod 之间的区别,但老实说,我认为我的手指只是在自动驾驶仪上:) 我会解决的。
【解决方案2】:

您可以尝试此代码以使用方法(setattr 的包装器)按名称和值添加属性:


class Car:
    def __init__(self, name, model, brand):
        self.__name = name
        self.__model = model
        self.__brand = brand

    def set_attribute(self, attr_name, value):
        setattr(self, attr_name, value)


obj = Car(name="name", model="model", brand="brand")
obj.set_attribute("__publisher", "publisher")
print(obj.__publisher)

>>> publisher

【讨论】:

  • 这绕过了应该具有的名称修饰私有属性,这实际上使得无法从类的任何方法中正常访问它(没有getattr/setattr)。
猜你喜欢
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 2018-08-13
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
  • 2018-06-12
  • 2015-09-01
相关资源
最近更新 更多