您如何预先知道方法(或函数)在调用时是否会更改变量?

时间:2018-08-22 20:02:18

标签: python methods

我是R语言的Python新手。最近,我花了很多时间阅读Python中的所有内容如何成为对象,对象可以自己调用方法,方法是类中的函数的方式,yada yada yada。

这是我不明白的地方。使用以下简单代码:

mylist = [3, 1, 7]

如果我想知道数字7出现了多少次,我可以这样做:

mylist.count(7)

那当然会返回1。如果我想将计数保存到另一个变量中:

seven_counts = mylist.count(7)

到目前为止,太好了。除了语法以外,其行为类似于R。但是,假设我正在考虑将数字添加到列表中:

mylist.append(9)

等等,该方法实际上更改了变量本身! (即“ mylist”已更改,现在将数字9作为列表的第四位。)将代码分配给新变量(就像我对seven_counts所做的那样)会产生垃圾:

newlist = mylist.append(9)

我发现这种行为的不一致有点奇怪,坦率地说是不可取的。 (比方说,我想先看看追加结果如何,然后可以选择是否将其分配给新变量。)

我的问题很简单:

是否可以提前知道调用特定方法是否会真正改变您的变量(对象)?

3 个答案:

答案 0 :(得分:3)

除了阅读文档(对于某些方法,该方法将包括指定返回值的类型注释)或在交互式解释器中使用该方法(包括使用help()检查类型注释的文档字符串)之外,否,仅通过查看方法就无法知道。

也就是说,您看到的行为是故意的。 Python方法 返回对象的 new 修改副本修改对象;至少在内置程序中,它们既不会做任何事情(某些方法会变异对象并返回非None值,但绝不会仅仅是对象被变异; {pop {1}}和dict是这种情况的示例。

此或/或行为是故意的;如果他们不遵守该规则,那么您将面临一个更加混乱且难以识别的问题,即确定list是变异了它所调用的值还是返回了一个新对象。您肯定回来了append,但这是新的list还是相同的list?如果它更改了它调用的值,那么

list

有点奇怪; newlist = mylist.append(9) newlist将是同一个mylist的别名(所以为什么要同时使用两个名称?)。您可能有一阵子都没有注意到;您会继续使用list,以为它独立于newlist,而只是看着mylist并发现它们被弄乱了。通过使所有此类“就地修改”方法返回mylist(或至少不是原始对象),可以更快/更轻松地发现错误;如果您尝试使用None,而错误地认为它是newlist,则会立即得到listTypeError s。

基本上,提前知道的唯一方法是阅读文档。对于名称表示修改操作的方法,您可以检查返回值,并经常了解它们是否正在变异。首先,它有助于了解哪些类型是可变的。 AttributeErrorlistdictset都是可变的,并且它们的方法具有不可变的对应物(除了bytearray之外,它们没有不可变的对应物)的缺乏往往会使对象在原处发生变异。

默认情况是倾向于简单地更改对象,因为这样做更有效;如果您有100,000个元素dict,则list的默认行为会产生一个新的100,001个元素append并返回它,这将是非常低效的(并且没有明显的方法来避免它) )。对于不可变类型(例如liststrtuple),这是不可避免的,如果希望保证对象永远不会发生突变,则可以使用这些类型,以不必要的对象创建和销毁为代价,这在大多数情况下会降低代码的速度。

答案 1 :(得分:2)

只需签出文档:

>>> list.count.__doc__
'L.count(value) -> integer -- return number of occurrences of value'
>>> list.append.__doc__
'L.append(object) -> None -- append object to end'

实际上并不是很容易分辨,但是:

  

不可变对象->无法通过方法调用进行更改

例如,tuple没有影响元组的方法,因为它是不可更改的,因此方法只能返回新实例。

如果您“想先看一下追加结果,然后可以选择是否将其分配给新变量”,则可以使用一个元素。

>>> l = [1,2,3]
>>> k = l + [4]
>>> l
[1, 2, 3]
>>> k
[1, 2, 3, 4]

答案 2 :(得分:0)

不仅仅是您的调用(您的方法调用)。您可以保证,如果仅传递不可变的对象,则该方法不会更改该对象,但是某些定义了 的方法可以更改该对象-并且不会为您使用的方法定义任何方法,否则会执行失败。

在《真实生活》中,您可以查看该方法的文档:这将告诉您确切的情况。

[我正要包括Joe Iddon的答案所涵盖的内容...]