【问题标题】:Multidimensional list of classes - overwriting issue类的多维列表 - 覆盖问题
【发布时间】:2020-09-03 04:16:18
【问题描述】:

我想创建一个类列表,但是每次更改列表中的元素时,列表中的所有类元素都会被覆盖:

class TypeTest:
    def __init__(self):
    self.val = int()

data = list([TypeTest for _ in range(3)])

for i in range(3):
    data[i].val = i
    print([data[0].val, data[1].val, data[2].val])

最后,我需要一个多维数组,并且会有一个更复杂的类,但问题是一样的。

【问题讨论】:

  • 您可能忘记在列表理解中实例化TypeTest 对象。您将该课程放入列表中 3 次。

标签: python list class


【解决方案1】:

解决方案

在 for 循环中实例化您的类对象(列表理解)。 您使用的是list([...])。只需使用[TypeTest() for _ in range(3)]

# instantiate your class object
data = [TypeTest() for _ in range(3)] # after correction

# The line were you had the problem
data = list([TypeTest() for _ in range(3)]) # before correction

修改类定义

使用 __init__() 方法指定可选输入 val 及其类型(如 int)和默认值 0。这将允许您直接为属性,val 在实例化期间。或者,如果您愿意,您也可以随时更新它。

class TypeTest(object):

    def __init__(self, val: int=0, verbose: int=0):
        self.val = val
        self.verbose = verbose
        if self.verbose > 0:
            print(self)

    # include __repr__ in your class-def to print 
    # meaningful information about the class. 
    def __repr__(self):
        return '{}( val: {} )'.format(self.__class__.__name__, self.val)

单行代码(精简)

有了这个改变,你的代码可以简化为单行实例化+val的赋值:

# This will also print the objects created
# as we are using the keyword parameter: 
#     verbose = 1
data = [TypeTest(val=i, verbose=1) for i in range(3)]

输出

TypeTest( val: 0 )
TypeTest( val: 1 )
TypeTest( val: 2 )

【讨论】:

    【解决方案2】:

    您正在创建一个类引用数组,而不是对象(实例)引用,这意味着每个元素都指向同一个东西 - TypeTest class

    要创建对象,只需使用

    data = np.array([TypeTest() for _ in range(3)])
    

    如果出于某种原因您确实需要不同的类,则必须通过从基类继承来为每个元素创建一个新的。

    【讨论】:

      【解决方案3】:

      你需要在数组中创建这样的新对象。

      data = list([TypeTest() for _ in range(3)])
      

      【讨论】:

        【解决方案4】:

        TypeTest 是一个类型; TypeTest() 创建该类型的实例。你需要

        data = list([TypeTest() for _ in range(3)])
        

        而不是

        data = list([TypeTest for _ in range(3)])
        

        在后一种情况下,您只是将同一 TypeTest 的多个副本添加到列表中。

        确实,如果你打印列表元素的内存地址,你会发现它们是同一个对象:

        >>> data = list([TypeTest for _ in range(3)])
        >>> print([id(x) for x in data])
        [140184769568224, 140184769568224, 140184769568224]
        

        >>> data = list([TypeTest() for _ in range(3)])
        >>> print([id(x) for x in data])
        [4451998096, 4451996816, 4451996176]
        

        【讨论】:

          【解决方案5】:

          您以错误的方式使用您的课程。 init() 方法应该用于接受参数,这些参数可以在初始化时传递给你的 self.val 变量。这样你就不需要额外的循环来设置变量了。

          把类想象成一个蓝图,你必须实例化它才能得到真实的东西,它可以用作列表的元素等。

          >>> my_object = TypeTest()
          

          或创建对象列表:

          >>> data = [TypeTest(value) for value in range(3)]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-01-13
            • 1970-01-01
            • 1970-01-01
            • 2012-10-18
            • 1970-01-01
            • 2020-12-29
            • 1970-01-01
            相关资源
            最近更新 更多