考虑到内置的Python List-methods,我遇到了一个问题。
当我学习Python时,我总是认为Python mutators,就像任何值类mutator应该做的那样,返回它创建的新变量。
举个例子:
a = range(5)
# will give [0, 1, 2, 3, 4]
b = a.remove(1)
# as I learned it, b should now be [0, 2, 3, 4]
# what actually happens:
# a = [0, 2, 3, 4]
# b = None
此列表mutator未返回新列表的主要问题是,您不能随后进行多个突变。 假设我想要一个范围从0到5的列表,没有2和3。 返回新变量的mutators应该能够这样做:
a = range(5).remove(2).remove(3)
这是不可能的,如range(5).remove(2) = None
。
现在,有没有办法在列表中实际进行多次突变,就像我想在我的例子中做的那样?我认为即使是PHP也允许使用Strings进行这些类型的后续突变。
我也找不到所有内置Python函数的好参考。如果有人能找到所有列表mutator方法的实际定义(带有返回值),请告诉我。我能找到的就是这个页面:http://docs.python.org/tutorial/datastructures.html
答案 0 :(得分:9)
而不是两个变异和返回对象,Python库选择只使用一种方式来使用mutator的结果。来自import this
:
应该有一个 - 最好只有一个 - 显而易见的方法。
话虽如此,对于你想要做的更常见的Python风格是使用列表推导或生成器表达式:
[x for x in range(5) if x != 2 and x != 3]
您也可以将这些链接在一起:
>>> [x for x in (x for x in range(5) if x != 2) if x != 3]
[0, 1, 4]
上面的生成器表达式具有额外的优势,即它在 O(n)时间运行,因为Python只迭代range()
一次。对于大型生成器表达式,甚至对于无限生成器表达式,这都是有利的。
答案 1 :(得分:4)
list
和其他可变类型的许多方法都故意返回None
,因此您无需考虑是创建新对象还是改变现有对象。唯一可能发生的事情是变异,因为如果创建了一个新对象,它必须由该方法返回,并且不会返回。
您可能已经注意到,编辑字符串的str
方法会返回新字符串,因为字符串是不可变的,并且总是返回一个新字符串。
当然,没有任何东西可以阻止你在list
et al,上编写一个具有所需行为的.append()
子类,尽管这看起来像是一个沉重的锤子摆动只是为了让你链接方法调用。此外,大多数Python程序员不会期望这种行为,使您的代码不那么清晰。
答案 2 :(得分:4)
在Python中,基本上所有改变对象的方法都会返回None
。
这样你就不会意外地认为你有一个新的对象。
你提到
我认为即使是PHP也允许使用Strings进行这些类型的后续突变。
虽然我不记得PHP,通过字符串操作,你可以链式方法调用,因为字符串是不可变的,所以所有字符串方法返回一个新字符串,因为它们不会(不能)更改您调用它们的字符串。
>>> "a{0}b".format(3).center(5).capitalize().join('ABC').swapcase()
'a A3B b A3B c'
答案 3 :(得分:2)
Python或php都没有内置的“mutators”。你可以简单地写多行,比如
a = list(range(5))
a.remove(2)
a.remove(3)
如果要生成新列表,请事先复制旧列表:
a = list(range(5))
b = a[:]
b.remove(2)
请注意,在大多数情况下,对remove
的单一调用表示您应该首先使用set
。
答案 4 :(得分:-1)
要删除列表中的多个突变,您可以执行以下操作:
a = range(5)
a = [i for j, i in enumerate(a) if j not in [2, 3]]
a将是[0,1,4]