在Python中,函数参数是通过对象引用传递的。这意味着修改列表的最简单代码将修改对象本身。
a = [1,2,3]
def remove_one(b):
b.remove(1)
remove_one(a)
print(a)
Run Code Online (Sandbox Code Playgroud)
该方法remove_one不返回任何内容。如果这是一个公共方法,则必须假设它将修改对象并且在方法内不是线程安全的。
第二种方法是像这样构建代码片段:
a = [1,2,3]
def remove_one(b):
b.remove(1)
return(b)
print(remove_one(a[:]))
Run Code Online (Sandbox Code Playgroud)
这里 a 的内容没有被修改,并返回一个新列表。这给方法调用者带来了很多责任。
话又说回来list comprehensions,修改列表内容的Pythonic方法总是创建一个新对象。
a = [1,2,3]
def remove_one(b):
b = [num for num in b if b!=1]
return(b)
print(remove_one(a))
Run Code Online (Sandbox Code Playgroud)
我不清楚是否有一种“Pythonic”方式来做到这一点,所以我会做出一些假设来挑战:
TLDR:如果修改参数,请勿返回它。
list.sort()对列表进行适当排序。为了提醒您这一事实,它不会返回排序列表。
惯用的做法是通过不返回参数来指示是否修改参数。例如,您的第一个案例是正确的,您的第二个案例则不正确:
def remove_one(b):
b.remove(1) # modify, do not return
Run Code Online (Sandbox Code Playgroud)
如果您不修改参数但创建副本,则return该副本必须使操作有意义:
def one_removed(b):
c = b.copy() # create new object...
c.remove(1)
return c # ...and return it
Run Code Online (Sandbox Code Playgroud)
函数/方法名称通常反映它们是否主动修改其参数。修饰功能倾向于使用主动动词,而非修饰功能倾向于使用被动动词或形容词。
没有“Pythonic”选择是否修改参数 - 对原始或副本进行操作是两种根本不同的操作。两者都有效,具体取决于用例。
>>> items = [4, 3, 10, 2, 5]
>>> sorted(items)
[2, 3, 4, 5, 10]
>>> items.sort()
>>> items
[2, 3, 4, 5, 10]
Run Code Online (Sandbox Code Playgroud)
一般来说,在 Python 中改变参数速度更快,而创建新结果更容易推理。具体来说,推导式代表函数式编程操作(即map和filter)——它们被设计为不修改其可迭代对象。
是否因修改而返回参数仅与该参数有关。例如,list.pop修改列表并且不返回它——但是,它确实返回弹出的元素。
| 归档时间: |
|
| 查看次数: |
913 次 |
| 最近记录: |