编写安全的,强制执行的Python类

问题描述 投票:1回答:3

我正在努力实现一个具有最佳和最安全的约定的类。有没有更好的方法

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
python class
3个回答
2
投票

您可以使用命名元组,以便该对象是不可变的

>>> 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


1
投票

Prevent external edits to properties

拥有类实例时,可以更改任何属性。但是你可以遵循惯例,即从单下划线开始的属性是私有的,你不应该直接访问它们,除非你知道你在做什么。

真正提供你想要的公共界面@property装饰器。

Enforce certain constraints

来自docs的报价:

在当前的实现中,内置变量__debug__在正常情况下是TrueFalse在请求优化时(命令行选项-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

1
投票

通过属性装饰器控制此类行为更为常见。实际上,您可以通过不实现setter来创建只读属性:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
       """Read-only access to bar."""
       return self._bar

我不会打扰双下划线名称。这仍然不会(并且不打算)使外部无法访问属性。

© www.soinside.com 2019 - 2024. All rights reserved.