您可以使用list或tuple(或者任何可迭代的?)在新式python类中定义__slots__
。创建实例后类型仍然存在。
鉴于元组总是比列表更有效并且是不可变的,你有什么理由不想使用__slots__
的元组吗?
>>> class foo(object):
... __slots__ = ('a',)
...
>>> class foo2(object):
... __slots__ = ['a']
...
>>> foo().__slots__
('a',)
>>> foo2().__slots__
['a']
答案 0 :(得分:4)
首先,元组并不比列表更有效;它们都支持来自C API代码的完全相同的快速迭代机制,并使用相同的代码进行索引和从Python迭代。
更重要的是,__slots__
机制实际上并不使用__slots__
成员,除非在构建期间。这可能不是the documentation清楚解释的,但是如果你仔细阅读了所有的要点,那么信息就在那里。
实际上, 是真的。否则,这不起作用:
class Foo(object):
__slots__ = (x for x in ['a', 'b', 'c'] if x != 'b')
......更糟糕的是,这会:
slots = ['a', 'b', 'c']
class Foo(object):
__slots__ = slots
foo = Foo()
slots.append('d')
foo.d = 4
进一步证明:
>>> a = ['a', 'b']
>>> class Foo(object):
... __slots__ = a
>>> del Foo.__slots__
>>> foo = Foo()
>>> foo.d = 3
AttributeError: 'Foo' object has no attribute 'd'
>>> foo.__dict__
AttributeError: 'Foo' object has no attribute '__dict__'
>>> foo.__slots__
AttributeError: 'Foo' object has no attribute '__slots__'
因此,__slots__
中的Foo
成员实际上仅用于文档和内省目的。这意味着没有性能问题或行为问题,只是风格问题。
答案 1 :(得分:0)
根据Python docs ..
可以为此类变量分配字符串,可迭代或序列 具有实例使用的变量名称的字符串。
因此,您可以使用任何可迭代来定义它。您使用哪一个取决于您,但就“优先”而言,我会使用一个列表。
首先,让我们看一下如果性能不是问题会是首选的选择,这意味着它将是所有Python代码中的same decision you would make between list and tuples。我会说一个列表,原因是因为元组设计具有语义结构:它应该在语义上表示将元素存储为第一个项而不是第二个项的东西。例如,如果将(X,Y)坐标元组(X)的第一个值存储为第二个项,则只需完全更改结构的语义值。如果重新排列__slots__
列表中属性的名称,则表示您没有在语义上更改任何内容。因此,在这种情况下,您应该使用列表。
现在,关于表现。首先,这可能是过早的优化。我不知道列表和元组之间的性能差异,但我想不管怎么说都没有。但即使假设存在,如果多次访问__slots__
变量,它真的只会发挥作用。
我实际上没有查看访问__slots__
时的代码,但我运行了以下测试..
print('Defining slotter..')
class Slotter(object):
def __iter__(self):
print('Looking for slots')
yield 'A'
yield 'B'
yield 'C'
print('Defining Mine..')
class Mine(object):
__slots__ = Slotter()
print('Creating first mine...')
m1 = Mine()
m1.A = 1
m1.B = 2
print('Creating second mine...')
m2 = Mine()
m2.A = 1
m2.C = 2
基本上,我使用自定义类,以便我可以确切地看到slot变量实际迭代的时间。当定义类时,你会看到它完成了一次。
Defining slotter..
Defining Mine..
Looking for slots
Creating first mine...
Creating second mine...
除非在__slots__
变量再次迭代的情况下遗漏了我的情况,否则我认为性能差异在最坏情况下可以忽略不计。