简体   繁体   English

Python-为什么在方法中未定义此类变量?

[英]Python - Why is this class variable not defined in the method?

I have a python application which is as follows: 我有一个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]

I'm getting the error: 我收到错误消息:

NameError: global name 'currentid' is not defined

on the lines of "open" and "on_close" where I print that I am opening/closing the connection. 在“ open”和“ on_close”行上打印打开/关闭连接的地方。 I defined it in the class, why is it not in scope. 我在类中定义了它,为什么不在范围内。 Also, I have read that using global variables is bad, but I don't see a way around this. 另外,我已经读到使用全局变量是不好的,但是我没有找到解决这个问题的方法。 Can someone point out what I should do? 有人可以指出我该怎么做吗? Thanks. 谢谢。

You don't have implicit access to attributes inside methods, in Python. 在Python中,您没有隐式访问方法内部的属性的权限。

A bare name like currentid in the line: 该行中的裸名,如currentid

del connections[currentid]

always looks up a name in the local function scope, then in each enclosing function scope, before trying the global module scope (and then looks at built-ins as a last resort). 在尝试全局模块作用域之前,总是先在本地函数作用域中查找名称,然后在每个封闭的函数作用域中查找名称(然后将内置方法作为最后的选择)。 currentid is a class attribute, which won't be found in any of those scopes. currentid是一个类属性,在任何这些范围中都找不到。

To look up an attribute in Python you always need to specify an object in which to look. 要在Python中查找属性,您始终需要指定要在其中查找的对象。 Though the lookup protocol means the object need not necessarily have the attribute itself; 尽管查找协议意味着对象不一定必须具有属性本身; attribute lookup will fall back to the class of the object you specified (and the base classes, if inheritance is involved). 属性查找将回退到您指定的对象的类(如果涉及继承,则返回基类)。

So this would work: 所以这可以工作:

del connections[self.currentid]

However, I don't think the rest of your code is doing what you think it is either. 但是,我认为您的其余代码也没有按照您认为的那样做。 This line in the open method: 这行在open方法中:

currentid = global_counter

doesn't set the currentid attribute of your SocketHandler object. 不会设置SocketHandler对象的currentid属性。 Assigning to a bare name always assigns to a local variable, unless you explicitly declare it global (you appear to be aware of this, since you've used the global keyword). 赋予裸名总是会赋予局部变量,除非您明确地将其声明为global变量(因为您已经使用了global关键字,所以您似乎已经意识到这一点)。 So in the open method, currentid is a local function variable; 因此,在open方法中, currentid是局部函数变量; its value is lost at the end of the open method. 它的值在open方法结束时丢失。

In fact, your SocketHandler objects do not have a currentid attribute at all (unless there's more code you haven't shown us). 实际上,您的SocketHandler对象根本没有currentid属性(除非您没有向我们展示更多代码)。 Putting currentid = 0 in the class block doesn't give all the SocketHandler instances a currentid attribute. 在类块中放置currentid = 0并不会为所有SocketHandler实例提供currentid属性。 It gives the SocketHandler class itself an attribute currentid ; 它为SocketHandler本身提供了一个属性currentid this is just as the def open(self): block creates an open attribute (storing a function) on the class object, not on each individual instance. 就像def open(self):块在类对象(而不是每个单独的实例)上创建open属性(存储函数)一样。

Reading self.currentid in the on_close method will fail to find a currentid attribute in the object self , so Python will look at the class of self which is SocketHandler . on_close方法中读取self.currentid将无法在对象self找到currentid属性,因此Python将查看self的类SocketHandler That object does have a currentid value, so the result of reading self.currentid will be 0 , whether or not you've previously run open on that SocketHandler . 该对象确实具有currentid值,因此,无论您之前是否在该SocketHandler上运行open ,读取self.currentid的结果将为0

If you meant to store the currentid as an instance variable in each SocketHandler , then the line in open would need to be: 如果您打算将currentid作为实例变量存储在每个SocketHandler ,则open行将需要为:

self.currentid = global_counter

This assigns to the currentid attribute of the object referred to by self . 这将分配给self引用的对象的currentid属性。 You would also then need to change all the other references to currentid in your methods to self.currentid . 然后,您还需要将方法中对currentid所有其他引用更改为self.currentid

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

currentid is instance attribute, so use self.currentid instead of currentid : currentid是实例属性,因此请使用self.currentid而不是currentid

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM