Je comprends que les fonctions peuvent avoir des attributs. Je peux donc faire ce qui suit:Est-il possible de faire en sorte que les fonctions Python se comportent comme des instances?
def myfunc():
myfunc.attribute += 1
print(myfunc.attribute)
myfunc.attribute = 1
Est-il possible par tout moyen de faire une telle fonction se comportent comme si elle était une instance? Par exemple, je voudrais pouvoir faire quelque chose comme ceci:
x = clever_wrapper(myfunc)
y = clever_wrapper(myfunc)
x.attribute = 5
y.attribute = 9
x() # I want this to print 6 (from the 5 plus increment)
y() # I want this to print 10 (from the 9 plus increment)
En l'état actuel, il n'y a qu'une « instance » de la fonction, donc attribute
existe qu'une seule fois. La modification par x
ou y
modifie la même valeur. Je voudrais que chacun d'eux ait son propre attribute
. Est-ce possible de faire du tout? Si oui, pouvez-vous fournir un exemple simple et fonctionnel?
Il est important que je puisse accéder à attribute
depuis l'intérieur de la fonction mais que la valeur de attribute
soit différente selon l'instance de la fonction appelée. Essentiellement, je voudrais utiliser attribute
comme s'il s'agissait d'un autre paramètre de la fonction (afin qu'il puisse changer le comportement de la fonction) mais pas le transmettre. (Supposons que la signature de la fonction a été fixée de sorte que je ne puisse pas changer la liste des paramètres.) Mais je dois être en mesure de définir les différentes valeurs pour attribute
, puis appeler les fonctions dans l'ordre. J'espère que cela à du sens.
Les principales réponses semblent dire de faire quelque chose comme ceci:
class wrapper(object):
def __init__(self, target):
self.target = target
def __call__(self, *args, **kwargs):
return self.target(*args, **kwargs)
def test(a):
return a + test.attribute
x = wrapper(test)
y = wrapper(test)
x.attribute = 2
y.attribute = 3
print(x.attribute)
print(y.attribute)
print(x(3))
print(y(7))
Mais cela ne fonctionne pas. Peut-être que je l'ai fait incorrectement, mais il est dit que test
n'a pas attribute
. (Je suppose que c'est parce que wrapper
a réellement l'attribut.)
La raison pour laquelle j'ai besoin de ceci est parce que j'ai une bibliothèque qui attend une fonction avec une signature particulière. Il est possible de mettre ces fonctions dans un pipeline de sorte qu'elles soient appelées dans l'ordre. J'aimerais passer plusieurs versions de la même fonction, mais changer leur comportement en fonction de la valeur d'un attribut. Je voudrais donc pouvoir ajouter x
et y
au pipeline, plutôt que d'avoir à implémenter une fonction test1
et une fonction test2
qui font presque exactement la même chose (sauf pour la valeur de l'attribut).
Y a-t-il une raison particulière pour laquelle vous voulez une fonction et non une classe? Est-ce seulement à des fins éducatives ou y a-t-il un vrai problème que vous essayez de résoudre? –
Les noms de classe doivent être PascalCase :) –
Essayez ma réponse. Je l'ai testé et cela fonctionne –