我有一个 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
在“open”和“on_close”行上,我打印我正在打开/关闭连接。我在类中定义了它,为什么它不在范围内。另外,我读到过使用全局变量是不好的,但我看不出解决这个问题的方法。有人可以指出我应该做什么吗?谢谢。
最佳答案
在 Python 中,您无法隐式访问方法内部的属性。
行中的 currentid
之类的裸名:
del connections[currentid]
总是在局部函数作用域中查找一个名称,然后在每个封闭函数作用域中查找,然后再尝试全局模块作用域(然后将内置函数作为最后的手段)。 currentid
是一个类属性,不会在任何这些范围内找到。
要在 Python 中查找属性,您总是需要指定要查找的对象。尽管查找协议(protocol)意味着对象本身不一定具有属性;属性查找将回退到您指定的对象的类(以及基类,如果涉及继承)。
所以这会起作用:
del connections[self.currentid]
但是,我认为您的其余代码也没有按照您的想法行事。 open
方法中的这一行:
currentid = global_counter
没有设置 SocketHandler
对象的 currentid
属性。分配给一个裸名总是分配给一个局部变量,除非你明确声明它global
(你似乎意识到了这一点,因为你已经使用了 global
关键字)。所以在open
方法中,currentid
是一个局部函数变量;它的值在 open
方法结束时丢失。
事实上,您的 SocketHandler
对象根本没有 currentid
属性(除非您没有向我们展示更多代码)。将 currentid = 0
放在类 block 中并不会为所有 SocketHandler
实例提供 currentid
属性。它给SocketHandler
类自身一个属性currentid
;这就像 def open(self):
block 在类对象上创建一个 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
。
关于Python - 为什么这个类变量没有在方法中定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12790114/