- Iterate over object attributes in python
- Python iter object attributes
- # Table of Contents
- # Iterate over an Object’s attributes in Python
- # Iterate over an Object’s attributes using vars()
- # Iterate over an Object’s attributes using dir()
- # Exclude the attributes that start with two underscores when iterating
- # Exclude the methods when iterating over the object
- # Iterating only over the class’s variables
- # Additional Resources
Iterate over object attributes in python
in general put a __iter__ method in your class and iterate through the object attributes or put this mixin class in your class.
class IterMixin(object): def __iter__(self): for attr, value in self.__dict__.iteritems(): yield attr, value
>>> class YourClass(IterMixin): pass . >>> yc = YourClass() >>> yc.one = range(15) >>> yc.two = 'test' >>> dict(yc)
Assuming you have a class such as
>>> class Cls(object): . foo = 1 . bar = 'hello' . def func(self): . return 'call me' . >>> obj = Cls()
calling dir on the object gives you back all the attributes of that object, including python special attributes. Although some object attributes are callable, such as methods.
>>> dir(obj) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo', 'func']
You can always filter out the special methods by using a list comprehension.
>>> [a for a in dir(obj) if not a.startswith('__')] ['bar', 'foo', 'func']
or if you prefer map/filters.
>>> filter(lambda a: not a.startswith('__'), dir(obj)) ['bar', 'foo', 'func']
If you want to filter out the methods, you can use the builtin callable as a check.
>>> [a for a in dir(obj) if not a.startswith('__') and not callable(getattr(obj, a))] ['bar', 'foo']
You could also inspect the difference between your class and its instance object using.
>>> set(dir(Cls)) - set(dir(object)) set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__'])
As mentioned in some of the answers/comments already, Python objects already store a dictionary of their attributes (methods aren’t included). This can be accessed as __dict__ , but the better way is to use vars (the output is the same, though). Note that modifying this dictionary will modify the attributes on the instance! This can be useful, but also means you should be careful with how you use this dictionary. Here’s a quick example:
class A(): def __init__(self, x=3, y=2, z=5): self.x = x self._y = y self.__z__ = z def f(self): pass a = A() print(vars(a)) # # all of the attributes of `a` but no methods! # note how the dictionary is always up-to-date a.x = 10 print(vars(a)) # # modifying the dictionary modifies the instance attribute vars(a)["_y"] = 20 print(vars(a)) #
Using dir(a) is an odd, if not outright bad, approach to this problem. It’s good if you really needed to iterate over all attributes and methods of the class (including the special methods like __init__ ). However, this doesn’t seem to be what you want, and even the accepted answer goes about this poorly by applying some brittle filtering to try to remove methods and leave just the attributes; you can see how this would fail for the class A defined above.
(using __dict__ has been done in a couple of answers, but they all define unnecessary methods instead of using it directly. Only a comment suggests to use vars ).
Python iter object attributes
Last updated: Feb 22, 2023
Reading time · 4 min
# Table of Contents
# Iterate over an Object’s attributes in Python
To iterate over an object’s attributes:
- Use the __dict__ attribute to get a dictionary containing the object’s properties and values.
- Use the dict.items() method to get a view of the dictionary’s items.
- Use a for loop to iterate over the object’s attributes.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) for attribute, value in emp1.__dict__.items(): # name bobbyhadz # salary 100 print(attribute, value)
The example uses the __dict__ attribute to get a dictionary containing the object’s properties and values.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) # 👇️ print(emp1.__dict__)
We can use the dict.items() method to get a view object we can iterate over.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) for attribute, value in emp1.__dict__.items(): # name bobbyhadz # salary 100 print(attribute, value)
The dict.items method returns a new view of the dictionary’s items ((key, value) pairs).
The last step is to use a for loop to iterate over the object’s attributes.
# Iterate over an Object’s attributes using vars()
An alternative to using the __dict__ attribute is to use the built-in vars() function.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) for attribute, value in vars(emp1).items(): # name bobbyhadz # salary 100 print(attribute, value)
The vars function takes an object and returns the __dict__ attribute of the given module, class, instance or any other object that has a __dict__ attribute.
The vars() function raises a TypeError if the provided object doesn’t have a __dict__ attribute.
If you need to include the class variables when iterating, use the dir() function.
# Iterate over an Object’s attributes using dir()
This is a three-step process:
- Use the dir() function to get a list of the names of the object’s attributes.
- Optionally filter out attributes that start with two underscores and methods.
- Use a for loop to iterate over the object’s attributes.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) for attribute in dir(emp1): print(attribute, getattr(emp1, attribute)) result = [attribute for attribute in dir(emp1) if not attribute.startswith('__')] print(result) # 👉️ ['cls_id', 'name', 'salary']
The dir function returns a list of the names of the object’s attributes, and recursively of the attribute of its base classes.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) # ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'cls_id', 'name', 'salary'] print(dir(emp1))
You can also pass a class to the dir() function, it doesn’t just accept instances.
# Exclude the attributes that start with two underscores when iterating
If you need to exclude the attributes that start with two underscores, use a list comprehension.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary emp1 = Employee('bobbyhadz', 100) attributes = [attribute for attribute in dir(emp1) if not attribute.startswith('__')] print(attributes) # 👉️ ['cls_id', 'name', 'salary'] for attr in attributes: # cls_id employee # name bobbyhadz # salary 100 print(attr, getattr(emp1, attr))
You can use the getattr() function if you need to get the value of an attribute when given the attributes name as a string.
The getattr function returns the value of the provided attribute of the object.
The function takes the following parameters:
Name | Description |
---|---|
object | the object whose attribute should be retrieved |
name | the name of the attribute |
default | a default value for when the attribute doesn’t exist on the object |
# Exclude the methods when iterating over the object
If your class has methods, you might also want to exclude the methods when iterating over the object’s attributes.
Copied!class Employee(): cls_id = 'employee' def __init__(self, name, salary): self.name = name self.salary = salary def get_name(self): return self.name emp1 = Employee('bobbyhadz', 100) attributes = [attribute for attribute in dir(emp1) if not attribute.startswith('__') and not callable(getattr(emp1, attribute))] print(attributes) # 👉️ ['cls_id', 'name', 'salary'] for attr in attributes: # cls_id employee # name bobbyhadz # salary 100 print(attr, getattr(emp1, attr))
The callable function takes an object as an argument and returns True if the object appears callable, otherwise False is returned.
We used the function to exclude all methods from the attributes.
# Iterating only over the class’s variables
If you only want to iterate over the class’s variables, you would pass the class to the dir() function, not the instance.
Copied!class Employee(): cls_id = 'employee' another = 'foo' def __init__(self, name, salary): self.name = name self.salary = salary class_variables = [attribute for attribute in dir(Employee) if not attribute.startswith('__') and not callable(getattr(Employee, attribute)) ] print(class_variables) # 👉️ ['another', 'cls_id'] for attr in class_variables: # another foo # cls_id employee print(attr, getattr(Employee, attr))
We passed the class to the dir() function and filtered out all class variables that start with two underscores and all class methods before iterating.
# Additional Resources
You can learn more about the related topics by checking out the following tutorials:
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.