Python attribute definition with lots of attributes - style

I have a class with a number of attributes. Can someone clarify the differences between setting attributes like a, b, c below and x, y, z. I understand that if the arguments for entering them should obviously be in init , however, just to set the numeric variables by default, which is preferable and which ones are for and against.

class Foo(object): a = 'Hello' b = 1 c = False def __init__(self): self.x = 'World' self.y = 2 self.z = True 
+8
python class styles
source share
4 answers

The main con / gotcha using class attributes to provide default values ​​for what you intend to use for specific instances is that the default values ​​will be shared among all instances of the class until the value is changed. For example:.

 class Foo(object): a = [] foo1 = Foo() foo2 = Foo() foo1.a.append(123) foo1.a # [123] foo2.a # [123] 

However, as expected, the following will work:

 class Bar(object): a = 123 bar1 = Bar() bar2 = Bar() bar1.a = 456 bar2.a # 123 

To avoid this error when using this technique, you should only use it to set default values ​​that are immutable. (For example, numbers, strings, tuples ...)

The reason Python behaves this way is because when accessing an attribute with:

 foo.bar 

then bar first scanned in the foo object. If the name is not found in the object (i.e. In foo.__dict__ ), then the name is looked up in the type of this object. For example, this mechanism is part of the work of search methods. (If you look at the __dict__ object, you will notice that its methods are missing there).

Other minor problems are that it provides default values ​​through a type object when they are intended for instance specificity; and that it mixes class-specific attribute definitions (like constants) if you have default values. The consequence of the first is that this will allow you to override the default value later for all objects that have not yet changed the value by assigning a class attribute. (This can be useful or confusing; the same precaution applies to mutable "global" variables.)

+4
source share

Variables a , b and c are class variables. They are evaluated and set once when the class is first created. The variables x , y and z are instance variables that are computed and set whenever an instance of an object of this class is created.

In general, you use class variables if the same values ​​will be used by each instance of the class and should be calculated only once. You use instance variables for variables that will be different for each instance of this class.

You can access class variables through the syntax of the self.a instance self.a , but this object is shared between all instances of the class. This does not affect the use of immutable data types, such as integers or strings, but when using mutable data types such as lists, adding to self.a will cause all instances to see the newly added value.

Some examples from IDLE are probably helpful in understanding this:

 >>> class Foo(object): a = 'Hello' b = [] def __init__(self): self.y = [] >>> instance_1 = Foo() >>> instance_2 = Foo() >>> instance_1.a 'Hello' >>> instance_2.a 'Hello' >>> instance_1.a = 'Goodbye' >>> instance_1.a 'Goodbye' >>> instance_2.a 'Hello' >>> instance_1.b [] >>> instance_2.b.append('12345') >>> instance_1.b ['12345'] >>> instance_2.y [] >>> instance_2.y.append('abcde') >>> instance_2.y ['abcde'] >>> instance_1.y [] 
+7
source share

As you declared them, a, b, and c will be available without instantiating Foo.
For example, you can say:

 Foo.a = "Goodbye" 

In contrast, x, y, and z will not be created until you create an instance of Foo, and they will not match this instance:

 bar = Foo() bar.x = 42 
+2
source share

This has been asked countless times ...

a,b,c are class variables shared between all instances, good use would be a counter to count all the occurrences of this class that were created, x,y,z are instance variables belonging to this single instance, therefore, using self to set them...

Please note that you can actually put out class variables, such as self.a = 3 , this will not change a , but rather overshadow it ... and several people were taken by surprise.

demo:

 >>> class Foo(object): ... a = 3 ... def __init__(self): ... self.x = 6 ... >>> Foo.a 3 >>> b = Foo() >>> ba = 5 >>> ba 5 >>> Foo.a 3 >>> ba 5 >>> Foo.a = 9 >>> Foo.a 9 >>> ba 5 >>> c = Foo() >>> ca 9 
+1
source share

All Articles