Personalizzare l'accesso agli attributi

Programmazione a oggetti intermedia in 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  # Tentativo di accedere a un attributo che non esiste
...
AttributeError: 'Student' object has no attribute 'residence_hall'
Programmazione a oggetti intermedia in Python

__getattr__()

# Rest of the class definition above

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

Lo spazio dei nomi di un oggetto è l'insieme degli attributi associati a quell'oggetto

__getattr__() viene eseguito quando si prova a riferirsi a QUALSIASI attributo fuori dallo spazio dei nomi dell'oggetto**

  • Metodo magico, non si chiama direttamente
  • Accetta il parametro name
  • Implementa funzionalità personalizzate invece di generare un AttributeError
Programmazione a oggetti intermedia in Python

Risolvere l'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  # Ora prova a recuperare di nuovo l'attributo residence_hall
residence_hall does not exist in this object's namespace, try setting a value for 
  residence_hall first
Programmazione a oggetti intermedia in Python

__setattr__()

__setattr__() è un metodo magico eseguito quando un attributo (nuovo o esistente) viene impostato o aggiornato

  • Include gli attributi impostati con __init__()
  • Accetta name dell'attributo e value
  • Usa l'attributo __dict__ dell'oggetto

$$

$$

Controllo delle modifiche agli attributi, validazione, trasformazione

# 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__ memorizza tutti gli attributi dell'oggetto, può essere usato per recuperare e salvare dati

Programmazione a oggetti intermedia in Python

Personalizzare l'archiviazione degli attributi

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!")
Programmazione a oggetti intermedia in Python

__setattr__ in azione

# Imposta un attributo usando un valore di tipo 'str'
karina.residence_hall = "Honors College South"
print(karina.residence_hall)
Setting residence_hall = Honors College South
Honors College South
# Imposta un attributo usando un valore di tipo 'int'
karina.student_id = 19301872
...
    raise Exception("Unexpected data type!")
Exception: Unexpected data type!
Programmazione a oggetti intermedia in Python

Usare __getattr__ e __setattr__ insieme

class Student:
    ...   

    def __getattr__(self, name):
        # Imposta l'attributo con un segnaposto
        self.__setattr__(name, None)
        return None

    def __setattr__(self, name, value):
        if value is None:  # Stampa un messaggio che indica un segnaposto
            print(f"Setting placeholder for {name}")

        self.__dict__[name] = value  # Imposta l'attributo
Programmazione a oggetti intermedia in Python

Esercitiamoci!

Programmazione a oggetti intermedia in Python

Preparing Video For Download...