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
在“ open”和“
on_close”行上打印打开/关闭连接的行。我在类中定义了它,为什么不在范围内。另外,我已经读到使用全局变量是不好的,但是我没有找到解决这个问题的方法。有人可以指出我该怎么做吗?谢谢。
问题答案:
在Python中,您没有隐式访问方法内部的属性的权限。
像这样的裸名currentid
:
del connections[currentid]
在尝试全局模块作用域之前,总是先在本地函数作用域中查找名称,然后在每个封闭的函数作用域中查找名称(然后将内置方法作为最后的选择)。currentid
是一个类属性,在任何这些范围中都找不到。
要在Python中查找属性,您 始终
需要指定要在其中查找的对象。尽管查找协议意味着对象不一定必须具有属性本身;属性查找将回退到您指定的对象的类(如果涉及继承,则返回基类)。
所以这将工作:
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
在每个实例中将as作为实例变量存储SocketHandler
,则其中的行open
必须为:
self.currentid = global_counter
这将分配给所currentid
引用的对象的属性self
。然后,您还需要将方法中的所有其他引用更改currentid
为self.currentid
。