为什么[]
要比list()
?
最大的原因是Python list()
就像用户定义的函数一样对待,这意味着您可以通过别名别名来拦截它list
并做一些不同的事情(例如使用您自己的子类列表或双端队列)。
它将立即使用创建新的内置列表实例[]
。
我的解释旨在为您提供直觉。
说明
[]
通常称为文字语法。
在语法中,这称为“列表显示”。从文档:
列表显示是括在方括号中的一系列可能为空的表达式:
list_display ::= "[" [starred_list | comprehension] "]"
列表显示将产生一个新的列表对象,其内容由表达式列表或理解列表指定。提供逗号分隔的表达式列表时,将按从左到右的顺序评估其元素,并将其按此顺序放入列表对象中。提供理解后,将根据理解产生的元素来构建列表。
简而言之,这意味着将list
创建一个内置类型的对象。
不能回避这一点-这意味着Python可以尽快完成它。
另一方面,list()
可以list
使用内置列表构造函数拦截创建内置对象的过程。
例如,假设我们希望创建噪音较大的列表:
class List(list):
def __init__(self, iterable=None):
if iterable is None:
super().__init__()
else:
super().__init__(iterable)
print('List initialized.')
然后,我们可以list
在模块级别的全局范围内截取该名称,然后在创建时list
,实际上创建了子类型列表:
>>> list = List
>>> a_list = list()
List initialized.
>>> type(a_list)
<class '__main__.List'>
同样,我们可以将其从全局名称空间中删除
del list
并将其放在内置名称空间中:
import builtins
builtins.list = List
现在:
>>> list_0 = list()
List initialized.
>>> type(list_0)
<class '__main__.List'>
并注意列表显示无条件创建列表:
>>> list_1 = []
>>> type(list_1)
<class 'list'>
我们可能只是暂时执行此操作,所以请撤消更改-首先List
从内置文件中删除新对象:
>>> del builtins.list
>>> builtins.list
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'builtins' has no attribute 'list'
>>> list()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'list' is not defined
哦,不,我们失去了原来的踪迹。
不用担心,我们仍然可以得到list
-它是列表文字的类型:
>>> builtins.list = type([])
>>> list()
[]
所以...
为什么[]
要比list()
?
如我们所见-我们可以覆盖list
-但是我们不能截取文字类型的创建。使用时,list
我们必须进行查找以查看是否存在任何内容。
然后,我们必须调用已查找的任何可调用对象。从语法上:
调用使用一系列可能为空的参数来调用可调用对象(例如,函数):
call ::= primary "(" [argument_list [","] | comprehension] ")"
我们可以看到它对任何名称都具有相同的作用,而不仅仅是列表:
>>> import dis
>>> dis.dis('list()')
1 0 LOAD_NAME 0 (list)
2 CALL_FUNCTION 0
4 RETURN_VALUE
>>> dis.dis('doesnotexist()')
1 0 LOAD_NAME 0 (doesnotexist)
2 CALL_FUNCTION 0
4 RETURN_VALUE
因为[]
在Python字节码级别没有函数调用:
>>> dis.dis('[]')
1 0 BUILD_LIST 0
2 RETURN_VALUE
它只是直接建立列表而无需在字节码级别进行任何查找或调用。
结论
我们已经证明了list
可以使用范围规则用用户代码拦截,并且可以list()
查找可调用对象然后调用它。
而[]
列表显示或文字显示则避免了名称查找和函数调用。
()
并且''
很特殊,因为它们不仅是空的,而且是不可变的,因此,使它们成为单例很容易。他们甚至不构造新对象,只需为空tuple
/ 加载单例str
。从技术实现的细节,但我也很难想象他们为什么不 缓存空tuple
/str
性能方面的原因。因此你对直觉[]
和{}
传回股票面值是错误的,但它确实适用于()
和''
。