我正在努力实现一个具有最佳和最安全的约定的类。有没有更好的方法
a)防止对属性的外部编辑,以及
b)对这些属性强制执行某些约束,例如有效排名和诉讼?
class Card:
__ranks = ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King']
__suits = ['Heart', 'Club', 'Diamond', 'Spade']
def __init__(self, rank, suit):
assert rank in self.__ranks
assert suit in self.__suits
self.__rank = rank
self.__suit = suit
def getRank(self):
return self.__rank
def getSuit(self):
return self.__suit
您可以使用命名元组,以便该对象是不可变的
>>> from collections import namedtuple
>>> Card = namedtuple('Card','rank,suit')
>>> acard = Card('10','D')
>>> acard.suit
'D'
>>> acard.rank
'10'
>>> acard.rank='H'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>
有关更多信息,请参阅namedtuple
文档(在collections
模块中,https://docs.python.org/2/library/collections.html)
拥有类实例时,可以更改任何属性。但是你可以遵循惯例,即从单下划线开始的属性是私有的,你不应该直接访问它们,除非你知道你在做什么。
真正提供你想要的公共界面@property
装饰器。
来自docs的报价:
在当前的实现中,内置变量
__debug__
在正常情况下是True
,False
在请求优化时(命令行选项-O
)。在编译时请求优化时,当前代码生成器不会为assert语句发出任何代码。
资产仅用于开发。它们可以用于测试检查等。如果你需要检查适当的值传递到__init__
方法,你可以提高ValueError
或从它派生的自定义错误。
class Card(object):
class CardValueError(ValueError):
pass
__ranks = ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10',
'Jack', 'Queen', 'King']
__suits = ['Heart', 'Club', 'Diamond', 'Spade']
def __init__(self, rank, suit):
if rank not in self.__ranks or suit not in self.__suits:
raise Card.CardValueError()
self.__rank = rank
self.__suit = suit
@property
def rank(self):
return self.__rank
@property
def suit(self):
return self.__suit
通过属性装饰器控制此类行为更为常见。实际上,您可以通过不实现setter来创建只读属性:
class Foo:
def __init__(self, bar):
self._bar = bar
@property
def bar(self):
"""Read-only access to bar."""
return self._bar
我不会打扰双下划线名称。这仍然不会(并且不打算)使外部无法访问属性。