在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模块。
我有这种方法的问题:
给您的问题:
我已经对我的问题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__
和捕获恶意写入,我想不出另一种阻止它的方法。如果您能想到任何事情,请在这里分享您的想法。
这种模式具有以下优点:
__setattr__
assert type in self.TYPES
或兼容assert isinstance(type, self.TYPES)
到目前为止,我可以看到用法上的两个区别:
.value
Enum的属性。因此,我需要使用哪一个正确地返回parent.type
(而不是返回"TYPES.MOTHER"
)。parent.type.value
'mother'
list(self.TYPES)
我认为使用Enum我也可以放弃ALL_CAPS标准,因为我不需要表示它types
是静态的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句