当前位置: 代码迷 >> python >> 我该如何破坏子框架中的财产?
  详细解决方案

我该如何破坏子框架中的财产?

热度:55   发布时间:2023-07-16 10:15:18.0

我正在尝试创建一个Config Python 3类,其中用户将配置参数设置为超类上的普通类属性或超类上的属性,用户可以在(sub)类的实例上设置覆盖/阴影。 我宁愿不需要用户为使用属性方法创建的属性定义setter方法。 有没有一种方法可以破坏父类中的属性集,即使它是使用属性装饰器创建的呢?

class Configuration:
    param1 = 'a'

    @property
    def param2(self):
        return self.param1 + 'x'

class Proj1(Configuration):
    param3 = 'blah'

config = Proj1()
config.param2 = 'new_val'

由于超类中的属性decorate,此代码段将尝试分配给pram2抛出AttributeError 有没有一种方法可以轻松破坏现有属性并使用任意属性值对其进行阴影处理?

看起来您的目标似乎是使派生属性在父对象上不可变,但让子类对其进行突变,而无需子类定义@setter即可。 因此,只需让父类定义明确禁止对父类本身进行操作的子类友好属性获取器和设置器即可:

class Configuration:
    param1 = 'a'

    @property
    def param2(self):
        try:
            return self._param2  # If child has an override, use that value
        except AttributeError:
            return self.param1 + 'x'  # Otherwise use parent default

    @param2.setter
    def param2(self, new_val):
        # Treat as immutable on parent
        if type(self) is Configuration:
            raise AttributeError("can't set attribute")
        # But allow it to be set on child
        self._param2 = new_val  # Or type(self)._param2 = new_val if it should be set on class

    @param2.deleter
    def param2(self):
        # Treat as immutable on parent
        if type(self) is Configuration:
            raise AttributeError("can't delete attribute")
        del self._param2  # Or del type(self)._param2 if it's a class attribute, not instance

现在,您的孩子的实例可以变得笨拙,松散等,但是原始父类无法更改(您可以手动执行Configuration._param2 = 'new value' ,但这违反了下划线前缀名称的实现细节约定)。

请注意,如果你需要这些特性来包装类的属性,而不是实例属性(因此改变config.param2应该改变param2为所有其他实例Proj1 ),一致性,你想要的行为时,直接分配工作Proj1.param2为好。 这得到丑陋的,为定义property上通过类,而不是实例直接访问类属性的工作,需要一个元类。 我不会在这里详细介绍,但是您可以在底部阅读更多内容,以 。

为了阐明我在基类中定义setter的含义,请考虑以下几点:

class Configuration:

    param1 = "a"

    @property
    def param2(self):
        return getattr(self, "_param2", self.param1 + "x")

    @param2.setter
    def param2(self, value):
        self._param2 = value


class Proj1(Configuration):

    param3 = "blah"

config = Proj1()
print(config.param2)  # ax
config.param2 = "new_val"
print(config.param2)  # new_val

而且,您可以对希望随心所欲覆盖的任何类属性执行相同的操作。

  相关解决方案