星号运算符(*)应用于列表和整数

时间:2013-12-23 07:55:46

标签: python python-2.7

假设我们有一个Foo类,我们想要实例化一个foos列表,我们可以按如下方式进行:

foo_list = [Foo()] * 3

现在如果foo_list[0].x = 5怎么办?此语句会将属性x设置为列表中实例的全部 !!!

当我发现它时,它引起了我的注意。问题是当我们创建这样的列表时,显然python将首先创建Foo实例,然后创建列表实例,然后将相同的对象追加到它3次,但我真的希望它能做某事像这样:

foo_list = [Foo() for i in range(3)]
你不是吗?好吧,现在我知道肯定这个语法糖不能用,因为我想用它,但那么,它用于什么?我唯一能想到的是创建一个初始大小的列表,如下所示:list = [None] * 5,对于python来说,这对我来说没有多大意义。

这种语法有没有其他真正有用的用例?

3 个答案:

答案 0 :(得分:7)

您可以使用星形表单,使用任何不可变类型,例如

print [5] * 3
print "abc" * 3
print [1.1] * 3
print (8,) * 3

让我们说,例如

nums = [5] * 3
print map(id, nums)

我机器上的输出

[41266184, 41266184, 41266184]

id函数给出了当前对象的唯一ID。如您所见,以这种方式创建不可变对象非常简单,高效。因为创建的对象中的所有元素都指向同一个元素。 (记住使用的对象是不可变的)

所以,作为经验法则

如果对象可变,请使用列表理解表单

[Foo() for i in range(3)]

如果对象不可变,则可以使用星形

[5] * 3

答案 1 :(得分:0)

它根本不是语法糖,只是乘以一个列表。也就是说,

foo_list = [Foo()] * 3

foo_list = ( [Foo()] ) * 3

foo_instance = Foo()
bar_list = [foo_instance]
foo_list = bar_list * 3

根本没有特殊的语法。它创建的列表与列表相同的内容相同,为三次。

我使用它的一件事是当我得到一个未知长度的列表并且我希望它具有完全长度n时,然后我添加一个n次默认值的列表,然后切片:

def set_to_length(l, n, defaultvalue=0):
    return (l + [defaultvalue] * n)[:n]

当然,使用可变的默认值进行操作会导致麻烦,正如您所发现的那样。

答案 2 :(得分:0)

语法:

list=[any_object]*n

是制作n个相同对象列表的捷径。您可以看到以下内容:

>>> l=[foo()]*3
>>> l
[<__main__.foo instance at 0x02D64D28>, <__main__.foo instance at 0x02D64D28>, <__main__.foo instance at 0x02D64D28>]
>>> m=[ foo() for i in range(3)]
>>> m
[<__main__.foo instance at 0x02D64F08>, <__main__.foo instance at 0x02D613A0>, <__main__.foo instance at 0x02D611C0>]

在上面的代码中,

中的三个对象是相同的

list l

如内存位置所示,或者您可以使用id(object)但在

list m

他们是不同的。 关键是当你使用列表推导时,你实际上是在一行中创建三个对象的过程,而不是使用循环来实例化对象并将它们放在一个列表中,但前者list=[any_object]*n只是一个附加的镜头列表中所需的次数相同的对象。