Python - Why is this class variable not defined in a method?

I have a python application that looks like this:

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 get an error message:

 NameError: global name 'currentid' is not defined 

in the lines "open" and "on_close", where I print that I open / close the connection. I identified him in the class, why he is not in the field. Also, I read that using global variables is bad, but I don't see a way around this. Can someone please indicate what I should do? Thanks.

+4
source share
3 answers

You do not have implicit access to attributes inside methods in Python.

Voice name of type currentid in line:

 del connections[currentid] 

always looking for a name in the scope of local functions, then in each scope of the enclosing function, before trying the global scope of the module (and then looking at the embedded attachments as a last resort). currentid is an attribute of a class that will not be found in any of these areas.

To find an attribute in Python, you always need to specify an object to view. Although the search protocol means that the object does not have to have the attribute itself; the attribute search returns to the class of the object you specified (and base classes if inheritance is involved).

So this will work:

 del connections[self.currentid] 

However, I don’t think the rest of your code does what you think. This line in the open method:

 currentid = global_counter 

does not set the currentid attribute of your SocketHandler object. Assigning a common name is always assigned to a local variable unless you explicitly declare it global (you seem to be aware of this since you used the global ). Thus, in the open method, currentid is a local variable of the function; its value is lost at the end of the open method.

In fact, your SocketHandler objects do not have the currentid attribute at currentid (unless you have already currentid us with the code). Putting currentid = 0 in a class block does not give all the attributes of SocketHandler a currentid . It gives a SocketHandler class attribute currentid ; this is the same as a def open(self): block def open(self): creates an open attribute (saving a function) for a class object, and not for each individual instance.

Reading self.currentid in the self.currentid method on_close not find the currentid attribute in the self object, so Python will look at the self class, which is equal to SocketHandler . This object has a currentid value, so the result of reading self.currentid will be 0 , regardless of whether you previously ran open on this SocketHandler .

If you wanted to keep currentid as an instance variable in each SocketHandler , then the line in open should be:

 self.currentid = global_counter 

This sets the currentid attribute of the object that self points to. You will also need to change all other references to currentid in your methods to self.currentid .

+7
source

currentid should be self.currentid , as it is a class variable.

+2
source

currentid is an instance attribute, so use self.currentid instead of currentid :

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

Source: https://habr.com/ru/post/1438513/


All Articles