Lyl*_*lax 7 python variables scope
我有一个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]
Run Code Online (Sandbox Code Playgroud)
我收到错误:
NameError: global name 'currentid' is not defined
Run Code Online (Sandbox Code Playgroud)
在"打开"和"on_close"的行上,我打印我打开/关闭连接.我在课堂上定义了它,为什么不在范围内.另外,我已经读过使用全局变量很糟糕,但我没有看到解决方法.有人可以指出我应该做什么吗?谢谢.
Ben*_*Ben 11
在Python中,您没有对方法内部属性的隐式访问权限.
一个简单的名字,如currentid行:
del connections[currentid]
Run Code Online (Sandbox Code Playgroud)
在尝试全局模块范围之前,总是在本地函数范围中查找名称,然后在每个封闭的函数范围中查找(然后将内置函数视为最后的手段).currentid是一个类属性,在任何这些范围中都找不到.
要在Python中查找属性,您始终需要指定要查看的对象.虽然查找协议意味着对象不一定必须具有属性本身; 属性查找将回退到您指定的对象的类(以及基类,如果涉及继承).
这样可行:
del connections[self.currentid]
Run Code Online (Sandbox Code Playgroud)
但是,我不认为你的代码的其余部分正在做你认为的那样.该open方法中的这一行:
currentid = global_counter
Run Code Online (Sandbox Code Playgroud)
不设置对象的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
Run Code Online (Sandbox Code Playgroud)
这将分配给currentid引用的对象的属性self.然后,您还需要将方法中的所有其他引用更改currentid为self.currentid.