python - 使 Python 类在创建新属性时抛出错误

标签 python class python-2.7 attributes

假设这是我的类(class):

class A:
    def __init__(self):
        self.good_attr = None
        self.really_good_attr = None
        self.another_good_attr = None

然后调用者可以设置这些变量的值:

a = A()
a.good_attr = 'a value'
a.really_good_attr = 'better value'
a.another_good_attr = 'a good value'

但他们也可以添加新的属性:

a.goood_value = 'evil'

这对我的用例来说是不可取的。我的对象被用来将一些值传递给一组方法。 (所以本质上,这个对象替换了一些方法上的一长串共享参数,以避免重复并清楚地区分什么是共享的,什么是不同的。)如果调用者输入了一个属性名称,那么该属性将被忽略,导致意外令人困惑且可能难以弄清楚的行为。最好快速失败,通知调用者他们使用了一个将被忽略的属性名称。因此,当他们使用对象上尚不存在的属性名称时,类似于以下内容的行为是我想要的:

>>> a.goood_value = 'evil'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'goood_value'

我怎样才能做到这一点?

我还想指出,我完全知道调用者可以创建一个新类并做任何他们想做的事,完全绕过这个。但是,这将是不受支持的行为。制作我提供的对象只是创建一个快速失败的愚蠢检查,以节省那些确实利用我提供的对象(包括我自己)的拼写错误的时间,而不是让他们挠头想知道为什么事情会以意想不到的方式表现.

最佳答案

您可以使用 __setattr__ 方法连接到属性设置。此方法为所有 属性设置调用,因此请考虑它也会为您的“正确”属性调用:

class A(object):
    good_attr = None
    really_good_attr = None
    another_good_attr = None

    def __setattr__(self, name, value):
        if not hasattr(self, name):
            raise AttributeError(
                '{} instance has no attribute {!r}'.format(
                    type(self).__name__, name))
        super(A, self).__setattr__(name, value)

因为 good_attr 等是在类上定义的,所以 hasattr() 调用会为这些属性返回 True,并且不会引发异常.您也可以在 __init__ 中设置这些相同的属性,但是要在 hasattr() 工作的类上定义这些属性

另一种方法是创建一个您可以测试的白名单。

演示:

>>> a = A()
>>> a.good_attr = 'foo'
>>> a.bad_attr = 'foo'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 10, in __setattr__
AttributeError: A instance has no attribute 'bad_attr'

当然,坚定的开发人员仍然可以通过向 a.__dict__ 实例字典添加键来向您的实例添加属性。

另一种选择是利用 __slots__ 的副作用;插槽用于节省内存,因为字典比将值直接放入 Python 为每个实例创建的 C 结构中占用更多空间(那时不需要键和动态表)。副作用是在这样的类实例上没有更多属性的地方:

class A(object):
    __slots__ = ('good_attr', 'really_good_attr', 'another_good_attr')

    def __init__(self):
        self.good_attr = None
        self.really_good_attr = None
        self.another_good_attr = None

错误信息如下所示:

>>> a = A()
>>> a.good_attr = 'foo'
>>> a.bad_attr = 'foo'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'bad_attr'

但请务必阅读文档中列出的有关使用 __slots__ 的注意事项。

因为在使用 __slots__ 时没有 __dict__ 实例属性,这个选项实际上关闭了在实例上设置任意属性的大门。

关于python - 使 Python 类在创建新属性时抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25061792/

相关文章:

Python2.7 UnicodeEncodeError : 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128)

python - 如何将字符串添加到文件中的奇数行?

python - 从 String 中删除一个 char,更有效的方法是什么?

python - 如何使用 Statsmodels 库从 Pandas 数据框创建马赛克图?

c++ - 用于命名可以采用两个值(真和假)的类的属性的技术术语?

python - 拆分字符串值,然后使用 pandas 创建一个新值

java - 如何以最佳方式从类对象创建实例

python - 添加到 dict 这是一个类的属性

python - 如何使用管道和 FeatureUnion 添加功能

python - 在 iOS 中使用 python 库