J'essaie de me prouver que je peux redéfinir la syntaxe du langage Python. Fondamentalement, l'une des facettes de la métaprogrammation. Mais j'ai du mal à écraser le comportement de la classe object
intégrée.Python: Puis-je remplacer le __getattr__ dans un objet (intégré)?
J'essaye de changer le comportement où un AttributeError
est levé quand un objet n'a aucun attribut spécifique. Au lieu de cela, j'essaye de forcer Python à se comporter comme JavaScript, en retournant None dans le cas. C'est un exercice pour essayer de mieux comprendre les built-ins de Python, pas vraiment un problème pratique.
Une fois que je l'ai modifié, je ne peux plus créer d'objets. Voici ma tentative de modifier le comportement de object
:
#!/usr/bin/env python
class object(type):
def __new__(self, *args, **kwargs):
print(args)
return super(object, self).__new__(object, *args, **kwargs)
def __init__(self, *args, **kwargs):
self._dict = {}
super(object, self).__init__(*args, **kwargs)
def __getattribute__(self, key):
print('GET -> LONG METHOD')
if key.startswith('_'):
raise TypeError('Cannot modify built-ins')
return self._dict.get(key)
def __getattr__(self, key):
print('GET -> SHORT METHOD')
if key.startswith('_'):
raise TypeError('Cannot modify built-ins')
return self._dict.get(key)
def __setattr__(self, key, value):
if key.startswith('_'):
raise TypeError('Cannot set directly on built-ins')
self._dict[key] = value
class A(object):
pass
a = A()
a.yay = 7
print(a.yay)
print(a.yup) # should be None
Je ne sais pas exactement quelle est la méthode __getattribute__
mais quand je visitai object
je l'ai trouvé avait cette méthode au lieu de __getattr__
, donc je l'ai écrasé à la fois (Au cas où).
Le problème avec le code est que pendant la instatiation de a = A()
choses exploser:
Traceback (most recent call last):
File "py.py", line 34, in <module>
a = A()
File "py.py", line 12, in __new__
return super(object, self).__new__(self, *args, **kwargs)
TypeError: type.__new__() takes exactly 3 arguments (0 given)
Le message d'erreur me semble erroné de. Je passe définitivement au moins 1 argument à __new__
dans:
return super(object, self).__new__(object, *args, **kwargs)
Au départ, je ne passait pas cet argument du tout, étant donné que la classe doit être transmis à l'intérieur *args
de toute façon. J'ai ajouté l'instruction print à la méthode __new__
et j'ai constaté que rien ne lui était transmis.
Est-il vraiment impossible de changer le comportement des built-ins en Python? Ou je le fais juste mal?
Même si vous réussissez, vous ne modifierez que les nouvelles classes qui héritent de votre «objet» fictif, et vous causerez des problèmes en observant l'original. Essayez de lui donner un nom différent. De plus, rien de tout cela ne change la syntaxe *. – jonrsharpe