简体   繁体   English

Python __init__参数问题

[英]Python __init__ argument problem

I have some trouble understanding what happens with class init arguments that are lists 我很难理解作为列表的类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  

This can't be done because the default value for every A object would point to the same piece of memory. 这是不可能的,因为每个A对象的默认值都指向同一块内存。 I can't really understand what happens here and how it happens. 我真的不明白这里发生了什么以及它是如何发生的。

This is a well known python gotcha . 这是一个众所周知的python 陷阱

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: 处理这类案件的通常方法是像第二个例子那样对待它:

def __init__(self, arguments=None):  
    self.arguments = arguments or []

But if what you want to do is have a list with all your arguments you could just use Python's argument unpacking . 但是如果你想要做的是拥有一个包含所有参数的列表,你可以使用Python的参数解压缩

It works like this: 它的工作原理如下:

def my_function(*args):
    print args

then, you will have in your method access to a tuple with all the arguments passed. 然后,您将在您的方法中访问传递了所有参数的元组。 So if you called your function like this: 所以如果你这样调用你的函数:

>>> my_function(1, 2, 3)

Your output would look like: 您的输出看起来像:

(1, 2, 3)

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: 你会这样做:

>>> my_list = [1, 2, 3]
>>> my_function(*my_list)

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 . 您应该阅读我指出文档,以及更深入地定义函数的部分

运行定义时创建列表,而不是在执行方法时创建。

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. 简而言之,这是它的工作原理:在Python中没有任何内容存储为值的名称。 Everything is stored internally as a pointer to a Python object. 一切都在内部存储为Python对象的指针。 When you do: 当你这样做时:

a = [1,2,3]
b = a

You're not setting b to the value of a . 你不设定b设置 a You're setting b to reference the same object. 您将b设置为引用同一对象。 So the statement: 声明如下:

a is b

Is true, as the names reference the same object. 是的,因为名称引用相同的对象。

a = [1,2,3]
b = [1,2,3]
a is b

This will return false. 这将返回false。 The reason is that now you have created two different objects. 原因是现在你已经创建了两个不同的对象。 So the line: 所以行:

self.argument = argument[:]

is a (necessary) way of making a copy of self.argument so that it doesn't reference the same object. 是一种(必要的)方法来制作self.argument的副本,以便它不引用同一个对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM