hasattr(some_var, "username")
Mais même cela est indésirable, par exemple, il y a des raisons pour lesquelles cette expression pourrait revenir faux, même si une enveloppe utilise un peu de magie avec __getattribute__
pour attribuer correctement l'attribut.
Il est généralement préférable de ne permettre aux variables de prendre qu'un seul type abstrait, et éventuellement None
. Différents comportements basés sur différentes entrées doivent être atteints en transmettant les données éventuellement typées dans différentes variables.Vous voulez faire quelque chose comme ceci:
def dosomething(some_user=None, some_otherthing=None):
if some_user is not None:
#do the "User" type action
elif some_otherthing is not None:
#etc...
else:
raise ValueError("not enough arguments")
Bien sûr, tout cela suppose que vous avez un certain niveau de contrôle du code qui fait la vérification de type. Supposons que ce ne soit pas. pour que "isinstance()" renvoie true, la classe doit apparaître dans les bases de l'instance ou la classe doit avoir un __instancecheck__
. Puisque vous ne contrôlez aucune de ces choses pour la classe, vous devez recourir à des manigances sur l'instance. Faites quelque chose comme ceci:
def wrap_user(instance):
class wrapped_user(type(instance)):
__metaclass__ = type
def __new__(cls):
pass
def __init__(self):
pass
def __getattribute__(self, attr):
self_dict = object.__getattribute__(type(self), '__dict__')
if attr in self_dict:
return self_dict[attr]
return getattr(instance, attr)
def extra_feature(self, foo):
return instance.username + foo # or whatever
return wrapped_user()
Ce que nous faisons est la création d'une nouvelle classe dynamique au moment où nous devons envelopper l'instance, et d'hériter en fait de l'objet de __class__
enveloppé. Nous allons aussi au problème supplémentaire de surcharger le __metaclass__
, au cas où l'original aurait des comportements supplémentaires que nous ne voulons pas rencontrer (comme chercher une table de base de données avec un certain nom de classe). Une bonne commodité de ce style est que nous ne devons jamais créer d'attributs d'instance sur la classe wrapper, il n'y a pas self.wrapped_object
, puisque cette valeur est présente à heure de création de la classe.
Edit: Comme indiqué dans les commentaires, ce qui précède ne fonctionne que pour certains types simples, si vous avez besoin de proxy attributs plus élaborés sur l'objet cible, (par exemple, les méthodes), puis voir la réponse suivante: Python - Faking Type Continued
héritage multiple? – JBernardo
'isinstance (some_var.user, Utilisateur)'? Qu'essayez-vous de faire? –
J'essaie juste d'avoir un wrapper transparent, qui se comporte exactement comme la classe enveloppée. Y compris avec isinstance. L'héritage multiple n'est pas la solution, au moins parce que l'utilisateur est l'une des nombreuses classes que DocumentWrapper encapsule. (Je n'ai pas le contrôle sur ces classes, je ne suis pas capable de changer leur arbre d'héritage.) – Pierre