我一直在阅读如何使Python类不那么动态,特别是不允许用户动态创建新属性。我读过overloadding __setattr__
is a good way to do this和__slots__
is not the way to go。一个post on this last thread实际上表明__slots__
可以打破酸洗。 (任何人都可以证实这一点吗?)
然而,我只是在阅读Python 2.2的whatsnew,而the attribute access section实际上建议使用__slots__
来限制属性创建,而不仅仅是像其他人所建议的那样进行优化。就Python历史而言,有谁知道__slots__
的初衷是什么?限制变量创建是一个特征还是一个被滥用的bug?人们如何看待__slots__
在实践中使用?有很多人看到__setattr__
重载以限制属性创建?哪一个最好?如果您对一种方法或另一种方法更熟悉,请随意发布您知道的方法的优缺点。此外,如果您有不同的解决方法,请分享! (请尽量不要重复other threads中表达的__slots__
的缺点。)
EDIT 2,重新酸洗:这些物品将来会被我们想要储存,而酸洗似乎是一种很好的方法。如果__slots__
显然是最好的解决方案,我们可能会找到另一种方法来存储它们,但酸洗肯定是有价值的,应该加以考虑。
编辑3:我还应该提到记忆保存不是问题。这些对象中很少会被创建,因此保存的任何内存都可以忽略不计(例如3-12 GB机器上的10千字节)。
答案 0 :(得分:4)
为什么要限制开发人员这样做?除了“我不想让他们这样做”之外还有任何技术原因吗?如果没有,请不要这样做。
无论如何,使用__slots__
可以节省内存(无__dict__
),因此这是更好的解决方案。如果您的某些代码需要该对象具有__dict__
,则无法使用它。
如果有充分的理由限制它(再次,你确定有吗?)或你需要保存那么一点内存,那就去__slots__
。< / p>
阅读完解释后,您可能希望使用__setattr__
,可能与__slots__
结合使用(无论如何都需要将属性白名单存储在某处,因此您也可以使用它来节省内存)。这样您就可以显示一些更有用的信息,例如哪些类似的属性可用。可能的实现可能如下所示:
class Test(object):
__slots__ = ('foo', 'bar', 'moo', 'meow', 'foobar')
def __setattr__(self, name, value):
try:
object.__setattr__(self, name, value)
except AttributeError:
alts = sorted(self.__slots__, key=lambda x: levenshtein(name, x))
msg = "object has no attribute '{}', did you mean '{}'?"
raise AttributeError(msg.format(name, alts[0]))
我测试的levenshtein()
来自this site的实施#4。如果不是那么聪明的用户,您可能希望使错误更加冗长并包含所有紧密匹配而不仅仅是第一个匹配。
您可以通过创建仅包含__setattr__
方法的mixin类来进一步改进代码。这样,您可以将代码保留在真正的类中,并在必要时使用自定义__setattr__
(只需在mixin中使用super(...).__setattr__(...)
而不是object.__setattr__
)
答案 1 :(得分:1)
我对您的用例的建议是使用__setattr__
并在使用Python的warnings模块无法识别属性名称时发出警告。