繁体   English   中英

Python类范围和列表

[英]Python Class scope & lists

我仍然是Python的新手,我的OO经验来自Java。 所以我有一些我用Python编写的代码,对我来说非常不寻常,给出以下代码:

class MyClass():
        mylist = []
        mynum = 0

        def __init__(self):
                # populate list with some value.
                self.mylist.append("Hey!")
                # increment mynum.

                self.mynum += 1

a = MyClass()

print a.mylist
print a.mynum

b = MyClass()

print b.mylist
print b.mynum

运行此结果会产生以下输出:

['Hey!']
1
['Hey!', 'Hey!']
1

很明显,我希望类变量能够得到完全相同的数据,并且输出完全相同......我无法在任何地方找到的是什么使得列表与字符串或数字不同,为什么是列表从后续的第一个实例中引用相同的列表? 很明显,我可能误解了某种范围机制或列表创建机制。

tlayton的答案是故事的一部分,但并不能解释所有事情。

添加一个

print MyClass.mynum

变得更加困惑:)。 它将打印'0'。 为什么? 因为行

self.mynum += 1

创建一个实例变量,然后增加它。 它不会增加变量。

mylist的故事是不同的。

self.mylist.append("Hey!")

不会创建列表。 它期望存在具有“追加”功能的变量。 由于实例没有这样的变量,因此它最终引用了类中的一个,它确实存在,因为你初始化它。 就像在Java中一样,实例可以“隐式地”引用类变量。 像“类字段应该由类引用,而不是由实例引用”(或类似的东西;自从我在Java中看到它以来已经有一段时间)的警告将是有序的。 添加一行

print MyClass.mylist

验证这个答案:)。

简而言之:您正在初始化类变量并更新实例变量。 实例可以引用类变量,但某些“更新”语句将自动为您创建实例变量。

你在这里做的不仅仅是创建一个类变量。 在Python中,类体中定义的变量既导致类变量(“MyClass.mylist”),又导致实例变量(“a.mylist”)。 这些是单独的变量,而不仅仅是单个变量的不同名称。

但是,当以这种方式初始化变量时,初始值仅被计算一次并传递给每个实例的变量。 这意味着,在您的代码中,MyClass的每个实例的mylist变量都指向一个列表对象。

在这种情况下,列表和数字之间的区别在于,与Java一样,当从一个变量传递到另一个变量时,会复制诸如数字之类的原始值。 这会导致您看到的行为; 即使变量初始化仅被计算一次,但是当将0传递给每个实例的变量时,也会复制0。 但是,作为一个对象,列表没有这样的东西,所以你的append()调用都来自同一个列表。 试试这个:

class MyClass():
    def __init__(self):
        self.mylist = ["Hey"]
        self.mynum = 1

这将导致每次创建实例时单独评估值。 与Java不同,您不需要在此片段中附带类体声明; __init __()中的赋值用作所需的所有声明。

我认为区别在于+=是一个赋值(与=+相同),而append就地改变了一个对象。

    mylist = []
    mynum = 0

这会在类定义时分配一些类变量。

    self.mylist.append("Hey!")

这会通过附加字符串来更改值MyClass.mylist

    self.mynum += 1

这与self.mynum = self.mynum + 1 ,即它分配self.mynum (实例成员)。 self.mynum读取属于类成员,因为那时没有该名称的实例成员。

暂无
暂无

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

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