简体   繁体   English

混淆python中的类行为

[英]Confusing class behavior in python

I don't understand the behavior of arrays in classes when looping over over them in an array of objects.当在对象数组中遍历数组时,我不理解类中数组的行为。

Ok, let's say i have this code:好的,假设我有这段代码:

class example:
    arr = []
    def __init__(self):
        self.arr.append(69)

examples = []
for i in range(5):
    examples.append(example())
for e in examples:
    for a in e.arr:
        print(str(a))

Expected output is five 69s, but it prints 25 of them.预期输出是五个 69,但它打印了其中的 25 个。 Why?为什么?

EDIT: I've somehow figured out that all the instances use the SAME ARRAY, how is that possible if i used self ?编辑:我不知何故发现所有实例都使用相同的数组,如果我使用self怎么可能?

example has a list -valued class attribute, so all instances of example share that same list. example有一个list属性,因此 example 的所有example共享同一个列表。 (You never assigned to self.arr , so you did not create an instance attribute that shadows the class attribute.) If you had created one instance of example, then example.arr would have one element. (您从未分配给self.arr ,因此您没有创建一个隐藏类属性的实例属性。)如果您创建了一个示例example,那么example.arr将有一个元素。 If you had created 50 instances of example, then example.arr would have 50 elements.如果您创建了 50 个example,example.arr将有 50 个元素。

As a resut, example.arr contains 5 elements, because you created 5 instances of example .结果, example.arr包含 5 个元素,因为您创建了 example 的 5 个example (There aren't 5 objects each with a singleton list specific to it.) Your nested loop prints the full contents of a 5-element list 5 times, resulting in 25 lines of output. (没有 5 个对象,每个对象都有一个特定的单例列表。)您的嵌套循环将 5 元素列表的全部内容打印 5 次,产生 25 行输出。

What you likely intended was for your class to be defined as follows:您可能打算将您的课程定义如下:

class Example:
    def __init__(self):
        self.arr = []
        self.arr.append(69)
        # Which would be the long way of writing
        # self.arr = [69]

Now the code现在的代码

examples = []
for i in range(5):
    examples.append(example())

would give you a list of objects whose arr attribute each contains a single element, and会给你一个对象列表,每个对象的arr属性都包含一个元素,并且

for e in examples:
    for a in e.arr:
        print(str(a))

would iterate over the distinct singleton list of each object, producing the expected 5 lines of output.将遍历每个对象的不同单例列表,产生预期的 5 行输出。

You are appending 69 to arr 5 times while simultaneously appending the class to examples list.您将69附加到arr 5 次,同时将类附加到examples列表。 If you try this:如果你试试这个:

class example:
    arr = []
    def __init__(self):
        self.arr.append(69)
        print(self.arr)

You can see that your arr already has 69 5 times.可以看到你的arr已经有69 5 次了。

Then, when you append the example class to your list it keeps on appending the class, however simultaneously the example class keeps on updating.然后,当您将example类附加到您的列表时,它会继续附加该类,但同时example类会不断更新。 Your current examples list outputs this:您当前的examples列表输出如下:

[<__main__.example object at 0x000001A2026EFAF0>, <__main__.example object at 0x000001A2026EFAC0>, <__main__.example object at 0x000001A2026EFA90>, <__main__.example object at 0x000001A2026EF8B0>, <__main__.example object at 0x000001A2026EF730>]

This whole list contains of the example class which has been lately updated to the arr containg 69 5 times.整个列表包含最近更新到arr 69 5 次的示例类。
To make your code functional with OOP try this:要使您的代码适用于 OOP,请尝试以下操作:

class example:
    arr = []
    def __init__(self):
        self.arr.append(69)

examples = []
for i in range(5):
    example.arr = []
    examples.append(example())
for e in examples:
    for a in e.arr:
        print(a)

Edit: Thanks to @chepner for the clarification of OP's requirement.编辑:感谢@chepner 对 OP 要求的澄清。

As you are updating the class variable each time, the arr variable in class appends the number, every time it is called.当您每次更新类变量时,类中的 arr 变量会在每次调用时附加数字。 To avoid the behaviour, try the below if this was your intention.为避免这种行为,如果这是您的意图,请尝试以下操作。

    class example:
            #arr = []
            def __init__(self):
                    self.arr = []
                    self.arr.append(69)  ## now that the self.arr is defined it acts as object variable, else it will try to find the variable in the class.
    
    examples = []
    for i in range(2):
            examples.append(example())
    
    for e in examples:
            for a in e.arr:
                    print(str(a))

Please find the below reference, hope this helps: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables请找到以下参考资料,希望对您有所帮助: https ://docs.python.org/3/tutorial/classes.html#class-and-instance-variables

example.arr does only have 5 elements in it: example.arr中只有 5 个元素:

print(example.arr)

… but you're iterating over example.arr 5 times (once for every one of the 5 example objects in the examples list) …但是你在example.arr上迭代了 5 次( examples列表中的 5 个example对象中的每一个对象一次)

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

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