En python 2.7, je veux créer une variable statique qui stocke le résultat de l'exécution d'une méthode statique de la classe englobante.

J'ai essayé ce qui suit:

class A:
    @staticmethod
    def foo():
            return 1
    v = A.foo() # a static variable
print A.v

Qui renvoie l'erreur:

NameError: name 'A' is not defined

Cependant, se référer à la variable statique d'une autre classe fonctionne:

class B:
    @staticmethod
    def foo():
            return 1
class A:
    @staticmethod
    def foo():
            return 1
    v = B.foo()

print A.v

>>> 1

Des explications?

ÉDITER:

Le cas d'utilisation de ce scénario consiste à mettre en cache le résultat de foo et à le placer sous l'espace de nom de A. Suite aux réponses, je comprends que A n'est pas encore défini au moment de l'exécution, ce qui conduit à une erreur. J'ai trouvé ce qui suit pour retarder le calcul:

class A:
    @staticmethod
    def foo():
            print 'running foo'
            return 1

    @staticmethod
    def get_v():
            try:
                    return A.v
            except AttributeError:
                    A.v = A.foo()
                    return A.v

print A.get_v()
print A.get_v()

>>> running foo
>>> 1
>>> 1

Cela semble faire l'affaire, mais c'est un peu lourd.

0
Gabis 8 mars 2016 à 12:15

3 réponses

Meilleure réponse

Utilisez @classmethod et mettez en cache la valeur sur l'objet classe.

class S(object):
    @classmethod
    def f(klass):
        if not hasattr(klass, '_f'):
            print "Calculating value"
            klass._f = 5

        return klass._f

Lorsqu'il est appelé deux fois à partir d'instances différentes:

>>> s = S()
>>> s2 = S()
>>> s.f()
Calculating value
5
>>> s2.f()
5

La valeur est partagée sur toutes les instances de S.

3
izak 8 mars 2016 à 10:21

Vous ne pouvez pas appeler une méthode (statique) de la classe A tant que la classe n'est pas complètement définie (fin du bloc class). Mais vous pouvez définir une variable statique dès que la classe est définie:

class A:
    @staticmethod
    def foo():
        print "running foo"
        return 1
A.v = A.foo()

Vous pouvez ensuite utiliser n'importe où

print A.v
1
Serge Ballesta 8 mars 2016 à 10:07

En plus de vous demander pourquoi vous faites cela: au moment où vous attribuez v (dans la ligne v = A.foo(), A n'a pas encore été défini. (La définition de A est le bloc entier class, donc A n'est défini qu'après ce bloc.)

Dans votre deuxième exemple, B est déjà défini lorsque vous dites v = B.foo().

EDIT: Ce qui me laisse perplexe est le suivant:

class A:
    @staticmethod
    def foo():
        return 1
    v = foo()

L'exécution de ce code entraîne

    v = foo()
TypeError: 'staticmethod' object is not callable
1
acdr 8 mars 2016 à 09:44