Skip to main content
 首页 » 编程设计

python之覆盖字符串列表中属性的 getter 和 setter

2025年05月04日20txw1958

目的是在列表中提供一些字符串作为类的属性。该类不仅应具有属性,还应具有各自的 getter 和 setter 方法。在继承自该类的其他一些类中,需要覆盖其中一些 setter 。

为此,我提出了以下建议。在字符串列表的循环中使用 setattr,创建一个属性和相应的方法。关于第一部分,代码按预期工作。
但是,我无法覆盖继承类中的 setter 。

class Base(): 
    attributes = ["attr{}".format(i) for i in range(100)] 
 
    def __init__(self): 
        _get = lambda a: lambda : getattr(self, a) 
        _set = lambda a: lambda v: setattr(self, a, v) 
 
        for attr in self.attributes: 
            setattr(self, attr, None) 
            setattr(self, "get_"+attr, _get(attr)) 
            setattr(self, "set_"+attr, _set(attr)) 
 
 
class Child(Base): 
    def __init__(self): 
        super().__init__() 
        #setattr(self, "set_attr4", set_attr4) 
 
    # Here I want to override one of the setters to perform typechecking 
    def set_attr4(self, v): 
        print("This being printed would probably solve the problem.") 
        if type(v) == bool: 
            super().set_attr4(v) 
        else: 
            raise ValueError("attr4 must be a boolean") 
 
if __name__ == "__main__": 
  b = Base() 
  b.attr2 = 5 
  print(b.get_attr2()) 
  b.set_attr3(55) 
  print(b.get_attr3()) 
 
  c = Child() 
  c.set_attr4("SomeString") 
  print(c.get_attr4()) 

这里的输出是

5 
555 
SomeString 

然而,预期的输出将是

5 
555 
This being printed would probably solve the problem. 
ValueError("attr4 must be a boolean") 

所以 set_attr4 方法永远不会被调用;我猜这是预料之中的,因为 __init__ 在读入类结构之后被调用。但是我不知道如何重写这些方法。我尝试添加 setattr(self, "set_attr4", set_attr4)(上面代码中的注释行)但无济于事。

或者更一般地说,propery 通常用于创建 getter 和 setter。但我不认为我理解如何在 getter 和 setter 是动态创建的并且需要被 child 覆盖的情况下应用它。

有什么解决办法吗?


由于评论而更新:有人指出,在 python 中使用 getters/setters 可能不是一个好的风格,而且通常可能不需要它们。虽然这绝对是要记住的事情,但这个问题的背景是我正在扩展一个旧的现有代码,它始终使用 getters/setters。因此,我不希望更改样式并让用户(这个项目总共只有大约 20 个用户,但仍然......)突然改变他们访问 API 中属性的方式。
然而,任何 future 的读者可能会认为 getter/setter 方法至少是有问题的。

请您参考如下方法:

元类来拯救!

class Meta(type): 
    def __init__(cls, name, bases, dct): 
        for attr in cls.attributes: 
            if not hasattr(cls, attr): 
                setattr(cls, attr, None) 
                setattr(cls, f'get_{attr}', cls._get(attr)) 
                setattr(cls, f'set_{attr}', cls._set(attr)) 
 
class Base(metaclass=Meta): 
    attributes = ["attr{}".format(i) for i in range(100)] 
 
    _get = lambda a: lambda self: getattr(self, a) 
    _set = lambda a: lambda self, v: setattr(self, a, v) 
 
# the rest of your code goes here 

这是不言自明的:创建 attributes、_get、_set 类变量(这样您就可以在没有类实例化的情况下访问它们),然后让元类为您设置一切。