difference between variables inside and outside of __init__()
Solution 1:
Variable set outside __init__
belong to the class. They're shared by all instances.
Variables created inside __init__
(and all other method functions) and prefaced with self.
belong to the object instance.
Solution 2:
Without Self
Create some objects:
class foo(object):
x = 'original class'
c1, c2 = foo(), foo()
I can change the c1 instance, and it will not affect the c2 instance:
c1.x = 'changed instance'
c2.x
>>> 'original class'
But if I change the foo class, all instances of that class will be changed as well:
foo.x = 'changed class'
c2.x
>>> 'changed class'
Please note how Python scoping works here:
c1.x
>>> 'changed instance'
With Self
Changing the class does not affect the instances:
class foo(object):
def __init__(self):
self.x = 'original self'
c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
Solution 3:
I would like to add something to the responses that I read in this thread and this thread (which references this one).
Disclaimer: this remarks come from the experiments I ran
Variables outside __init__
:
These are, in fact, static class variables and are, therefore, accesible to all instances of the class.
Variables inside __init__
:
The value of these instance variables are only accesible to the instance at hand (through the self
reference)
My contribution:
One thing that programmers must consider when using static class variables is that they can be shadowed by instance variables (if you are accessing the static class variables through the self
reference).
Explanation:
Previously, I thought that both ways of declaring the variables were exactly the same (silly me), and that was partly because I could access both kind of variables through the self
reference. It was now, when I ran into trouble, that I researched the topic and cleared it up.
The problem with accessing static class variables through the
self
reference is that it only references the static class variable if there is no instance variable with the same name, and to make things worse, trying to redefine a static class variable through the self
reference does not work because an instance variable is created which then shadows the previously-accesible static class variable.
To get around this problem, you should always reference static class variables through the name of the class.
Example:
#!/usr/bin/env python
class Foo:
static_var = 'every instance has access'
def __init__(self,name):
self.instance_var = 'I am %s' % name
def printAll(self):
print 'self.instance_var = %s' % self.instance_var
print 'self.static_var = %s' % self.static_var
print 'Foo.static_var = %s' % Foo.static_var
f1 = Foo('f1')
f1.printAll()
f1.static_var = 'Shadowing static_var'
f1.printAll()
f2 = Foo('f2')
f2.printAll()
Foo.static_var = 'modified class'
f1.printAll()
f2.printAll()
Output:
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
I hope this is helpful to someone
Solution 4:
further to S.Lott's reply, class variables get passed to metaclass new method and can be accessed through the dictionary when a metaclass is defined. So, class variables can be accessed even before classes are created and instantiated.
for example:
class meta(type):
def __new__(cls,name,bases,dicto):
# two chars missing in original of next line ...
if dicto['class_var'] == 'A':
print 'There'
class proxyclass(object):
class_var = 'A'
__metaclass__ = meta
...
...
Solution 5:
class User(object):
email = 'none'
firstname = 'none'
lastname = 'none'
def __init__(self, email=None, firstname=None, lastname=None):
self.email = email
self.firstname = firstname
self.lastname = lastname
@classmethod
def print_var(cls, obj):
print ("obj.email obj.firstname obj.lastname")
print(obj.email, obj.firstname, obj.lastname)
print("cls.email cls.firstname cls.lastname")
print(cls.email, cls.firstname, cls.lastname)
u1 = User(email='abc@xyz', firstname='first', lastname='last')
User.print_var(u1)
In the above code, the User class has 3 global variables, each with value 'none'. u1 is the object created by instantiating this class. The method print_var prints the value of class variables of class User and object variables of object u1. In the output shown below, each of the class variables User.email
, User.firstname
and User.lastname
has value 'none'
, while the object variables u1.email
, u1.firstname
and u1.lastname
have values 'abc@xyz'
, 'first'
and 'last'
.
obj.email obj.firstname obj.lastname
('abc@xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')