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

2024-09-30 02:16:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚从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作为列表中的第四个数字。)将代码赋给一个新的变量(就像我对七个\u计数所做的那样)会产生垃圾:

newlist = mylist.append(9)

我发现这种行为的不一致性有点奇怪,坦率地说是不可取的。(假设我想先看看append的结果是什么样的,然后可以选择是否将其赋给一个新变量。)

我的问题很简单:

有没有办法提前知道调用一个特定的方法是否会改变你的变量(对象)?你知道吗


Tags: 对象方法函数代码列表count时间语法
3条回答

不仅仅是调用(方法调用)。如果只传入不可变的对象,则可以保证方法不会更改对象,但有些方法是定义的来更改对象的,并且不会为您使用的方法定义,或者在执行时会出错。你知道吗

在现实生活中,你看看这个方法的文档:它会告诉你到底发生了什么。你知道吗

[我正要把乔·伊登的回答包括在内…]

除了阅读文档(对于某些方法,它将包含指定返回值的类型注释)或在交互式解释器中使用方法(包括使用help()检查docstring中的类型注释)之外,不,您不能仅仅通过查看方法就预先知道。你知道吗

也就是说,你看到的行为是故意的。Python方法要么返回对象的新的修改过的副本要么就地修改对象;至少在内置方法中,它们从不同时执行这两个操作(有些方法会修改对象并返回一个非None值,但它决不是刚刚修改过的对象;dictlistpop方法就是一个例子本案中)。你知道吗

这种非此即彼的行为是有意为之的;如果他们不遵守这条规则,那么您将遇到一个更容易混淆和难以识别的问题,即确定append是否改变了调用它的值,或者返回了一个新对象。你肯定得到了一个list,但它是一个新的list还是相同的list?如果它改变了所调用的值

newlist = mylist.append(9)

有点奇怪;newlistmylist是同一个list的别名(为什么两个名字都有?)。你可能一段时间都没有注意到;你会继续使用newlist,以为它独立于mylist,结果看到mylist就发现一切都搞砸了。通过让所有这些“modify in place”方法返回None(或者至少不是原始对象),可以更快/更容易地发现错误;如果您尝试使用newlist,错误地认为它是list,您会立即得到TypeErrorAttributeError

基本上,提前知道的唯一方法就是阅读文档。对于名称指示修改操作的方法,您可以检查返回值,并经常了解它们是否在发生变化。首先,它有助于了解哪些类型是可变的;listdictsetbytearray都是可变的,并且它们不可变的对应项(除了没有不可变的对应项的dict)所缺少的方法往往会在适当的位置对对象进行变异。你知道吗

默认情况下,只需简单地对对象进行适当的修改就可以了,因为这样效率更高;如果有100000个元素list,那么append的默认行为会生成一个新的100001个元素list并返回它,这将是非常低效的(而且没有明显的方法可以避免它)。对于不可变的类型(例如strtuplefrozenset),这是不可避免的,如果您希望保证对象永远不会原地突变,那么可以使用这些类型,但是这样做的代价是不必要地创建和销毁对象,这在大多数情况下会减慢代码的速度。你知道吗

只需签出文档:

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

其实没有一个简单的方法来判断,但是:

immutable object > no way of changing through method calls

例如,tuple没有影响元组的方法,因为元组是不可更改的,所以方法只能返回新实例。你知道吗

如果你“想先看看append的结果是什么样的,然后可以选择我是否想把它赋给一个新的变量”,那么你可以把这个列表和一个新的列表和一个元素连接起来。你知道吗

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

相关问题 更多 >

    热门问题