我有一个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
在我打开/关闭连接的“打开”和“on_close”行上。我在类中定义了它,为什么不在范围内。另外,我已经读到使用全局变量是不好的,但是我没有找到解决这个问题的方法。有人可以指出我该怎么做吗?谢谢。
最佳答案
在Python中,您没有隐式访问方法内部的属性的权限。
该行中的裸名,如currentid
:
del connections[currentid]
在尝试全局模块作用域之前,总是先在本地函数作用域中查找名称,然后在每个封闭的函数作用域中查找名称(然后将内置方法作为最后的选择)。
currentid
是一个类属性,在任何这些范围中都找不到。要在Python中查找属性,您始终需要指定要在其中查找的对象。尽管查找协议(protocol)意味着对象不一定必须具有属性本身,但是对象本身不一定具有属性。属性查找将回退到您指定的对象的类(如果涉及继承,则返回基类)。
因此,这将工作:
del connections[self.currentid]
但是,我认为您的其余代码也没有按照您认为的那样做。
open
方法中的这一行:currentid = global_counter
没有设置
currentid
对象的SocketHandler
属性。赋予裸名总是会分配给局部变量,除非您明确声明它为global
(由于使用了global
关键字,您似乎已经意识到了这一点)。因此,在open
方法中,currentid
是局部函数变量;它的值在open
方法的末尾丢失。实际上,您的
SocketHandler
对象根本没有currentid
属性(除非您没有向我们展示更多代码)。将currentid = 0
放在类块中并不能为所有SocketHandler
实例提供currentid
属性。它给SocketHandler
类本身一个属性currentid
;就像def open(self):
块在类对象(而不是每个单独的实例)上创建open
属性(存储函数)一样。用
self.currentid
方法读取on_close
将无法在对象currentid
中找到self
属性,因此Python将查看self
的类SocketHandler
。该对象确实具有currentid
值,因此,无论您先前是否对该self.currentid
运行0
,读取open
的结果将为SocketHandler
。如果您打算将
currentid
作为实例变量存储在每个SocketHandler
中,则open
中的行将需要为:self.currentid = global_counter
这将分配给
currentid
引用的对象的self
属性。然后,您还需要将方法中对currentid
的所有其他引用更改为self.currentid
。关于Python-为什么在方法中未定义此类变量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12790114/