Функция getattr() в Python с примерами

Функция Python getattr() применяется для получения именованного атрибута объекта.

Содержание

Что такое функция getattr() в Python?

Функция getattr() позволяет получить значение именованного атрибута объекта. Вот синтаксис функции getattr():

getattr(object, name[, default])

Функция getattr() принимает три параметра:

  • object — это объект, из которого вы хотите получить значение именованного атрибута.
  • name — это строка, которая определяет имя атрибута объекта.
  • default: если именованный атрибут не существует в объекте, функция getattr() возвращает значение по умолчанию. Если вы опустите значение по умолчанию и именованный атрибут не существует, функция вызовет исключение AttributeError.

Пример функции Python getattr()

Следующий пример иллюстрирует, как использовать getattr() для получения значений атрибутов объекта:

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)  # 🛑 AttributeError

Как это работает.

  • Сначала определите класс Member с двумя атрибутами: name и age:
class Member:
    def __init__(self, name, email):
        self.name = name
        self.email = email
  • Во-вторых, создайте новый экземпляр класса Member:
member = Member('John Doe', '[email protected]')
  • В-третьих, используйте функцию getattr(), чтобы получить значения атрибутов name и email:
name = getattr(member, 'name')
print(name)  # 👉 John Doe

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

Это то же самое, что и прямой доступ к атрибутам:

print(member.name)  # 👉 John Doe
print(member.email)  # 👉 [email protected]

Наконец, попытайтесь получить доступ к несуществующему атрибуту age. Это вызовет исключение AttributeError.

age = getattr(member, 'age')
print(age)  # 🛑 AttributeError

Чтобы избежать исключения, вы можете передать None в качестве значения по умолчанию следующим образом:

age = getattr(member, 'age', None)

В данном случае возраст равен None.

Практический пример функции Python getattr()

На практике вы будете использовать функцию getattr() для динамического вызова метода объекта. Обратите внимание, что метод также является атрибутом объекта.

Предположим, вам необходимо проверить имя и адрес электронной почты с помощью следующих правил:

  • name обязательно, т.е. его длина больше нуля.
  • email — действительный адрес электронной почты

Для этого можно создать повторно используемый класс проверки и использовать его следующим образом:

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

В этом коде данные и правила представляют собой словари.

  • Каждый элемент в словаре данных имеет имя поля и значение.
  • Каждый элемент в словаре правил имеет имя поля и правило, которое может быть обязательным или адресом электронной почты.

Код должен вернуть следующий результат:

{
 'name': 'The name is required', 
 'email': 'The email is not a valid email address'
}

Давайте разработаем класс проверки.

  • Сначала определите класс проверки:
class Validation:
    pass
  • Во-вторых, объявите сообщения об ошибках(ERRORS) для обязательных правил и правил электронной почты:
class Validation:
    ERRORS = {
        'required': 'The {} is required',
        'email': 'The {} is not a valid email address'
    }
  •  В-третьих, определите метод required(), который возвращает True, если длина значения больше нуля, и метод email(), который возвращает True, если значение является допустимым адресом электронной почты:
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)

Для проверки адреса электронной почты метод email() использует функцию fullmatch() из модуля регулярных выражений(re).

Наконец, определите метод validate():

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

В методе validate():

  1. Инициализируйте словарь ошибок для хранения сообщений об ошибках.
  2. Повторите правила из словаря правил.
  3. Для каждого правила используйте функцию getattr(), чтобы найти метод, соответствующий правилу. Например, getattr() возвращает требуемый метод для требуемого правила и метод email для правила email.
  4. Вызовите метод динамически для проверки данных. Если метод возвращает False, добавьте сообщение об ошибке в словарь ошибок.
  5. Верните ошибки.

Соберите все вместе.

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)

Выход:

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)

Выход:

{
 'name': 'The name is required', 
 'email': 'The email is not a valid email address'
}

Если вы передадите действительные данные, ошибки будут пустыми:

# 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)

Для успешного выполнения этот код должен содержать класс Validation.

Выход:

{}

Вы можете скрыть методы required() и email(), сделав их приватными. В этом случае вам также нужно передать правило с префиксом подчеркивания(_) в функцию getattr(), чтобы получить соответствующий метод:

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

Обратите внимание на следующую строку кода:

is_valid_method = getattr(self, f'_{rule}')

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *