Python __init__ 参数问题
我无法理解列表类初始化参数会发生什么情况
like:
class A(object):
def __init__(self, argument=[]):
self.argument = argument[:]
or:
def __init__(self,argument=None):
self.arguments = arguments or []
or:
def __init__(self, argument=[]):
self.argument = argument
这是无法完成的,因为每个 A
对象的默认值都将指向同一块内存。我真的无法理解这里发生了什么以及它是如何发生的。
I have some trouble understanding what happens with class init arguments that are lists
like:
class A(object):
def __init__(self, argument=[]):
self.argument = argument[:]
or:
def __init__(self,argument=None):
self.arguments = arguments or []
or:
def __init__(self, argument=[]):
self.argument = argument
This can't be done because the default value for every A
object would point to the same piece of memory. I can't really understand what happens here and how it happens.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是众所周知的 python 陷阱。
基本上,该参数的默认值是在首次定义该方法时创建的,并且由于它是一个可变对象(在本例中是一个列表),因此即使在更改后,甚至在后续调用中,它也仅引用同一个对象到方法。
处理这种情况的通常方法是像第二个例子一样对待它:
但是如果你想要做的是拥有一个包含所有参数的列表,你可以使用Python的 参数解包。
它的工作原理如下:
然后,您将可以在方法中访问传递了所有参数的元组。因此,如果您像这样调用您的函数:
您的输出将如下所示:
最酷的是,您始终可以以相反的方式使用它,所以,让我们假设您有一个列表(或元组),并且您想要传递每个项目在列表中作为函数的位置参数。您可以这样做:
并且,就您的功能而言,它与之前的调用相同。
您还应该阅读我指出的文档作为更深入地介绍定义函数。
This is a well known python gotcha.
Basically, the default for that argument is created when the method is first defined, and since it is a mutable object (in this case, a list), it just referes to the same object even after it has changed, and even in subsequent calls to the method.
The usual way to deal with cases like that is to treat it like in your second example:
But if what you want to do is have a list with all your arguments you could just use Python's argument unpacking.
It works like this:
then, you will have in your method access to a tuple with all the arguments passed. So if you called your function like this:
Your output would look like:
The cool thing is, you can always use it in the oposite way, so, lets suppose you have a list (or tuple), and you want to pass every item in the list as a positional argument to your function. You would do this:
And, as far as your function is concerned, it is the same as the previous call.
You should read the documentation that I pointed to, as well as the section that goes a little more deeply on defining functions.
该列表是在运行定义时创建的,而不是在执行方法时创建的。
The list is created when the definition is run, not when the method is executed.
我认为这个问题有点不清楚,但我从中了解到的是,您想知道如何传递一个类初始化列表不会使内部对象与您传递的对象相同,而是一个副本。如果这不是问题,请告诉我,我将删除此答案。
简而言之,它的工作原理如下:在 Python 中,没有任何内容按名称按值存储。所有内容都在内部存储为指向 Python 对象的指针。当您这样做时:
您没有将
b
设置为a
的值。您将b
设置为引用同一对象。所以陈述:是真的,因为名称引用同一个对象。
这将返回 false。原因是现在您创建了两个不同的对象。所以这一行:
是制作 self.argument 副本的(必要的)方法,这样它就不会引用同一个对象。
I think the question is somewhat unclear, but what I understand from it is that you are wondering how passing a class init a list doesn't make the internal object the same one you pass it, but rather a copy. If this is not the question, tell me, and I'll delete this answer.
Briefly, here's how it works: nothing is stored as a name by value in Python. Everything is stored internally as a pointer to a Python object. When you do:
You're not setting
b
to the value ofa
. You're settingb
to reference the same object. So the statement:Is true, as the names reference the same object.
This will return false. The reason is that now you have created two different objects. So the line:
is a (necessary) way of making a copy of
self.argument
so that it doesn't reference the same object.