多个实例访问的Python类变量

时间:2019-05-13 20:25:41

标签: python

我想定义一个全局变量,该类的所有实例都可以访问(读取和写入)。我当前的解决方案显示在下面的示例中。我不喜欢在全局命名空间中使用变量,但是无法将idx放在类中。如何将idx放在课堂上并达到相同的目的?

# working
idx = 0
class test(object):
    def add(self):
        global idx
        idx += 1
    def print_x(self):
        global idx
        print(idx)

test1 = test()
test1.add()
test1.print_x()
test2 = test()
test2.add()
test2.print_x()

# Error
class test(object):
    idx = 0
    def add(self):
        global idx
        idx += 1
    def print_x(self):
        global idx
        print(idx)

test1 = test()
test1.add()
test1.print_x()
test2 = test()
test2.add()
test2.print_x()

Traceback (most recent call last):
  File "test.py", line 16, in <module>
    test1.add()
  File "test.py", line 9, in add
    idx += 1
NameError: global name 'idx' is not defined

4 个答案:

答案 0 :(得分:4)

您的代码失败,因为您尝试在未正确声明的情况下访问全局变量idx。您需要访问您的类变量。

class Test(object):
    idx = 0
    def add(self):
        Test.idx += 1

obj = Test()
obj.add()
print(Test.idx)
obj = Test()
obj.add()
print(Test.idx)

输出:

1
2

答案 1 :(得分:2)

这是一种不需要任何全局变量的小巧方法。它利用了以下事实:默认参数仅在首次调用__init__时创建一次,并且如果默认参数是可变的,则更改其中一个将影响同一类的所有将来函数/实例。

由于列表是可变的,因此我们可以将idx创建为列表,然后确保仅在适当位置修改该列表。这样做将确保Test类的所有实例都指向完全相同的idx列表。只要您只进行就地修改,更改一项就会全部更改。

class Test:
    def __init__(self, idx = [0]):
        self.idx = idx

    def add(self):
        self.idx[0] += 1

a = Test()
b = Test()

a.add()

print(a.idx, b.idx)
# >> Prints [1], [1]

答案 2 :(得分:1)

您可以使用单例模式来实现。这是一个单例的小例子:

class Singleton:
    # Here will be the instance stored.
    __instance = None

    @staticmethod
    def getInstance():
        """ Static access method. """
        if Singleton.__instance == None:
            Singleton()
        return Singleton.__instance

    def add(self):
        self.idx += 1

    def __init__(self):
        """ Virtually private constructor. """
        if Singleton.__instance != None:
            raise Exception("This class is a singleton!")
        else:
            Singleton.__instance = self
            self.idx = 0
In [3]: main = Singleton()
In [4]: a = Singleton.getInstance()
In [5]: print(a.idx)
0

In [6]: a.add()
In [7]: print(a.idx)
1

In [8]: b = Singleton.getInstance()
In [9]: print(b.idx)
1

参考:https://www.tutorialspoint.com/python_design_patterns/python_design_patterns_singleton.htm

在SO上也有一些优雅的Singleton示例。

答案 3 :(得分:0)

您必须在方法之外的类中定义变量,并且该变量不得为自变量。自变量对于每个实例都是唯一的。 在方法中,必须使用类名来访问变量,否则该方法会将其视为私有变量,并且在大多数情况下,您会得到一个错误,因为它在使用前未初始化。

class MyClass:
    my_public_variable = 0
    __my_private_variable = 5

    def inc(self):
        MyClass.my_public_variable += 1
        MyClass.__my_private_variable += 1

    def show(self):
        print(MyClass.my_public_variable)
        print(MyClass.__my_private_variable)

obj1 = MyClass()
obj1.show()

obj2 = MyClass()
obj2.show()

obj1.inc()
obj2.show()

print(obj1.my_public_variable)
print(obj1.my_private_variable) # Invokes error

运行此代码,将打印出不带括号的以下内容:

0  (my_public_variable of obj1)
5  (my_private_variable of obj1)
0  (my_public_variable of obj2)
5  (my_private_variable of obj2)
1  (my_public_variable of obj2, incremented by obj1)
6  (my_private_variable of obj2, incremented by obj1)
1  (my_public_variable of obj1, it can be accessed outside of the class, since it is a public variable of the class)
Error (because, as its name suggests, my_private_variable is a private variable of the class)