【发布时间】:2020-03-24 03:11:41
【问题描述】:
在 Python 中实现静态不可变属性的正确方法是什么?
小例子:
程序模块“家庭”有一个类Parent,定义如下:
class Parent():
def __init__(self, type):
self.type = type
父级可以是以下两种字符串类型之一:'mother' 或 'father'。该类的外部用户应该能够在构造时设置类型,然后查询parent.type 以获取这两个值中的任何一个。此外,Family 模块的其他部分使用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行
- 感觉很老套(可能是由于我在其他语言中使用受语言支持的私有静态变量的经验)
- 我的 IDE 的 linter 不喜欢它,因为没有“self”参数(即使提供了)
您的问题:
- 这个方法是 Pythonic 的吗?
- 有更好的方法吗?
- 您能否建议一种模式来实现这种不变性,同时强制用户仅使用我希望他们使用的变量,防止他们将原始字符串传递给构造函数?
【问题讨论】:
-
相关,如果不重复:stackoverflow.com/q/36932/1639625
标签: python design-patterns interface immutability static-variables