In the earlier articles, we introduced variables as a basic component of a class but we didn't go much deeper into it. In this article, we will dive deeper into different types of variables in a class and how they can be used for different purposes.
Variables let us store particular values in programs. In a class, some common usage of variables is to initiate an empty variable to be used by the methods, declare a name, or default value.
A Python class can have two types of variables: Instance, and Class Variables.
Setting Up¶
We will continue our discussion using a slightly modified version of the class - NumList
that we created in the last article.
class NumListA:
def __init__(self, name = ""):
self.instName = name
self.__list = []
def add_value(self, val):
self.__list.append(val)
def remove_value(self):
rv = self.__list[-1]
del self.__list[-1]
return rv
def get_list(self):
return self.__list
nlA1 = NumListA(name = "Number List A1")
nlA1.add_value(2)
# printing the nl instance name
print("Instance name of nlA1 = ", nlA1.instName)
# creating an instance variable on the fly
nlA1.outOfClassVar = 'Instance Variable'
Instance name of nlA1 = Number List A1
Instance Variable¶
These are the variables that are closely tied to the object or the class instances, not a class.
For example, if you have a toy car and we consider that as a Toy
class type then instance variables will be the ones that are attached to your toy car, not with any other toy cars of Toy
class.
Declaring Instance Variable¶
An instance variable can be declared either inside the Class or after the class instance is created.
For example,
__list
andinstName
are two instance variables that were declared inside theNumListA
class. Also, note how you can pass a parameter while a class is initialized and be used later e.g.nlA1.insName
= "Number List A1".outOfClassVar
is created on the fly fornlA1
object directly.
Instance Variable are Isolated¶
Instance variables are instance specific and thus are isolated from other instances even though they all may of the same class type. Check how the instance variable instName
produce different results while called from two instances created (nl
and nl2
) with two different name parameters.
nlA2 = NumListA(name = "Number List A2")
print('Name of nlA1 instance = ', nlA1.instName)
print('Name of nlA2 instance = ', nlA2.instName)
Name of nlA1 instance = Number List A1 Name of nlA2 instance = Number List A2
Class Variables¶
Class variables are declared inside a class and they stick to the class. Meaning, unlike instance variables even if no objects are created class variables will still exist and their values are updated at the class level, not at the instance level.
Declaration and Calling Class Variables¶
Class variables are declared inside a class but outside any methods. Look at the example below where the class variable counter
is created in NumListB
.
Class variables are called following the same convention as instance variables are: <instance name
><.
><class variable name
>.
class NumListB:
counter = 0
__hidden_code = 999
def __init__(self, name = ""):
self.instName = name
self.__list = []
NumListB.counter += 1
def add_value(self, val):
self.__list.append(val)
def remove_value(self):
rv = self.__list[-1]
del self.__list[-1]
return rv
def get_list(self):
return self.__list
Class Variables are Sticky!¶
Instance variables are confined only within their instances while class variables are sticky. They carry over and update across all the objects created from the class.
In NumListB
we have added NumListB.counter += 1
in the __init__
method which basically tells Python to increment the class variable counter
by 1 every time the NumListB
is instantiated.
🛑 Notice below how calling counter
from nlB1
and nlB2
produced the same value.
nlB1 = NumListB(name = "Number List B1")
nlB2 = NumListB(name = "Number List B2")
# printing out class variable
print("Number of NumList class instance created = ", nlB1.counter)
print("Number of NumList class instance created = ", nlB2.counter)
Number of NumList class instance created = 2 Number of NumList class instance created = 2
Checking Existence of Properties¶
Once you have a bunch of classes and objects created it's quite unlikely that you would know which properities or variables that they contain. Or think about when you have to use classes created by other people. In such cases, to check which properties are contained in a class or object we can use two functionalities: __dict__
and hasattr
.
Listing all the Properties¶
__dict__
is a built-in functionality that comes automatically with an object or class whenever they are created. See below how we can call it to get all the properties of an object.
# printing out the instance variables
print('Instance variables of %s are: \n' %(nlB1.instName), nlB1.__dict__)
Instance variables of Number List B1 are: {'instName': 'Number List B1', '_NumListB__list': []}
🛑 Notice, the output from nlB1.__dict__
doesn't show the class variable - counter
.
Calling
__dict__
from an instance doesn't show the class variables since they are not the property of an instance.
But we can use __dict__
from the class to see the class properties. It will print out a bunch of other stuff some of which we will come back to later but for now, check the output from the below code and look for the two class variables: counter
and __hidden_code
.
# printing out the class variables
print('Properties of NumListB class:\n', NumListB.__dict__)
Properties of NumListB class: {'__module__': '__main__', 'counter': 2, '_NumListB__hidden_code': 999, '__init__': <function NumListB.__init__ at 0x0000019447733490>, 'add_value': <function NumListB.add_value at 0x0000019447733520>, 'remove_value': <function NumListB.remove_value at 0x0000019447733010>, 'get_list': <function NumListB.get_list at 0x0000019447253C70>, '__dict__': <attribute '__dict__' of 'NumListB' objects>, '__weakref__': <attribute '__weakref__' of 'NumListB' objects>, '__doc__': None}
Name Mangling¶
🛑 Have you noticed how the names of the private variables are printed out by __dict__
variable?
Since these private variables aren't supposed to be available to the outside of an object, Python mangles the operation of making them available by,
- Putting the class name before the variable names and
- Prefixing an additional underscore (
_
) at the beginning.
Thus, in the outputs you should see instance variable __list
printed out as _NumListA__list
and class variable __hidden_code
printed out as _NumListB__hidden_code
.
These mangled names can be used to directly access these private variables. Which shows how the private characteristics of the Python classes are limited.
# printing out private instance variable using mangled name
print('Private instance variable __list from instace: nlA1 =', nlA1._NumListA__list)
# printing out privatge class variable using mangled name
print('Private class variable from class NumListB = ', NumListB._NumListB__hidden_code)
Private instance variable __list from instace: nlA1 = [2] Private class variable from class NumListB = 999
Checking for Specific Property¶
Using __dict__
is probably a good solution for exploration. But what if you need to check if a certain attribute or property exists in a class or in an object?
Python function
hasattr()
can be used to check for a specific property.
hasattr()
take two arguments: the object being checked, and the name of the property to search as a string value. If the property exists it returns True
otherwise False
.
# n1B1 instance properties
print(hasattr(nlB1, '__list'))
print(hasattr(nlB1, 'counter')) # class variable
# NumListB class properties
print(hasattr(NumListB, 'counter'))
print(hasattr(NumListB, '__hidden_code'))
# checking mangled names for the private attributes
print(hasattr(nlB1, '_NumListB__list'))
print(hasattr(NumListB, '_NumListB__hidden_code'))
False True True False True True
Note:
🛑 Unlike __dict__
, hasattr()
can check for class variables from the objects and return True
.
🛑 Private properties are searchable using their mangled names otherwise they will return False
.
What's Next¶
In this article, we have gone detailed into the different types of variables and their properties in the Python class context. We have learned,
- What instance and class variables ar.
- How to check for the properties from objects and classes.
- How to access public and private variables.
In the next article, we will dig deeper into the methods of a class.