What is the difference between declaring data attributes inside or outside __init__

Possible duplicate:
Python: difference between class and instance attributes

I'm trying to plunge into OOP in Python, and I'm a little confused when it comes to declaring variables inside a class. Should I declare them inside the __init__ procedure or outside it? Who cares?

The following code works very well:

 # Declaring variables within __init__ class MyClass: def __init__(self): country = "" city = "" def information(self): print "Hi! I'm from %s, (%s)"%(self.city,self.country) me = MyClass() me.country = "Spain" me.city = "Barcelona" me.information() 

But declaring variables outside the __init__ procedure also works:

 # Declaring variables outside of __init__ class MyClass: country = "" city = "" def information(self): print "Hi! I'm from %s, (%s)"%(self.city,self.country) me = MyClass() me.country = "Spain" me.city = "Barcelona" me.information() 
+4
source share
3 answers

In the first example, you define the attributes of an instance. The second is class attributes.

Class attributes are shared between all instances of this class, where this particular instance "belongs" as instance attributes.

Difference by example

To understand the differences, use an example.

We will define a class with instance attributes:

 class MyClassOne: def __init__(self): self.country = "Spain" self.city = "Barcelona" self.things = [] 

And one with class attributes:

 class MyClassTwo: country = "Spain" city = "Barcelona" things = [] 

And a function that displays information about one of these objects:

 def information(obj): print "I'm from {0}, ({1}). I own: {2}".format( obj.city, obj.country, ','.join(obj.things)) 

Create 2 MyClassOne objects and change them to Milan and give Milan โ€œsomethingโ€:

 foo1 = MyClassOne() bar1 = MyClassOne() foo1.city = "Milan" foo1.country = "Italy" foo1.things.append("Something") 

When we call information() on foo1 and bar1 , we get the values โ€‹โ€‹you expect:

 >>> information(foo1) I'm from Milan, (Italy). I own: Something >>> information(bar1) I'm from Barcelona, (Spain). I own: 

However, if we do the same, but using instances of MyClassTwo , you will see that class attributes are shared between instances.

 foo2 = MyClassTwo() bar2 = MyClassTwo() foo2.city = "Milan" foo2.country = "Italy" foo2.things.append("Something") 

And then call information() ...

 >>> information(foo2) I'm from Milan, (Italy). I own: Something >>> information(bar2) I'm from Barcelona, (Spain). I own: Something 

So, as you can see, things shared between instances. things - a link to a list to which each instance has access. Therefore, if you add to things from any instance, the same list will be displayed by all other instances.

The reason you don't see this behavior in string variables is because you are actually assigning a new variable to the instance. In this case, this reference "belongs" to the instance and is not used at the class level. To illustrate, assign a new list of things to bar2 :

 bar2.things = [] 

This leads to:

 >>> information(foo2) I'm from Milan, (Italy). I own: Something >>> information(bar2) I'm from Barcelona, (Spain). I own: 
+6
source

You are two versions of the code, very different. In python, you have two different objects: classes and class instances. An instance is what is created when you do:

 new_instance = my_class() 

You can bind attributes to an instance inside __init__ through self ( self is a new instance).

 class MyClass(object): def __init__(self): self.country = "" #every instance will have a `country` attribute initialized to "" 

There is nothing special about self and __init__ . self is a common name that is used to represent the instance that is passed to each method (default).

 a.method() #-> Inside the class where `method` is defined, `a` gets passed in as `self` 

The only thing that is especially important is that __init__ is called when the class is built:

 a = MyClass() #implicitly calls `__init__` 

You can also bind attributes to a class (by putting it outside __init__ ):

 class MyClass(object): country = "" #This attribute is a class attribute. 

At any time, you can associate a new attribute with an instance simply:

 my_instance = MyClass() my_instance.attribute = something 

Or a new class attribute via:

 MyClass.attribute = something 

Now it is getting interesting. If the instance does not have the requested attribute, then python looks at the class for the attribute and returns it (if any). Thus, class attributes are a way for all instances of a class to share a piece of data.

Consider:

 def MyClass(object): cls_attr = [] def __init__(self): self.inst_attr = [] a = MyClass() a.inst_attr.append('a added this') a.cls_attr.append('a added this to class') b = MyClass() print (b.inst_attr) # [] <- empty list, changes to `a` don't affect this. print (b.cls_attr) # ['a added this to class'] <- Stuff added by `a`! print (a.inst_attr) #['a added this'] 
+4
source

When you define a variable in the scope of a class (outside of any method), it becomes an attribute of the class. When you define a value in a method scope, it becomes a local variable of the method. If you assign a value to the self attribute (or any other label that refers to an object), it becomes (or changes) the instance attribute.

0
source

All Articles