Problems with wrapper classes
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 20.6k
- Fork
- 3.3k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
Let's say I have a Person class with a bunch of attributes; it comes from a library I don't control but for which type information exists. Now I have a PersonWrapper class which provides for defaults so that accessing missing attributes never raises an exception (think, use of instances in f-strings).
class PersonWrapper:
def __init__(self, person: Person, default: Any = '') -> None:
self.person = person
self.default = default
def __getattr__(self, attribute: str) -> Any:
return getattr(self.person, attribute, self.default)
In general, any place I want to use a Person I might also want to use a PersonWrapper, so I have variables that can be assigned either a Person or a PersonWrapper. mypy seems not to be able to handle this, and I don't really know of any way to tell the type checker that it should treat Person and PersonWrapper as equivalent. For example, if I have this code:
def print_person(original_person: Person) -> None:
person = PersonWrapper(original_person)
# This attribute might be missing from the original person object.
print(f' Username: {person.username}')
person = original_person
# Only print this if the attribute exists.
phone = getattr(person, 'phoneNumber', None)
if phone:
print(f' Phone: {phone}')
mypy complains about the assignment of original_person to person:
error: Incompatible types in assignment (expression has type "Person", variable has type "PersonWrapper")
Because Person has some dynamic attribute access as well, I can't change the original assignment to:
person: Person = cast(Person, PersonWrapper(original_person))
because then I get errors such as:
error: "Person" has no attribute "office"
The way I fix this is by changing the second assignment to use cast():
person = cast(PersonWrapper, original_person)
This feels wrong, but maybe it's okay. What I think i'd like to do is to create an equivalence between PersonWrapper and Person, but then I'd probably still have to handle the dynamic parts of Person in some way. FWIW I didn't have much luck using Union[Person, PersonWrapper] either.
Is there a better way to handle wrapper classes?
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con l’esempio riportato di Person/PersonWrapper e con l’interazione tra inferenza dell’assegnazione, Union[Person, PersonWrapper], cast() e getattr dinamico; non è indicato alcun file sorgente o test di mypy. Definisci il comportamento di tipizzazione desiderato e aggiungi un test di regressione mirato una volta identificata la posizione dell’implementazione.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- devtools
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Da chiarire
- Idoneità per principianti
- 25/100