Настройка доступа к атрибутам

Объектно-ориентированное программирование на Python: средний уровень

Jake Roach

Data Engineer

AttributeError

class Student:
  def __init__(self, student_name, major):
    self.student_name = student_name
    self.major = major
...
karina = Student("Karina", "Literature")
student.residence_hall  # Attempt to access an attribute that does not exist
...
AttributeError: 'Student' object has no attribute 'residence_hall'
Объектно-ориентированное программирование на Python: средний уровень

__getattr__()

# Rest of the class definition above

  def __getattr__(self, name):
    # Implement logic here
    ...

Пространство имён объекта — это совокупность атрибутов, связанных с данным объектом

__getattr__() вызывается при обращении к любому атрибуту, которого нет в пространстве имён объекта

  • Магический метод, не вызывается напрямую
  • Принимает параметр name
  • Реализует пользовательскую логику вместо вызова AttributeError
Объектно-ориентированное программирование на Python: средний уровень

Устранение AttributeError

class Student:
  def __init__(self, student_name, major):
    self.student_name = student_name
    self.major = major

  def __getattr__(self, name):
      print(f"""{name} does not exist in this object's namespace, try setting 
            a value for {name} first""")
karina.residence_hall  # Now, try to retrieve the residence_hall attribute again
residence_hall does not exist in this object's namespace, try setting a value for 
  residence_hall first
Объектно-ориентированное программирование на Python: средний уровень

__setattr__()

__setattr__() — магический метод, который вызывается при установке или обновлении атрибута (нового или существующего)

  • Включает атрибуты, заданные через __init__()
  • Принимает name атрибута и value
  • Использует атрибут __dict__ объекта

$$

$$

Управление изменениями атрибутов, валидация, преобразование

# Rest of the class definition above

  def __setattr__(self, name, value):
    # Implement logic here
    ...

    # Use __dict__ to create/update 
    # the attribute
    self.__dict__[name] = value

__dict__ хранит все атрибуты объекта и позволяет получать и записывать данные

Объектно-ориентированное программирование на Python: средний уровень

Настройка хранения атрибутов

class Student:
  def __init__(self, student_name, major):
    self.student_name = student_name
    self.major = major

  def __setattr__(self, name, value):
    # If value is a string, set the attribute using the __dict__ attribute
    if isinstance(value, str):
      print(f"Setting {name} = {value}")
      self.__dict__[name] = value

    else: # Otherwise, raise an exception noting an incorrect data type
        raise Exception("Unexpected data type!")
Объектно-ориентированное программирование на Python: средний уровень

__setattr__ в действии

# Set an attribute using a value of type 'str'
karina.residence_hall = "Honors College South"
print(karina.residence_hall)
Setting residence_hall = Honors College South
Honors College South
# Set an attribute using a value of type 'int'
karina.student_id = 19301872
...
    raise Exception("Unexpected data type!")
Exception: Unexpected data type!
Объектно-ориентированное программирование на Python: средний уровень

Совместное использование __getattr__ и __setattr__

class Student:
    ...   

    def __getattr__(self, name):
        # Set the attribute with a placeholder
        self.__setattr__(name, None)
        return None

    def __setattr__(self, name, value):
        if value is None:  # Print a message denoting a placeholder
            print(f"Setting placeholder for {name}")

        self.__dict__[name] = value  # Set the attribute
Объектно-ориентированное программирование на Python: средний уровень

Давайте потренируемся!

Объектно-ориентированное программирование на Python: средний уровень

Preparing Video For Download...