Sebbene la delega sia possibile, in effetti non è comune.
-
In molti casi in cui potresti raggiungere la delega, potresti anche utilizzare l'ereditarietà multipla. Ruby non ha ereditarietà multipla, quindi deve utilizzare altri approcci come mixin o delega. Python ha qui una semantica più flessibile.
-
La delega basata su __getattr__
e / o __getattribute__
è complessa e richiede una buona comprensione dei dettagli di basso livello di Python da implementare correttamente. Questo interagisce con il protocollo descrittore e le caratteristiche di introspezione come dir()
o help()
e con altri metodi dunder come __str__
o __add__
: non è possibile delegare implicitamente metodi dunder, ma dovrebbe implementare un metodo che esegue la delega.
-
Questa complessità è percepita come non-Pythonic. "Explicit è meglio di implicito."
-
Invece della delega tramite __getattr__
, puoi semplicemente implementare manualmente i metodi o le proprietà che desideri delegare. Puoi utilizzare metaprogrammazione (tramite metaclassi o decoratori di classi) per semplificare questa operazione oppure utilizzare il protocollo descrittore per creare membri della classe che eseguono la delega quando vi si accede tramite un'istanza.
-
La delega è lenta, specialmente se basata su funzioni di riflessione o metaprogrammazione.
I descrittori sono oggetti che implementano un membro della classe. Vengono richiamati in modi diversi a seconda che si acceda a un membro di classe o istanza. Le funzioni e le proprietà sono implementazioni di descrittori comunemente utilizzate, ma è possibile creare descrittori definiti dall'utente. Tutto ciò che ha un metodo __get__
può essere usato come descrittore. In un progetto ho implementato un descrittore per eseguire la delega, ad es. usato come:
class Foo:
delegated_method = delegate('TargetType', 'delegated_method', to='_target')
def __init__(self, target):
self._target = target
# Foo().delegated_method => Foo()._target.delegated_method
# Foo.delegated_method => returns the descriptor
# help(Foo.delegated_method) # works
Alla fine, la complessità e l'impatto sulle prestazioni dell'uso dei descrittori era troppo importante in quel progetto, e ho semplicemente spiegato esplicitamente la delega.