在为班级成员设定价值时如何防止错别字?

时间:2010-06-20 12:58:53

标签: python

考虑以下示例:

class A():
    def __init__(self):
        self.veryImportantSession = 1

a = A()
a.veryImportantSession = None # ok

# 200 lines below
a.veryImportantSessssionnnn = 2 # I wanna exception here!! It is typo!

如果我尝试设置未在__init__中设置的成员,我怎么能这样做才会引发异常?

上面的代码在执行时不会失败,但给我一个有趣的时间来调试问题。

与str:

一样
>>> s = "lol"
>>> s.a = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'a'

谢谢!

3 个答案:

答案 0 :(得分:6)

您可以覆盖__setattr__以仅允许定义列表中的属性名称。

class A(object):
    def __setattr__(self, name, value):
        allowed = ('x',)
        if name in allowed:
            self.__dict__[name]  = value
        else:
            raise AttributeError('No attribute: %s' % name) 

在操作中:

>>> a = A()
>>> a.x = 5
>>> a.other = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "myc.py", line 7, in __setattr__
    raise AttributeError('No attribute: %s' % name)
AttributeError: No attribute: other   

但是,正如msw所评论的那样,尝试使Python更像Java或C ++的行为通常是一个坏主意,并且会导致失去Python提供的许多好处。如果您担心可能会错过拼写错误,那么您最好花时间为代码编写单元测试,而不是试图锁定类的使用。

答案 1 :(得分:2)

防止拼写错误的最佳方法是使用pyflakespylint等工具 - 这些工具将通过您的代码告诉您是否有变量a.superImportantSesssssionnnn不再使用,以及许多其他事情。

如果您坚持在代码中执行此操作,则有两种选择:

  • (ab)使用__slots__ - __slots__的主要目的是在您拥有数百,数千或数百万个对象并且需要保留物体的足迹尽可能小。如果你走这条路线,你应该确保将__weakref__作为允许的名称之一,以便weak references继续工作。

  • (ab)使用__setattr__ - __setattr__的主要目的是允许运行代码来验证,操作或以其他方式获取给定的数据并将其置于正确的位置存储格式

重申一下,上述两个选项并不打算用作拼写检查程序,并且您通过禁止每个可能的属性名称来限制代码的有用性的努力除了您自己使用的少数属性之外可能不会被人理解正试图支持你没有预料到的用例。

答案 2 :(得分:1)

您可以定义名为__slots__的类变量。有关详细信息,请参阅Language Reference

__slots__仅适用于新式课程,因此在此示例中您需要class A(object)而不是class A

class A(object):
    __slots__ = ['x']
    def __init__(self):
        self.x = 1

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