Python静态不可变属性

我去

在Python中实现静态不可变属性的正确方法是什么?

最小示例:

程序模块“家庭”具有一个类Parent,定义如下:

class Parent():
    def __init__(self, type):
        self.type = type

父级可以是以下两种字符串类型之一:'mother''father'此类的外部用户应该能够在构造时设置类型,并在以后进行查询parent.type以获取这两个值之一。此外,“家庭”模块的其他部分利用Parent该类并依赖于所返回的这两个值中的任何一个。因此,对该类型的要求如下:

  • 对用户和内部模块都可用
  • 永远是“母亲”或“父亲”,因此要基于不可变的变量

天真的方法可以鼓励通过传递字符串来设置类型:

parent = Parent('mother')

但这会导致意外的拼写错误(例如Parent('omther'))。为了防止这种情况,我采用以下方法:

class Parent():
    TYPE_MOTHER = 'mother'
    TYPE_FATHER = 'father'
    TYPES = [TYPE_MOTHER, TYPE_FATHER]

    def __init__(self, type):
        assert type in self.TYPES, ('Invalid type "%s"' % type)
        self.type = type

parent = Parent(Parent.TYPE_MOTHER)

但是,没有什么能阻止用户根据需要更改这些静态变量,例如:

parent = Parent('mother')
Parent.TYPE_MOTHER = 'burrito'
print(parent.type == Parent.TYPE_MOTHER)
#> False

为了解决这个问题,我考虑使用@staticmethod@property注释:

class Parent():
    @property
    @staticmethod
    def TYPE_MOTHER():
        return 'mother'

    @property
    @staticmethod
    def TYPE_FATHER():
        return 'father'

这不会阻止用户将字符串传递给构造函数(例如Parent('mother')),但至少会阻止用户通过更改父类型可以弄乱Family模块。


我有这种方法的问题:

  • 很难看,用4行代码代替了1行
  • 感觉很hack(可能是由于我在使用其他语言支持的语言的私有静态变量方面的经验)
  • 我的IDE的linter不喜欢它,因为没有'self'参数(即使提供了它)

给您的问题:

  • 这是Pythonic吗?
  • 有更好的方法吗?
  • 您是否可以建议一种将实现这种不变性的模式,同时还可以强制用户仅使用我希望它们使用的变量,从而阻止它们将原始字符串传递给构造函数?
我去

我已经对我的问题Enum(doc)找到了一个整洁的答案

from enum import Enum
class Parent():
    class TYPES(Enum):
        MOTHER = 'mother'
        FATHER = 'father'

    def __init__(self, type:TYPES):
        assert type in self.TYPES, ('Invalid type "%s"' % type)
        self.type = type

parent = Parent(Parent.TYPES.MOTHER)

在这种情况下,用户仍然可以覆盖Parent.TYPES除了使用__setattr__和捕获恶意写入,我想不出另一种阻止它的方法如果您能想到任何事情,请在这里分享您的想法。

这种模式具有以下优点:

  • 由于Enum的政策,无法覆盖MOTHER和父亲的各个属性
  • 由于以下原因,无法覆盖TYPES __setattr__
  • 无法使用原始字符串代替Parent.TYPES.MOTHER(或.FATHER)
  • assert type in self.TYPES兼容assert isinstance(type, self.TYPES)

到目前为止,我可以看到用法上的两个区别:

  • 如果我想获得实际值-即。“母亲”或“父亲”,那么我需要使用.valueEnum属性。因此,我需要使用哪一个正确地返回parent.type而不是返回"TYPES.MOTHER"parent.type.value'mother'
  • 要打印我需要使用的TYPES内容 list(self.TYPES)

我认为使用Enum我也可以放弃ALL_CAPS标准,因为我不需要表示它types是静态的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章