[英]Change object directly in function is anti-pattern in python?
Assume that we have to get some value and change it from function.假设我们必须得到一些值并将其从 function 更改。
Way-1方式一
def change_b(obj):
obj['b'] = 4
result = {'a': 1, 'b': 2}
change_b(obj=result)
print(result)
As you know that function change_b()
change result['b']
's value directly in function.如您所知,function change_b
change_b()
直接在 function 中更改result['b']
的值。
Way-2方式二
from copy import deepcopy
def change_b(obj):
temp = deepcopy(obj)
temp['b'] = 4
return temp
result = {'a': 1, 'b': 2}
result = change_b(obj=result)
print(result)
But Way-2 copying object to new object and replace value from new object.但是方式 2将 object 复制到新的 object 并从新的 object 替换值。
So, original object doesn't affect anything.所以,原来的 object 不会影响任何东西。 (Also, no side-effect)
(而且,没有副作用)
Maybe Way-2 is more safe, because it doesn't change original object.也许Way-2更安全,因为它不会改变原来的object。
I wonder that which one is more general and pythonic way?我想知道哪一种更通用和pythonic的方式?
Thanks.谢谢。
If the API is explicit that it is updating its input, Way-1 is fine and desirable: add_route(route_map, new_route)
.如果 API 明确表示它正在更新其输入,则Way-1很好且可取:
add_route(route_map, new_route)
。
If the API is primarily about doing something else, then Way-2 avoids unintended side-effects.如果 API 主要是为了做其他事情,那么Way-2可以避免意外的副作用。
Way-1 : The dict.update() and list.sort() do in-place updates because that is their primary job.方式 1 : dict.update()和list.sort()进行就地更新,因为这是它们的主要工作。
Way-2 : The builtin sorted() function produces a new sorted list from its inputs which it takes care not to alter.方式 2 :内置的sorted() function 从其输入中生成一个新的排序列表,注意不要更改。 Roughly, it does this:
大致来说,它是这样做的:
def sorted(iterable, *, key=None, reverse=False):
result = list(iterable) # copy the data
result.sort(key=key, reverse=reverse) # in-place sort
return result
Hope that clarifies when to copy and when to mutate in-place:-)希望澄清何时复制以及何时就地变异:-)
"Explicit is better than implicit"
“显式胜于隐式”
......
"In the face of ambiguity, refuse the temptation to guess."“面对模棱两可,拒绝猜测的诱惑。”
Modifying a parameter within a function is not necessarily a bad thing.修改 function 中的参数不一定是坏事。 What is bad is to do so with no good reason for doing so.
不好的是没有充分理由这样做。 If you're clear with your function name and documentation that the parameter will be modified within the function, then that's fine.
如果您清楚您的 function 名称和文档将在 function 中修改参数,那很好。 If the function modifies the parameter with no indication it's trying to do so, that's less fine.
如果 function 修改了参数而没有任何迹象表明它正在尝试这样做,那就不太好了。
In this case, your Way-1 is simpler and more explicit.在这种情况下,您的Way-1更简单、更明确。 It's obvious that the variable is going to be changed, and the way in which it's going to be changed can be determined easily by looking at the code.
很明显,变量将被更改,并且通过查看代码可以轻松确定更改的方式。
Way-2 is worse, because the name change_b
would imply that the parameter is going to be modified, and it's not .方式 2更糟糕,因为名称
change_b
意味着参数将被修改,而不是. Returning a modified version of a parameter without modifying the original is a standard design pattern in python, but it's best to be explicit about it.返回参数的修改版本而不修改原始版本是 python 中的标准设计模式,但最好明确说明。
For example, python's built-in set
data structure has counterpart methods: set.difference(other)
and set.difference_update(other)
.例如,python 内置的
set
数据结构有对应的方法: set.difference(other)
和set.difference_update(other)
。 In both cases, they do the same thing: compute the difference between this set and the given set.在这两种情况下,它们都做同样的事情:计算这个集合和给定集合之间的差异。 In the former case, that result is returned without modifying the original set.
在前一种情况下,返回结果而不修改原始集。 In the latter case, the original set is modified and nothing is returned.
在后一种情况下,原始集合被修改并且不返回任何内容。 It's very straightforward to figure out which does what.
弄清楚哪个做什么是非常简单的。
In general, you should probably avoid updating a value and returning that same value, because that's more ambiguous.一般来说,您可能应该避免更新一个值并返回相同的值,因为这更加模棱两可。 Note how most python methods do one or the other, but not both (and those that do do both, like
list.pop()
, do so sensibly, with the returned object not being the object that was modified).请注意大多数 python 方法如何做一个或另一个,但不是两者都做(以及同时做这两个的方法,如
list.pop()
,这样做是明智的,返回的 object 不是经过修改的 ZA8CFDE6331BD59EB2AC96F8911C4B666)。
As I understand Python, the most Pythonic way to approach this problem is to make it very clear what is happening.据我了解 Python,解决此问题的最 Pythonic 方法是非常清楚正在发生的事情。 As long as you do that, I don't believe it matters.
只要你这样做,我认为这并不重要。
my_dict = {'a': 3, 'b': 4}
double_values_in_dict(my_dict)
# Some other code
This is a contrived example, but it's pretty clear what's intended to happen here, even without the method definition included.这是一个人为的例子,但很清楚这里打算发生什么,即使没有包含方法定义。 What would be unclear is if you assigned the return value of
double_values_in_dict
to a new variable;不清楚的是,如果您将
double_values_in_dict
的返回值分配给一个新变量; I wouldn't know then what you may have done to the original dict
object, and I'd have to start digging through that method to figure out how it actually works.那时我不知道您可能对原始
dict
object 做了什么,我必须开始深入研究该方法以弄清楚它是如何工作的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.