Editor’s note: This article was updated on 11/29/22 by our editorial team. It has been modified to include recent sources and to align with our current editorial standards.
I recently had a programming interview phone screen in which we used a collaborative text editor and it got me thinking about Python class attributes.
I was asked to implement a certain API and chose to do so in Python. Abstracting away the problem statement, let’s say I needed a class whose instances stored some data
and some other_data
.
I took a deep breath and started typing. After a few lines, I had something like this:
class Service(object): data = [] def __init__(self, other_data): self.other_data = other_data ...
My interviewer stopped me:
-
Interviewer: “That line
data = []
. I don’t think that’s valid Python.” -
Me: “I’m pretty sure it is. It’s just setting a default value for the instance attribute.”
-
Interviewer: “When does that code get executed?”
-
Me: “I’m not really sure. I’ll just fix it up to avoid confusion.”
For reference, and to give you an idea of what I was going for, here’s how I amended the code:
class Service(object): def __init__(self, other_data): self.data = [] self.other_data = other_data ...
As it turns out, we were both wrong. The real answer lay in understanding the distinction between Python class attributes and Python instance attributes.
Note: If you have an expert handle on Python class attributes, you can skip ahead to use cases.
Python Class Attributes
My interviewer was wrong in that the above code is syntactically valid.
I was wrong in that the code isn’t setting a “default value” for the instance attribute. Instead, it’s defining data
as a class attribute with value []
.
In my experience, Python class attributes are a topic that many people know something about, but few understand completely.
Python Class Variables vs. Instance Variables: What’s the Difference?
A Python class attribute is an attribute of the class (circular, I know), rather than an attribute of an instance of a class.
Let’s use a Python class example to illustrate the difference. Here, class_var
is a class attribute, and i_var
is an instance attribute:
{:lang='python'} class MyClass(object): class_var = 1 def __init__(self, i_var): self.i_var = i_var
Note that all instances of the class have access to class_var
, and that it can also be accessed as a property of the class itself:
{:lang='python'} foo = MyClass(2) bar = MyClass(3) foo.class_var, foo.i_var ## 1, 2 bar.class_var, bar.i_var ## 1, 3 MyClass.class_var ## <— This is key ## 1
For Java or C++ programmers, the class attribute is similar—but not identical—to the static member. We’ll see how they differ later.
Python Class Properties vs. Instance Namespaces
To understand what’s happening here, let’s talk briefly about Python namespaces.
A namespace is a mapping from names to objects, with the property that there is zero relation between names in different namespaces. They’re usually implemented as Python dictionaries, although this is abstracted away.
Depending on the context, you may need to access a namespace using dot syntax (e.g., object.name_from_objects_namespace
) or as a local variable (e.g., object_from_namespace
). As a concrete example:
{:lang='python'} class MyClass(object): ## No need for dot syntax class_var = 1 def __init__(self, i_var): self.i_var = i_var ## Need dot syntax as we’ve left scope of class namespace MyClass.class_var ## 1
Python classes and instances of classes each have their own distinct namespaces represented by the pre-defined attributes MyClass.__dict__
and instance_of_MyClass.__dict__
, respectively.
When you try to access Python attributes from an instance of a class, it first looks at its instance namespace. If it finds the attribute, it returns the associated value. If not, it then looks in the class namespace and returns the attribute (if it’s present, otherwise throwing an error). For example:
{:lang='python'} foo = MyClass(2) ## Finds i_var in foo’s instance namespace foo.i_var ## 2 ## Doesn’t find class_var in instance namespace… ## So looks in class namespace (MyClass.__dict__) foo.class_var ## 1
The instance namespace takes precedence over the class namespace: If there is a Python attribute with the same name in both, the instance namespace will be checked first and its value returned. Here’s a simplified version of the code for attribute lookup:
{:lang='python'} def instlookup(inst, name): ## simplified algorithm if inst.__dict__.has_key(name): return inst.__dict__[name] else: return inst.__class__.__dict__[name]
And, in visual form:
How Python Class Attributes Handle Assignment
With this in mind, we can make sense of how class attributes handle assignment:
-
If a class attribute is set by accessing the class, it will override the value for all instances. For example:
{:lang='python'} foo = MyClass(2) foo.class_var ## 1 MyClass.class_var = 2 foo.class_var ## 2
At the namespace level we’re setting MyClass.__dict__['class_var'] = 2
. (Note: This isn’t the exact code which would be setattr(MyClass, 'class_var', 2)
as __dict__
returns a dictproxy, an immutable wrapper that prevents direct assignment, but it helps for demonstration’s sake). Then, when we access foo.class_var
, class_var
has a new value in the class namespace and thus 2 is returned.
-
If a Python class variable is set by accessing an instance, it will override the value only for that instance. This essentially overrides the class variable and turns it into an instance variable available intuitively only for that instance. For example:
foo = MyClass(2)foo.class_var## 1foo.class_var = 2foo.class_var## 2MyClass.class_var## 1
At the namespace level we’re adding the class_var
attribute to foo.__dict__
, so when we look up foo.class_var
, we return 2. Meanwhile, other instances of MyClass
will not have class_var
in their instance namespaces, so they continue to find class_var
in MyClass.__dict__
and thus return 1.
Mutability
What if your class attribute has a mutable type? You can manipulate the class attribute by accessing it through a particular instance and, in turn, end up manipulating the referenced object that all instances are accessing (as pointed out by Timothy Wiseman).
Let’s go back to the Service
I defined earlier and see how my use of a class variable could have led to problems down the road:
{:lang='python'} class Service(object): data = [] def __init__(self, other_data): self.other_data = other_data ...
My goal was to have the empty list ([]
) as the default value for data
, and for each instance of Service
to have its own data that would be altered over time on an instance-by-instance basis. But in this case, we got the following behavior (note that other_data
is arbitrary in this example):
{:lang='python'} s1 = Service(['a', 'b']) s2 = Service(['c', 'd']) s1.data.append(1) s1.data ## [1] s2.data ## [1] s2.data.append(2) s1.data ## [1, 2] s2.data ## [1, 2]
This is no good—altering our Python class variable via one instance alters it for all the others!
At the namespace level all instances of Service
are accessing and modifying the same list in Service.__dict__
without making their own data
attributes in their instance namespaces.
We could get around this using assignment; that is, instead of exploiting the list’s mutability, we could assign our Service
objects to have their own lists, as follows:
{:lang='python'} s1 = Service(['a', 'b']) s2 = Service(['c', 'd']) s1.data = [1] s2.data = [2] s1.data ## [1] s2.data ## [2]
In this case, we’re adding s1.__dict__['data'] = [1]
, so the original Service.__dict__['data']
remains unchanged.
Unfortunately, this requires that Service
users have intimate knowledge of its variables, and this workaround is certainly prone to mistakes. In a sense, we’d be addressing the symptoms rather than the cause. It’s preferable to have something that is correct by construction.
My personal solution: If you’re just using a class variable to assign a default value to a would-be Python instance variable, don’t use mutable values. In this case, every instance of Service
was going to override Service.data
with its own instance attribute eventually, so using an empty list as the default led to a tiny bug that was easily overlooked. Instead of the above, we could have either:
-
Stuck to instance attributes entirely, as demonstrated in the introduction.
-
Avoided using the empty list (a mutable value) as our “default.”
For example:
class Service(object): data = None def __init__(self, other_data): self.other_data = other_data ...
Of course, we’d have to handle the None
case appropriately, but that’s a small price to pay.
When Should You Use Python Class Attributes?
Class attributes are tricky, but let’s look at a few cases where they would come in handy:
-
Storing constants. As class attributes can be accessed as attributes of the class itself, it’s often nice to use them for storing class-wide, class-specific constants. For example:
class Circle(object): pi = 3.14159 def __init__(self, radius): self.radius = radius def area(self): return Circle.pi * self.radius * self.radius Circle.pi ## 3.14159 c = Circle(10) c.pi ## 3.14159 c.area() ## 314.159
-
Defining default values. As a small example, we might create a bounded list (i.e., a list that can only hold a certain number of elements or fewer) and choose to have a default cap of 10 items:
class MyClass(object): limit = 10 def __init__(self): self.data = [] def item(self, i): return self.data[i] def add(self, e): if len(self.data) >= self.limit: raise Exception("Too many elements") self.data.append(e) MyClass.limit ## 10
We could then create instances with their own specific limits too, by assigning them to the instance’s
limit
attribute.foo = MyClass() foo.limit = 50 ## foo can now hold 50 elements—other instances can hold 10
This only makes sense if you will want your typical instance of
MyClass
to hold just 10 elements or fewer—if you’re giving all of your instances different limits, thenlimit
should be an instance variable. (Remember to be careful when using mutable values as your defaults.) -
Tracking all data across all instances of a given class. This is sort of specific, but I could see a scenario in which you might want to access a piece of data related to every existing instance of a given class.
(Video) Classes and Objects with Python - Part 1 (Python Tutorial #9)To make the scenario more concrete, let’s say we have a
Person
class, and every person has aname
. We want to keep track of all the names that have been used. One approach might be to iterate over the garbage collector’s list of objects, but it’s simpler to use class variables.Note that, in this case,
names
will only be accessed as a class variable, so the mutable value default is acceptable.class Person(object): all_names = [] def __init__(self, name): self.name = name Person.all_names.append(name) joe = Person('Joe') bob = Person('Bob') print Person.all_names ## ['Joe', 'Bob']
We could even use this design pattern to track all existing instances of a given class, rather than just some associated data.
class Person(object): all_people = [] def __init__(self, name): self.name = name Person.all_people.append(self) joe = Person('Joe') bob = Person('Bob') print Person.all_people ## [<__main__.Person object at 0x10e428c50>, <__main__.Person object at 0x10e428c90>]
-
Considering Performance
Related: Python Best Practices and Tips by Toptal Developers
Under the Hood
Note: If you’re worrying about performance at this level, you might not want to be use Python in the first place, as the differences will be on the order of tenths of a millisecond—but it’s still fun to poke around a bit and it helps for illustration’s sake.
Recall that a class’s namespace is created and filled in at the time of the class’s definition. That means that we do just one assignment for a given class variable, while instance variables must be assigned every time a new instance is created.
Let’s take an example:
{:lang='python'} def called_class(): print "Class assignment" return 2 class bar(object): y = called_class() def __init__(self, x): self.x = x ## "Class assignment" def called_instance(): print "Instance assignment" return 2 class foo(object): def __init__(self, x): self.y = called_instance() self.x = x bar(1) bar(2) foo(1) ## "Instance assignment" foo(2) ## "Instance assignment"
We assign to Bar.y
just once, but instance_of_Foo.y
on every call to __init__
.
As further evidence, let’s use the Python disassembler:
{:lang='python'} import dis class bar(object): y = 2 def __init__(self, x): self.x = x class foo(object): def __init__(self, x): self.y = 2 self.x = x dis.dis(Bar) ## Disassembly of __init__: ## 7 0 LOAD_FAST 1 (x) ## 3 LOAD_FAST 0 (self) ## 6 STORE_ATTR 0 (x) ## 9 LOAD_CONST 0 (None) ## 12 RETURN_VALUE dis.dis(Foo) ## Disassembly of __init__: ## 11 0 LOAD_CONST 1 (2) ## 3 LOAD_FAST 0 (self) ## 6 STORE_ATTR 0 (y) ## 12 9 LOAD_FAST 1 (x) ## 12 LOAD_FAST 0 (self) ## 15 STORE_ATTR 1 (x) ## 18 LOAD_CONST 0 (None) ## 21 RETURN_VALUE
When we look at the byte code, it’s again obvious that Foo.__init__
has to do two assignments, while Bar.__init__
does just one.
In practice, what does this gain really look like? I’ll be the first to admit that timing tests are highly dependent on often uncontrollable factors and the differences between them are often hard to explain accurately.
However, I think these small snippets (run with the Python timeit module) help to illustrate the differences between class and instance variables, so I’ve included them anyway.
Note: I’m on a MacBook Pro with OS X 10.8.5 and Python 2.7.2.
Initialization
10000000 calls to `Bar(2)`: 4.940s10000000 calls to `Foo(2)`: 6.043s
The initializations of Bar
are faster by over a second, so the difference here does appear to be statistically significant.
So why is this the case? One speculative explanation: We do two assignments in Foo.__init__
, but just one in Bar.__init__
.
Assignment
10000000 calls to `Bar(2).y = 15`: 6.232s10000000 calls to `Foo(2).y = 15`: 6.855s10000000 `Bar` assignments: 6.232s - 4.940s = 1.292s10000000 `Foo` assignments: 6.855s - 6.043s = 0.812s
Note: There’s no way to re-run your setup code on each trial with timeit, so we have to reinitialize our variable on our trial. The second line of times represents the above times with the previously calculated initialization times deducted.
From the above, it looks like Foo
only takes about 60% as long as Bar
to handle assignments.
Why is this the case? One speculative explanation: When we assign to Bar(2).y
, we first look in the instance namespace (Bar(2).__dict__[y]
), fail to find y
, and then look in the class namespace (Bar.__dict__[y]
), then make the proper assignment. When we assign to Foo(2).y
, we do half as many lookups, as we immediately assign to the instance namespace (Foo(2).__dict__[y]
).
In summary, though these performance gains won’t matter in reality, these tests are interesting at the conceptual level. If anything, I hope these differences help illustrate the mechanical distinctions between class and instance variables.
In Conclusion
Class attributes seem to be underused in Python; a lot of programmers have different impressions of how they work and why they might be helpful.
My take: Python class variables have their place within the school of good code. When used with care, they can simplify things and improve readability. But when carelessly thrown into a given class, they’re sure to trip you up.
Appendix: Private Instance Variables
One additional variable to mention: private instance variables.
Python doesn’t have private variables so to speak, but another interesting relationship between class and instance naming comes with name mangling.
In the Python style guide, it’s said that pseudo-private variables should be prefixed with a double underscore: ‘__’. This is not only a sign to others that your variable is meant to be treated privately, but also a way to prevent access to it, of sorts. Here’s what I mean:
class Bar(object): def __init__(self): self.__zap = 1a = Bar()a.__zap## Traceback (most recent call last):## File "<stdin>", line 1, in <module>## AttributeError: 'Bar' object has no attribute '__baz'## Hmm. So what’s in the namespace?a.__dict__{'_Bar__zap': 1}a._Bar__zap## 1
Look at that: The instance attribute __zap
is automatically prefixed with the class name to yield _Bar__zap
.
While still settable and gettable using a._Bar__zap
, this name mangling is a means of creating a “private” variable as it prevents you and others from accessing it by accident or through ignorance.
Edit: As Pedro Werneck kindly pointed out, this behavior is largely intended to help out with subclassing. In the PEP 8 style guide, they see it as serving two purposes: (1) preventing subclasses from accessing certain attributes, and (2) preventing namespace clashes in these subclasses. While useful, variable mangling shouldn’t be seen as an invitation to write code with an assumed public-private distinction, such as is present in Java.
Further Reading on the Toptal Engineering Blog:
- Ensuring Clean Code: A Look at Python, Parameterized
- Python Design Patterns: For Sleek And Fashionable Code
- Top 10 Mistakes That Django Developers Make
- An Introduction to Mocking in Python
- The Six Commandments of Good Code: Write Code That Stands the Test of Time
Understanding the basics
What is a Python namespace?
A Python namespace is a mapping from names to objects, with the property that there is zero relation between names in different namespaces. Namespaces are usually implemented as Python dictionaries, although this is abstracted away.
Python class method versus instance method: What’s the difference?
In Python, a class method is a method that is invoked with the class as the context. This is often called a static method in other programming languages. An instance method, on the other hand, is invoked with an instance as the context.
What happens if both instance attribute and class attribute are defined?
In that case, the instance namespace takes precedence over the class namespace. If there is an attribute with the same name in both, the instance namespace will be checked first and its value returned.
Tags
- Python
- Java
FAQs
What are the attributes of a class in Python? ›
A class attribute is a Python variable that belongs to a class rather than a particular object. It's shared between all the objects of this class and is defined outside the constructor function, __init__(self,...) , of the class.
What is the difference between class attributes and instance attributes in Python? ›Differences Between Class and Instance Attributes
The difference is that class attributes are shared by all instances. When you change the value of a class attribute, it will affect all instances that share the same exact value. The attribute of an instance on the other hand is unique to that instance.
Using built-in dir() Function
To get the list of all the attributes, methods along with some inherited magic methods of a class, we use a built-in called dir().
Adding attributes to a Python class is very straight forward, you just use the '. ' operator after an instance of the class with whatever arbitrary name you want the attribute to be called, followed by its value.
What is the purpose of class attributes? ›The class attribute specifies one or more classnames for an element. The class attribute is mostly used to point to a class in a style sheet. However, it can also be used by a JavaScript (via the HTML DOM) to make changes to HTML elements with a specified class.
What is true about the class attributes? ›Class attributes are attributes which are owned by the class itself. They will be shared by all the instances of the class. Therefore they have the same value for every instance. We define class attributes outside all the methods, usually they are placed at the top, right below the class header.
Can you have multiple class attributes? ›HTML elements can be assigned multiple classes by listing the classes in the class attribute, with a blank space to separate them. If the same property is declared in both rules, the conflict is resolved first through specificity, then according to the order of the CSS declarations.
What is the difference between class attributes and intense attributes? ›Class attributes are the variables defined directly in the class that are shared by all objects of the class. Instance attributes are attributes or properties attached to an instance of a class. Instance attributes are defined in the constructor. Defined directly inside a class.
Can a class attribute be used without an instance of that class? ›while you can access class attributes using an instance it's not safe to do so. In python, the instance of a class is referred to by the keyword self. Using this keyword you can access not only all instance attributes but also the class attributes.
How do you print all attributes of a class object in Python? ›To print all the attributes of an object in Python, you can use the 'getmembers()' function of the inspect module. This function returns the list of tuples containing the attributes along with their values.
How do I access class attributes? ›
- getattr() – This function is used to access the attribute of object.
- hasattr() – This function is used to check if an attribute exist or not.
- setattr() – This function is used to set an attribute.
Element.getAttribute()
The getAttribute() method of the Element interface returns the value of a specified attribute on the element. If the given attribute does not exist, the value returned will either be null or "" (the empty string); see Non-existing attributes for details.
Python does not have a 'static' keyword to declare the static variable. In Python, you simply declare a variable inside the class, note that it should not be inside any method, and that variable will be known as a static or class variable.
Are class attributes inherited? ›Objects are defined by classes, classes can inherit attributes and behavior from pre-existing classes. The resulting classes are known as derived classes or subclasses. A subclass “inherits” all the attributes (methods, etc) of the parent class.
Are Python class attributes private? ›Python doesn't have public OR private attributes. All attributes are accessible to all code. Your method isn't in any way making _attr private, it's just a bit of obfuscation.
What is the advantage of working with the class attribute? ›Advantages of class attributes: All instances of the class inherit them from the class. They store data that is relevant to all the instances. For example, we could have a counter class attribute that increments every time we create a new instance and decrements every time we delete an instance.
Why should class attributes be private? ›A private attribute provides you a level of protection from the users of your class, for that attribute. If you use a public attribute, you will need to add in more logic to test for invalid values up front, which can be more work, as well as more computationally expensive.
What are dynamic attributes of a class? ›Dynamic attributes represent changing characteristics of the resource. Dynamic attributes of a host resource, for example, would identify such things as the average number of processes that are waiting in the run queue, processor idle time, and the number of users who are currently logged on.
What is is the true about the class attributes in Python? ›Question 3: What is TRUE about the class attributes? They are defined in the __init__() method. They can be defined inside any method. They are accessible by the name of the class.
Can you have a class without attributes? ›You can use class without any attributes if you don't need any.
Which of the following statement is true about class attributes in Python? ›
The correct answer is E.
Class attributes represent the state of the object created at any particular time.
ID selectors have a higher specificity than attribute selectors. You should always try to use IDs to increase the specificity. A class selector beats any number of element selectors.
Can a class attribute be an object? ›A class attribute is a variable that belongs to a certain class, and not a particular object.
Is it OK to create multiple objects from a class? ›A program may create many objects of the same class. Objects are also called instances, and they can be stored in either a named variable or in an array or collection. Client code is the code that uses these variables to call the methods and access the public properties of the object.
What is class attributes vs instance? ›Classes contain characteristics called Attributes. We make a distinction between instance attributes and class attributes. Instance Attributes are unique to each object, (an instance is another name for an object). Here, any Dog object we create will be able to store its name and age.
Are class attributes static? ›A class attribute/method is static in Java and C++, no difference, except that in Python the first parameter to a class method call is the class.
Can a class attribute be used without an instance of that class in Python? ›We can also make class methods that can be called without having an instance. The method is then similar to a plain Python function, except that it is contained inside a class and the method name must be prefixed by the classname.
Are class attributes private by default? ›By default, the classes visibility is package private, i.e. only visible for classes in the same package. The class has no visibility defined like in Java. They are visible if you included them to the compilation unit.
What is the difference between class methods and class attributes? ›A class is a kind of data type, just like a string, integer or list. When we create an object of that data type, we call it an instance of a class. The data values which we store inside an object are called attributes, and the functions which are associated with the object are called methods.
Can class attribute have space? ›A class name can't have spaces. When you have a space-separated string in your class attribute, you're always giving your element several classes.
How do you get all variables in a class? ›
Field[] fields = YourClassName. class. getFields(); returns an array of all public variables of the class.
How do I get all the attributes of an object in Active Directory? ›Go to Start and open Administrative tools. Click on Active Directory users and Computers. Right click on the object whose attributes you wish to view, and click Properties. In the dialogue box that opens, you will be able to view all the AD attributes of the object categorized based on the attribute type.
What is the difference between attribute and property in Python? ›Attributes are defined by data variables like name, age, height etc. Properties are special type of attributes. Property method comes with the getter, setter and delete methods like __get__, __set__, and __delete__ methods. Class attributes are defined in the class body not in the functions.
What is the difference between attributes and methods in Python? ›A variable stored in an instance or class is called an attribute. A function stored in an instance or class is called a method.
How do you get a specific attribute of an object in Python? ›Python getattr() function is used to get the value of an object's attribute and if no attribute of that object is found, default value is returned. Basically, returning the default value is the main reason why you may need to use Python getattr() function.
What is the difference between getText () and getAttribute ()? ›What's the difference between the two? As the name suggests, the getAttribute method gets the value of a given HTML attribute. On the other hand, getText() returns the inner text of a given element. The term “inner text” means the text located between the opening and closing tags of the element.
How do you select an element with specific attributes? ›The [attribute|="value"] selector is used to select elements with the specified attribute, whose value can be exactly the specified value, or the specified value followed by a hyphen (-). Note: The value has to be a whole word, either alone, like class="top", or followed by a hyphen( - ), like class="top-text".
What are the attributes of a class? ›Class attributes are the variables defined directly in the class that are shared by all objects of the class. Instance attributes are attributes or properties attached to an instance of a class. Instance attributes are defined in the constructor. Defined directly inside a class.
What are classes objects and attributes in Python? ›A class attribute is a variable that belongs to a certain class, and not a particular object. Every instance of this class shares the same variable. These attributes are usually defined outside the __init__ constructor. An instance/object attribute is a variable that belongs to one (and only one) object.
What are the attributes of a class called? ›Data in a class are called attributes and behaviors are called methods.
What are the three attributes in Python? ›
There are three attributes that are most important to an organization when hiring: attitude, competency and mindset. Attitude.
What are the five types of attributes? ›There are six such types of attributes: Simple, Composite, Single-valued, Multi-valued, and Derived attribute.
What is the difference between classes and attributes? ›Classes are extensional, attributes are not. That, briefly stated, is what Quine would have us believe is the sole difference between classes and attributes.
How do you set class attributes? ›- Example. Add a class attribute to an element: element. setAttribute("class", "democlass"); ...
- Change an input field to an input button: myInput. setAttribute("type", "button"); Before: ...
- Add a href attribute to an <a> element: myAnchor. setAttribute("href", "https://www.w3schools.com"); Before:
In summary, class attributes remain the same for every object and are defined outside the __init__() function. Instance attributes are somewhat dynamic because they can have different values in each object. Instance attributes are defined in the __init__() function.
Why should I use classes in Python? ›Classes are great if you need to keep state, because they containerize data (variables) and behavior (methods) that act on that data and should logically be grouped together. This leads to code that is better organized (cleaner) and easier to reuse.
What is the purpose of attributes in objects Python? ›Attributes of a class are function objects that define corresponding methods of its instances. They are used to implement access controls of the classes.
What are the 4 types of attributes? ›- Single valued Attribute. Attributes having a single value for a particular item is called a single valued attribute. ...
- Multi-valued Attribute. Attribute having a set of values for a single entity is called a multi-valued attribute. ...
- Derived Attributes or stored Attributes. ...
- Complex Attribute.