I am working on a small game server in Python using the class SimpleWebSocketServer found here. Everything works great, but the problem is each time I want to access a variable, I have to use self.variable_name. Let me give an example.
class SimpleEcho(WebSocket):
times_played_since_reset = 0
def handleMessage(self):
global times_played_since_reset
print times_played_since_reset
Whenever I try accessing times_played_since_reset using global it doesn't work and the server quits. Make it self.times_played_since_reset and everything works.
This variable needs affected by EVERY client connected. Unfortunately when I make it using self, only the client affects it's own instance. I need it to be where the client affects the class-wide variable instead of self.
You might want to consider using a mutable type for times_played_since_reset if you want it to be shared between all instances of the class.
Integers are not mutable, so they are not shared. As mentioned in the comments above, you could explicitly modify the class variable by doing something like SimpleEcho.times_played_since_reset += 1 however this only works as long as the instance attribute of the same name has not explicitly been set/modified.
For instance, take this example class:
class Foo(object):
bar = 1
If we create two instances:
>>> x = Foo()
>>> y = Foo()
Then:
>>> x.bar
1
>>> y.bar
1
And if we do:
>>> Foo.bar += 1
Then
>>> x.bar
2
>>> y.bar
2
But if we do:
>>> x.bar = 7
>>> Foo.bar +=1
Then:
>>> x.bar
7
>>> y.bar
3
If instead you were to use a mutable type like a list, For example like:
class Foo(object):
bar = [1]
whether you modify Foo.bar[0] or <instance>.bar.[0] all current and future instances would see the change. This is because they all reference the same list, and you have modified the contents of the list rather than changing the specific object the variable points to.
However, if you were to assign a new list via <instance>.bar = [78], only that instance would see the change and all other instances (current and future) would still reference the original list that was defined in the class definition.
To access global variables from python server, use:
(Class Name).variable
SimpleEcho.times_played_since_reset
Related
This question already has answers here:
How do I get a result (output) from a function? How can I use the result later?
(4 answers)
Closed 4 months ago.
I am trying to access a local function variable outside the function in Python.
I can make code like this work with global variables:
bye = ''
def hi():
global bye
bye = 5
sigh = 10
hi()
print(bye)
Next, I tried this code, hoping to access bye outside hi() without using global bye:
def hi():
bye = 5
sigh = 10
return
hi()
x = hi()
print(x.bye)
This gives AttributeError: 'NoneType' object has no attribute 'bye'.
Next, I tried:
def hi():
bye = 5
sigh = 10
return bye
hi()
x = hi()
print(x.bye)
This didn't improve matters; I get AttributeError: 'int' object has no attribute 'bye'.
Is there a way to access a local function variable (bye) outside its function (hi()) without using globals and also without printing out the sigh variable? How can I do it?
You could do something along these lines (which worked in both Python v2.7.17 and v3.8.1 when I tested it/them):
def hi():
# other code...
hi.bye = 42 # Create function attribute.
sigh = 10
hi()
print(hi.bye) # -> 42
Functions are objects in Python and can have arbitrary attributes assigned to them.
If you're going to be doing this kind of thing often, you could implement something more generic by creating a function decorator that adds a this argument to each call to the decorated function.
This additional argument will give functions a way to reference themselves without needing to explicitly embed (hardcode) their name into the rest of the definition and is similar to the instance argument that class methods automatically receive as their first argument which is usually named self — I picked something different to avoid confusion, but like the self argument, it can be named whatever you wish.
Here's an example of that approach:
def add_this_arg(func):
def wrapped(*args, **kwargs):
return func(wrapped, *args, **kwargs)
return wrapped
#add_this_arg
def hi(this, that):
# other code...
this.bye = 2 * that # Create function attribute.
sigh = 10
hi(21)
print(hi.bye) # -> 42
Note
This doesn't work for class methods. Just use the instance argument, named self by convention, that's already passed to methods instead of the method's name. You can reference class-level attributes through type(self). See Function's attributes when in a class.
The problem is you were calling print(x.bye) after you set x as a string. When you run x = hi() it runs hi() and sets the value of x to 5 (the value of bye; it does NOT set the value of x as a reference to the bye variable itself). EX: bye = 5; x = bye; bye = 4; print(x) prints 5, not 4.
Also, you don't have to run hi() twice, just run x = hi(), not hi(); x=hi() (the way you had it it was running hi(), not doing anything with the resulting value of 5, and then rerunning the same hi() and saving the value of 5 to the x variable.
So full code should be
def hi():
bye = 5
sigh = 10
return bye
x = hi()
print(x)
If you wanted to return multiple variables, one option would be to use a list, or dictionary, depending on what you need. For example:
def hi():
return { 'bye': 5, 'sigh': 10 }
x = hi()
print x['bye']
def hi():
bye = 5
return bye
print hi()
You could do something along this lines:
def static_example():
if not hasattr(static_example, "static_var"):
static_example.static_var = 0
static_example.static_var += 1
return static_example.static_var
print static_example()
print static_example()
print static_example()
To be able to access a local function's variable, one might add the name of the function and a dot before the name of the local variable (and then, of course, use this construction for calling the variable both in the function's body and outside of it). This solution works in Python 3.7.4.
For example:
def func(): # define a function
# here y is a local variable, which I want to access; func.y
# defines a method for my example function which will allow me to
# access function's local variable y
func.y = 4
x = func.y + 8
return x
func() # now I'm calling the function
a = func.y # I put its local variable into my new variable
print(a) # and print my new variable
If you want to avoid global, one possible approach is to define a class. Each class instance has its own attributes; there is also a class attribute space where instances can share an attribute between them.
Object-oriented programming can be challenging to get into if you are new to Python, but this might actually be a good time to start playing with it.
class Thing:
shared = "foo"
def __init__(self):
"""
This gets called when you create a new Thing()
"""
self.bar = "baz" # default value for new instances
def get_bar(self):
return self.bar
def set_bar(self, value):
self.bar = value
Now, let's create two instances.
first = Thing()
second = Thing()
The get_bar and set_bar methods are not strictly necessary in simple examples like this one. You can also do
second.bar = "ick"
print(second.bar)
# "ick"
print(first.bar)
# "baz"
(though for more complex scenarios, you probably want to require users to call the setter and getter methods; there are ways to force this - see e.g. What's the pythonic way to use getters and setters?)
If you change a class attribute via one instance, it will not be changed in the other instances, either.
second.shared = "poo"
print(first.shared)
# "foo"
But if you change it in the class itself, it will be changed in all the instances which have not separately overridden the shared value.
Thing.shared = "zoom"
print(first.shared)
# "zoom"
print(second.shared)
# "poo", still
To recap, you create a new Thing instance by calling Thing(); this will run the __init__ method before returning the new instance. Inside the class, the instance is the first argument to every (non-static, non-class) method, and conventionally called self (though you could get away with calling it shirley if you wanted to, as far as the Python interpreter is concerned).
There's a lot more to classes; the main selling point is probably that you can create subclasses which inherit from their parent class but can override some behaviors (common examples often involve real-world concepts like animals or vehicles, but a class can just be anything where you want to create a type and encapsulate its behavior, and perhaps override some methods in derived types).
I'm from a C++ background and have often been using static vars to reduce the number of time variables have to be initialized (especially if the initialization takes very long). So from other posts on StackOverflow, people suggested using static class variables as follows:
class MyClass(object):
StaticList1 = [...] # Very large list
StaticList2 = [...] # Very large list
Now this is fine if there exists at least 1 instance of MyClass throughout the execution of the program and the lists are only created once. However, if at some stage of the execution there is no instance of MyClass, Python seems to remove the static lists (I assume because the reference counter drops to 0).
So my question, is there any easy way without using external modules to initialize StaticList1 and StaticList2 only once (the first time they are used) and never to remove them even if there is no instance of MyClass until the program exists (or you delete the lists manually)?
EDIT:
Maybe I oversimplified this issue. What I'm doing:
class MyClass(object):
StaticList = None
def __init__(self, info):
if self.StaticList == None:
print "Initializing ..."
self.StaticList = []
# Computationally expensive task to add elements to self.StaticList, depending on the value of parameter info
def data(self):
return self.StaticList
I import the module from another script and have a loop like this:
import myclass
for i in range(10000):
m = myclass.MyClass(i)
d = m.data()
# Do something with d.
The initializing of the static list takes about 200 - 300 ms and is executed on every iteration of the loop, so the loop takes extremely long to finish.
While your class does have a static field called StaticList, you are actually initializing and working with an instance field of the same name because of the self qualifier you are using. I think your code will work fine if you use MyClass.StaticList to initialize and access it instead.
In general, by Python's name lookup, you can access a class field via an instance as if it was an instance field (e.g., self.StaticList) on that instance as long as you haven't actually set an instance field of the same name on that instance. From that moment on, the instance field shadows the class field (i.e., self.StaticList will find your new value, while MyClass.StaticList will still refer to your class value).
As an example fresh from the interpreter:
>>> class A(object):
... v=2 # static initialization
...
>>> A.v
2
>>> a=A() # get an instance, and
>>> a.v # get the static value via the instance:
2
>>> a.v = 7 # but now set 'v' on the instance, and ...
>>> a.v # we will get the instance field's value:
7
>>> A.v # the static value is still the old:
2
>>> b=A() # and other instances of the class ...
>>> b.v # will use the same old static value:
2
The instance variable a.v is initially equal to A.v, but by explicitly setting a.v=7, you are "dissociating" them in that instance.
While this means that, in principle, you could make use of a static class field MyClass.Values as well as an instance field xyz.Values of the same name, this is often discouraged for exactly this kind of confusion.
As a separate remark, you could consider annotating the data method as a #staticmethod (and remove the self argument in the move) and call it as MyClass.data() to make the fact clearer that you would be getting back the same list instance on every call.
I just started programming in Python, and there's something OOP-related that I'm not quite clear on. So in Python, you can create and assign value to a new variable without needing to first declare it. So with that, is there any difference between creating and assigning a new variable for self (eg. self.variable = 5) inside a function (eg. __init__()) vs. creating and assigning a new private member variable? It seems to me like there is no difference at all.
class Foo:
__var_A = 5;
def __init__(self):
self.__var_B = 5;
self.printVars()
def printVars(self):
print(self.__var_A)
print(self.__var_B)
foo = Foo()
There is in fact a difference between those two variables:
Since __var_A is defined in class Foo instead of an individual member-function like __init__, you can change it for all instances at once like this:
Foo._Foo__var_A = 2
This will not work for __var_B since you define it individually per instance.
Note though, that changing __var_A on an instance will not change it for everyone else, it will instead put a local override into the object itself:
foo2 = Foo()
foo2._Foo__var_A = 1
Foo._Foo__var_A = 2
(foo2._Foo__var_A, foo._Foo__var_A) # Returns: (1, 2)
It seems to me like there is no difference at all.
That is correct.
But remember that Python does not have 'private' members. That is only a convention.
The difference between protected and public is a matter of convention. And class or member variable prefixed by one _ indicates to a developer "don't use this unless you know what you're doing." Private is a SLIGHTLY different case, however: they require two _ and they cannot be suffixed by more than one _. Here are the docs:
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.
Name mangling is an important part of Python inheritence. It allows classes to protect API calls from accidental manipulation of descendants (see above docs). However, if necessary you can still access them via _<class-name><var name>. Eg:
class Foo:
def __init__(self):
self.__bar = 1
print(Foo()._Foo__bar)
# 1
There is no difference if the variable is declared under class foo: of within the __init__(self). Both methods accomplish the same thing.
However, this is slight a twist if the variable (e.g. self.bar) is declared from a method other than __init__. Using
def bar(self):
self.bar = 'test'
creates a variable within the object that is not part of the default class. You can do this, but it is not good programming practice for python.
There is a difference. Consider following example:
foo = Foo()
foo.__dict__
This will return:
{'_Foo__var_B': 5}
But, following code:
bar = Foo
bar.__dict__
will return
{'_Foo__var_A': 5,
'__doc__': None,
'__init__': <function __main__.__init__>,
'__module__': '__main__',
'printVars': <function __main__.printVars>}
This leads to conclusion that __var_A will be accessible even if Foo is not instantiated, while __var_B will not be.
This question already has answers here:
How do I get a result (output) from a function? How can I use the result later?
(4 answers)
Closed 4 months ago.
I am trying to access a local function variable outside the function in Python.
I can make code like this work with global variables:
bye = ''
def hi():
global bye
bye = 5
sigh = 10
hi()
print(bye)
Next, I tried this code, hoping to access bye outside hi() without using global bye:
def hi():
bye = 5
sigh = 10
return
hi()
x = hi()
print(x.bye)
This gives AttributeError: 'NoneType' object has no attribute 'bye'.
Next, I tried:
def hi():
bye = 5
sigh = 10
return bye
hi()
x = hi()
print(x.bye)
This didn't improve matters; I get AttributeError: 'int' object has no attribute 'bye'.
Is there a way to access a local function variable (bye) outside its function (hi()) without using globals and also without printing out the sigh variable? How can I do it?
You could do something along these lines (which worked in both Python v2.7.17 and v3.8.1 when I tested it/them):
def hi():
# other code...
hi.bye = 42 # Create function attribute.
sigh = 10
hi()
print(hi.bye) # -> 42
Functions are objects in Python and can have arbitrary attributes assigned to them.
If you're going to be doing this kind of thing often, you could implement something more generic by creating a function decorator that adds a this argument to each call to the decorated function.
This additional argument will give functions a way to reference themselves without needing to explicitly embed (hardcode) their name into the rest of the definition and is similar to the instance argument that class methods automatically receive as their first argument which is usually named self — I picked something different to avoid confusion, but like the self argument, it can be named whatever you wish.
Here's an example of that approach:
def add_this_arg(func):
def wrapped(*args, **kwargs):
return func(wrapped, *args, **kwargs)
return wrapped
#add_this_arg
def hi(this, that):
# other code...
this.bye = 2 * that # Create function attribute.
sigh = 10
hi(21)
print(hi.bye) # -> 42
Note
This doesn't work for class methods. Just use the instance argument, named self by convention, that's already passed to methods instead of the method's name. You can reference class-level attributes through type(self). See Function's attributes when in a class.
The problem is you were calling print(x.bye) after you set x as a string. When you run x = hi() it runs hi() and sets the value of x to 5 (the value of bye; it does NOT set the value of x as a reference to the bye variable itself). EX: bye = 5; x = bye; bye = 4; print(x) prints 5, not 4.
Also, you don't have to run hi() twice, just run x = hi(), not hi(); x=hi() (the way you had it it was running hi(), not doing anything with the resulting value of 5, and then rerunning the same hi() and saving the value of 5 to the x variable.
So full code should be
def hi():
bye = 5
sigh = 10
return bye
x = hi()
print(x)
If you wanted to return multiple variables, one option would be to use a list, or dictionary, depending on what you need. For example:
def hi():
return { 'bye': 5, 'sigh': 10 }
x = hi()
print x['bye']
def hi():
bye = 5
return bye
print hi()
You could do something along this lines:
def static_example():
if not hasattr(static_example, "static_var"):
static_example.static_var = 0
static_example.static_var += 1
return static_example.static_var
print static_example()
print static_example()
print static_example()
To be able to access a local function's variable, one might add the name of the function and a dot before the name of the local variable (and then, of course, use this construction for calling the variable both in the function's body and outside of it). This solution works in Python 3.7.4.
For example:
def func(): # define a function
# here y is a local variable, which I want to access; func.y
# defines a method for my example function which will allow me to
# access function's local variable y
func.y = 4
x = func.y + 8
return x
func() # now I'm calling the function
a = func.y # I put its local variable into my new variable
print(a) # and print my new variable
If you want to avoid global, one possible approach is to define a class. Each class instance has its own attributes; there is also a class attribute space where instances can share an attribute between them.
Object-oriented programming can be challenging to get into if you are new to Python, but this might actually be a good time to start playing with it.
class Thing:
shared = "foo"
def __init__(self):
"""
This gets called when you create a new Thing()
"""
self.bar = "baz" # default value for new instances
def get_bar(self):
return self.bar
def set_bar(self, value):
self.bar = value
Now, let's create two instances.
first = Thing()
second = Thing()
The get_bar and set_bar methods are not strictly necessary in simple examples like this one. You can also do
second.bar = "ick"
print(second.bar)
# "ick"
print(first.bar)
# "baz"
(though for more complex scenarios, you probably want to require users to call the setter and getter methods; there are ways to force this - see e.g. What's the pythonic way to use getters and setters?)
If you change a class attribute via one instance, it will not be changed in the other instances, either.
second.shared = "poo"
print(first.shared)
# "foo"
But if you change it in the class itself, it will be changed in all the instances which have not separately overridden the shared value.
Thing.shared = "zoom"
print(first.shared)
# "zoom"
print(second.shared)
# "poo", still
To recap, you create a new Thing instance by calling Thing(); this will run the __init__ method before returning the new instance. Inside the class, the instance is the first argument to every (non-static, non-class) method, and conventionally called self (though you could get away with calling it shirley if you wanted to, as far as the Python interpreter is concerned).
There's a lot more to classes; the main selling point is probably that you can create subclasses which inherit from their parent class but can override some behaviors (common examples often involve real-world concepts like animals or vehicles, but a class can just be anything where you want to create a type and encapsulate its behavior, and perhaps override some methods in derived types).
I'm still fairly new to Python, and my OO experience comes from Java. So I have some code I've written in Python that's acting very unusual to me, given the following code:
class MyClass():
mylist = []
mynum = 0
def __init__(self):
# populate list with some value.
self.mylist.append("Hey!")
# increment mynum.
self.mynum += 1
a = MyClass()
print a.mylist
print a.mynum
b = MyClass()
print b.mylist
print b.mynum
Running this results in the following output:
['Hey!']
1
['Hey!', 'Hey!']
1
Clearly, I would expect the class variables to result in the same exact data, and the same exact output... What I can't seem to find anywhere is what makes a list different than say a string or number, why is the list referencing the same list from the first instantiation in subsequent ones? Clearly I'm probably misunderstanding some kind of scope mechanics or list creation mechanics..
tlayton's answer is part of the story, but it doesn't explain everything.
Add a
print MyClass.mynum
to become even more confused :). It will print '0'. Why? Because the line
self.mynum += 1
creates an instance variable and subsequently increases it. It doesn't increase the class variable.
The story of the mylist is different.
self.mylist.append("Hey!")
will not create a list. It expects a variable with an 'append' function to exist. Since the instance doesn't have such a variable, it ends up referring the one from the class, which does exist, since you initialized it. Just like in Java, an instance can 'implicitly' reference a class variable. A warning like 'Class fields should be referenced by the class, not by an instance' (or something like that; it's been a while since I saw it in Java) would be in order. Add a line
print MyClass.mylist
to verify this answer :).
In short: you are initializing class variables and updating instance variables. Instances can reference class variables, but some 'update' statements will automagically create the instance variables for you.
I believe the difference is that += is an assignment (just the same as = and +), while append changes an object in-place.
mylist = []
mynum = 0
This assigns some class variables, once, at class definition time.
self.mylist.append("Hey!")
This changes the value MyClass.mylist by appending a string.
self.mynum += 1
This is the same as self.mynum = self.mynum + 1, i.e., it assigns self.mynum (instance member). Reading from self.mynum falls through to the class member since at that time there is no instance member by that name.
What you are doing here is not just creating a class variable. In Python, variables defined in the class body result in both a class variable ("MyClass.mylist") and in an instance variable ("a.mylist"). These are separate variables, not just different names for a single variable.
However, when a variable is initialized in this way, the initial value is only evaluated once and passed around to each instance's variables. This means that, in your code, the mylist variable of each instance of MyClass are referring to a single list object.
The difference between a list and a number in this case is that, like in Java, primitive values such as numbers are copied when passed from one variable to another. This results in the behavior you see; even though the variable initialization is only evaluated once, the 0 is copied when it is passed to each instance's variable. As an object, though, the list does no such thing, so your append() calls are all coming from the same list. Try this instead:
class MyClass():
def __init__(self):
self.mylist = ["Hey"]
self.mynum = 1
This will cause the value to be evaluated separately each time an instance is created. Very much unlike Java, you don't need the class-body declarations to accompany this snippet; the assignments in the __init__() serve as all the declaration that is needed.