Python模块/类可变出血

时间:2009-04-24 00:57:06

标签: python oop class

好吧,我花了一点时间来缩小这个问题,但看起来python正在做这个目的。有人可以解释为什么会发生这种情况以及我可以做些什么来解决这个问题?

文件:library / testModule.py

class testClass:

    myvars = dict()

    def __getattr__(self, k):
        if self.myvars.has_key(k):
            return self.myvars[k]

    def __setattr__(self, k, v):
        self.myvars[k] = v

    def __str__(self):
        l = []
        for k, v in self.myvars.iteritems():
            l.append(str(k) + ":" + str(v))

        return " - ".join(l)

test.py

from library import testModule

#I get the same result if I instantiate both classes one after another
c1 = testClass()
c1.foo = "hello"
c2 = testClass()

print("c1: " + str(c1) + "\n")
print("c2: " + str(c2) + "\n")

输出:

c1: foo:hello
c2: foo:hello

我最好的猜测是因为library有一个"__init__.py"文件,整个模块就像一个类对象一样被加载,它现在变成了一个持久对象的一部分..这是这种情况吗?

3 个答案:

答案 0 :(得分:7)

myvars的属性,而不是实例。这意味着当您从实例myvarsc1插入属性时,该属性将与类testClass相关联,而不是与实例c1相关联。由于c2是同一个类的实例,因此它也具有相同的属性。

你可以通过写下这个来获得你想要的行为:

class testClass:
    def __init__(self):
        self.myvars = dict()

    def __getattr__(self, k):
        if self.myvars.has_key(k):
            return self.myvars[k]

    def __setattr__(self, k, v):
        self.myvars[k] = v

    def __str__(self):
        l = []
        for k, v in self.myvars.iteritems():
            l.append(str(k) + ":" + str(v))
        return " - ".join(l)

答案 1 :(得分:2)

其他答案是正确的。让我来谈谈我认为你的误解是什么。

  

我最好的猜测是因为库有一个“__init__.py”文件,整个模块就像一个类对象一样被加载,它现在变成了一个持久对象的一部分......就是这样吗?

所有包都有__init__.py个文件。有必要制作python包。该软件包可能包含也可能没有任何代码。如果确实如此,则保证执行。在一般情况下,这与包中的其他模块的执行方式没有任何关系,尽管它确实可以在那里放置很多非常酷的技巧,但确实会影响它。

至于模块和类的工作方式,将模块视为一次实例化的类对象通常是一个非常好的主意。加载程序执行一次文件,然后可以在文件末尾访问所有可用的变量,类定义和函数定义。

类也是如此,主要的例外是在类中声明的函数被转换为方法(并且一个特殊的方法让你实例化类)。因此testModule有一个testClass有一个myvars。所有三个对象都是唯一的:不会有多个实例。无论我们说“模块有一个类对象”还是“类对象有一个类变量”,has-a relathionship实际上或多或少都是一样的。 (不同之处在于您不应该关注的实施细节。)

答案 2 :(得分:0)

有关如何使用 getattr 以及其他类似方法的参考,请参阅How-To Guide for Descriptors,并且没有什么比练习更好的了。