Python getattr

Summary: in this tutorial, you’ll learn how to use the Python getattr() function to get a named attribute of an object.

Introduction to Python getattr() function

The getattr() function allows you to get the value of the named attribute of an object. Here’s the syntax of the getattr() function:

getattr(object, name[, default])Code language: Python (python)

The getattr() function accepts three parameters:

  • object is the object from which you want to get the value of a named attribute.
  • name is a string that specifies the attribute name of the object.
  • default: if the named attribute doesn’t exist in the object, the getattr() function returns the default. If you omit the default and the named attribute doesn’t exist, the function will raise an AttributeError exception.

Python getattr() function example

The following example illustrates how to use the getattr() to get the attribute values of an object:

class Member:
    def __init__(self, name, email):
        self.name = name
        self.email = email


member = Member('John Doe', '[email protected]')
name = getattr(member, 'name')
print(name)  # 👉 John Doe

email = getattr(member, 'email')
print(name)  # 👉 [email protected]

age = getattr(member, 'age')
print(age)  # 🛑 AttributeErrorCode language: Python (python)

How it works.

First, define a class Member with two attributes, name and age:

class Member:
    def __init__(self, name, email):
        self.name = name
        self.email = emailCode language: Python (python)

Second, create a new instance of the Member class:

member = Member('John Doe', '[email protected]')Code language: Python (python)

Third, use the getattr() function to get the values of the name and email attribute:

name = getattr(member, 'name')
print(name)  # 👉 John Doe

email = getattr(member, 'email')
print(name)  # 👉 [email protected]Code language: Python (python)

It is the same as accessing the attributes directly:

print(member.name)  # 👉 John Doe
print(member.email)  # 👉 [email protected]Code language: Python (python)

Finally, attempt to access the non-existing attribute age. It’ll raise an AttributeError exception.

age = getattr(member, 'age')
print(age)  # 🛑 AttributeErrorCode language: Python (python)

To avoid the exception, you can pass None as the default value like this:

age = getattr(member, 'age', None)Code language: Python (python)

In this case, the age is None.

A practical example of the Python getattr() function

In practice, you’ll use the getattr() function to call the method of an object dynamically. Note that a method is also an attribute of an object.

Suppose, you need to validate the name and email with the following rules:

  • name is required i.e., its length is greater than zero.
  • email is a valid email address

To do that, you can create a reusable Validation class and use it as follows:

validation = Validation()
data = {'name': '', 'email': 'test'}
rules = {'name': 'required', 'email': 'email'}
errors = validation.validate(data, rules)
print(errors)Code language: Python (python)

In this code, the data and rules are dictionaries.

  • Each item in the data dictionary has a field name and value.
  • Each item in the rules dictionary has the field name and rule, which can be either required or email.

The code should return the following output:

{
 'name': 'The name is required', 
 'email': 'The email is not a valid email address'
}Code language: Python (python)

Let’s develop the Validation class.

First, define a Validation class:

class Validation:
    passCode language: Python (python)

Second, declare the error messages (ERRORS) for the required and email rules:

class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }Code language: Python (python)

Third, define the required() method that returns True if the length of a value is greater than zero and email() method that returns True if a value is a valid email address:

import re

class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }

    def required(self, value):
        return len(value) > 0

    def email(self, value):
        pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
        return re.fullmatch(pattern, value)Code language: Python (python)

To validate an email address, the email() method uses the fullmatch() function from the regular expression (re) module.

Finally, define the validate() method:

class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }

    def required(self, value):
        return len(value) > 0

    def email(self, value):
        pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
        return re.fullmatch(pattern, value)

    def validate(self, data, rules):
        errors = {}
        for field, rule in rules.items():
            is_valid_method = getattr(self, rule)
            if not is_valid_method(data[field]):
                errors[field] = self.ERRORS[rule].format(field)

        return errorsCode language: Python (python)

In the validate() method:

  1. Initialize an errors dictionary to store error messages.
  2. Iterate the rules from the rules dictionary.
  3. For each rule, use the getattr() function to find the method that is corresponding to the rule. For example, the getattr() returns the required method for the required rule and email method for the email rule.
  4. Call the method dynamically to validate data. If the method returns False, add the error message to the errors dictionary.
  5. Return the errors.

Put it all together.


import re


class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }

    def required(self, value):
        return len(value) > 0

    def email(self, value):
        pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
        return re.fullmatch(pattern, value)

    def validate(self, data, rules):
        errors = {}
        for field, rule in rules.items():
            is_valid_method = getattr(self, rule)
            if not is_valid_method(data[field]):
                errors[field] = self.ERRORS[rule].format(field)

        return errors


validation = Validation()
data = {'name': '', 'email': 'test'}
rules = {'name': 'required', 'email': 'email'}
errors = validation.validate(data, rules)
print(errors)Code language: Python (python)

Output:


import re


class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }

    def required(self, value):
        return len(value) > 0

    def email(self, value):
        pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
        return re.fullmatch(pattern, value)

    def validate(self, data, rules):
        errors = {}
        for field, rule in rules.items():
            is_valid_method = getattr(self, rule)
            if not is_valid_method(data[field]):
                errors[field] = self.ERRORS[rule].format(field)

        return errors


if __name__ == '__main__':
    validation = Validation()
    data = {'name': '', 'email': 'test'}
    rules = {'name': 'required', 'email': 'email'}
    errors = validation.validate(data, rules)
    print(errors)Code language: Python (python)

Output:

{
 'name': 'The name is required', 
 'email': 'The email is not a valid email address'
}Code language: Python (python)

If you pass the valid data, the errors will be empty:

# Validation class
if __name__ == '__main__':
    validation = Validation()
    data = {'name': 'John', 'email': '[email protected]'}
    rules = {'name': 'required', 'email': 'email'}
    errors = validation.validate(data, rules)
    print(errors)Code language: Python (python)

Note that this code should contain the Validation class to execute successfully

Output:

{}Code language: Python (python)

Note that you can hide the required() and email() method by making them private. In this case, you also need to pass the rule prefixed with an underscore (_) to the getattr() function get the corresponding method:


import re

class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }

    def _required(self, value):
        return len(value) > 0

    def _email(self, value):
        pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
        return re.fullmatch(pattern, value)

    def validate(self, data, rules):
        errors = {}
        for field, rule in rules.items():
            is_valid_method = getattr(self, f'_{rule}')
            if not is_valid_method(data[field]):
                errors[field] = self.ERRORS[rule].format(field)

        return errors

Notice the following line of code:

is_valid_method = getattr(self, f'_{rule}')Code language: PHP (php)

Summary

  • Use Python getattr() function to get a value of a named attribute of an object.
Did you find this tutorial helpful ?