Python-为什么这个类变量没有在方法中定义?

2024-05-12 22:16:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个python应用程序,如下所示:

global_counter = 0
connections = {}

class SocketHandler():
    currentid = 0
    def open(self):
        global global_counter
        global connections
        currentid = global_counter
        global_counter += 1
        connections[currentid] = self
        print "WebSocket " + str(currentid) + " opened"

    def on_close(self):
        global connections
        print "WebSocket " + str(currentid) + " closed"
        del connections[currentid]

我发现了错误:

NameError: global name 'currentid' is not defined

在“打开”和“打开/关闭”行中,我在其中打印我正在打开/关闭连接。我在类中定义了它,为什么它不在范围内。另外,我已经读到使用全局变量是不好的,但是我看不到解决这个问题的方法。有人能指出我该怎么做吗?谢谢。


Tags: self应用程序ondefcounteropenconnectionsglobal
3条回答

currentid应该是self.currentid,因为它是一个类变量。

currentid是实例属性,因此使用self.currentid而不是currentid

def on_close(self):
        global connections
        print "WebSocket " + str(self.currentid) + " closed"
        del connections[self.currentid]

在Python中,不能隐式访问方法内部的属性。

一个像currentid这样的空名字:

del connections[currentid]

在尝试全局模块作用域之前,始终在本地函数作用域中查找一个名称,然后在每个封闭函数作用域中查找一个名称(然后在最后一种方法中查看内置函数)。currentid是一个类属性,在这些作用域中都找不到。

要在Python中查找属性,需要指定要查找的对象。尽管查找协议意味着对象不一定需要属性本身;但属性查找将返回到指定对象的类(如果涉及继承,则返回基类)。

所以这是可行的:

del connections[self.currentid]

但是,我认为您的代码的其余部分也没有做您认为它是什么。open方法中的此行:

currentid = global_counter

不设置SocketHandler对象的currentid属性。赋值给裸名总是赋值给局部变量,除非您显式声明它global(您似乎意识到了这一点,因为您使用了global关键字)。所以在open方法中,currentid是一个局部函数变量;它的值在open方法的末尾丢失。

事实上,您的SocketHandler对象根本没有currentid属性(除非有更多代码您没有向我们显示)。把currentid = 0放在类块中并不能给所有的SocketHandler实例一个currentid属性。它给SocketHandler类本身一个属性currentid;这就像def open(self):块在类对象上创建open属性(存储函数)一样,而不是在每个单独的实例上。

读取on_close方法中的self.currentid将无法在对象self中找到currentid属性,因此Python将查看self的类,即SocketHandler。那个对象确实有一个currentid值,所以读取self.currentid的结果将是0,不管您以前是否在该SocketHandler上运行过open

如果要将currentid作为实例变量存储在每个SocketHandler中,那么open中的行将需要:

self.currentid = global_counter

这将分配给由self引用的对象的currentid属性。然后还需要将方法中对currentid的所有其他引用更改为self.currentid

相关问题 更多 >