Les variables statiques de classe sont-elles possibles?

est-il possible d'avoir des variables de classe statiques ou des méthodes en python? Quelle syntaxe est nécessaire pour faire cela?

1550
demandé sur Tyto 2008-09-16 05:46:36

16 réponses

les Variables déclarées dans la définition de classe, mais non dans une méthode sont des variables de classe ou statiques:

>>> class MyClass:
...     i = 3
...
>>> MyClass.i
3 

comme @ millerdev souligne, Cela crée une variable de niveau de classe i , mais cela est distinct de n'importe quelle variable de niveau d'instance i , donc vous pourriez avoir

>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)

c'est différent de C++ et Java, mais pas si différent de C#, où un membre statique ne peut pas être accédé en utilisant une référence à une instance.

Voir ce que le tutoriel Python a à dire sur le sujet de classes et les objets de la classe .

@Steve Johnson a déjà répondu concernant méthodes statiques , également documenté sous "fonctions intégrées" dans la référence de bibliothèque Python .

class C:
    @staticmethod
    def f(arg1, arg2, ...): ...

@beidy recommande classemethod s over staticmethod, comme la méthode reçoit alors le type de classe comme premier argument, mais je suis encore un peu flou sur les avantages de cette approche sur staticmethod. Si tu l'es aussi, ça n'a probablement pas d'importance.

1523
répondu Blair Conrad 2017-06-06 13:00:27

@Blair Conrad dit que les variables statiques déclarées dans la définition de classe, mais pas dans une méthode sont des variables de classe ou "statiques":

>>> class Test(object):
...     i = 3
...
>>> Test.i
3

il y a quelques gotcha ici. Reprenant l'exemple ci-dessus:

>>> t = Test()
>>> t.i     # static variable accessed via instance
3
>>> t.i = 5 # but if we assign to the instance ...
>>> Test.i  # we have not changed the static variable
3
>>> t.i     # we have overwritten Test.i on t by creating a new attribute t.i
5
>>> Test.i = 6 # to change the static variable we do it by assigning to the class
>>> t.i
5
>>> Test.i
6
>>> u = Test()
>>> u.i
6           # changes to t do not affect new instances of Test

# Namespaces are one honking great idea -- let's do more of those!
>>> Test.__dict__
{'i': 6, ...}
>>> t.__dict__
{'i': 5}
>>> u.__dict__
{}

remarquez comment la variable d'instance t.i s'est déconnectée de la variable de classe "statique" lorsque l'attribut i a été placé directement sur t . C'est parce que i était re-liée à l'intérieur de la t espace de noms, ce qui est distincte de la Test espace de noms. Si vous voulez changer la valeur d'une variable "statique", vous devez la changer dans la portée (ou l'objet) où elle a été initialement définie. J'ai mis" static " entre guillemets parce que Python n'a pas vraiment de variables statiques dans le sens où C++ et Java le font.

bien qu'il ne dise rien de spécifique sur les variables statiques ou les méthodes, le tutoriel Python a certaines informations pertinentes sur les classes et les objets de la classe .

@Steve Johnson a également répondu concernant les méthodes statiques, également documentées sous "Fonctions intégrées" dans la référence de la bibliothèque Python.

class Test(object):
    @staticmethod
    def f(arg1, arg2, ...):
        ...

@beid a également mentionné classmethod, qui est similaire à staticmethod. Un classmethod premier argument est l'objet de classe. Exemple:

class Test(object):
    i = 3 # class (or static) variable
    @classmethod
    def g(cls, arg):
        # here we can use 'cls' instead of the class name (Test)
        if arg > cls.i:
            cls.i = arg # would the the same as  Test.i = arg1

Pictorial Representation Of Above Example

533
répondu millerdev 2017-07-28 00:15:27

méthodes statiques et de classe

comme les autres réponses ont noté, les méthodes statiques et de classe sont facilement accomplies en utilisant les décorateurs intégrés:

class Test(object):

    # regular instance method:
    def MyMethod(self):
        pass

    # class method:
    @classmethod
    def MyClassMethod(klass):
        pass

    # static method:
    @staticmethod
    def MyStaticMethod():
        pass

comme d'habitude, le premier argument de MyMethod() est lié à l'objet de l'instance de classe. En revanche, le premier argument de MyClassMethod() est lié à l'objet de classe lui-même (par exemple, dans ce cas, Test ). Pour MyStaticMethod() , aucun les arguments sont liés, et avoir des arguments est facultatif.

"Variables Statiques"

Toutefois, la mise en œuvre de "variables statiques" (ainsi, mutable variables statiques, de toute façon, si ce n'est pas une contradiction dans les termes...) n'est pas aussi simple. Comme millerdev l'a souligné dans sa réponse , le problème est que les attributs de classe de Python ne sont pas vraiment des"variables statiques". Considérons:

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i

c'est parce que la ligne x.i = 12 a ajouté un nouvel attribut d'instance i à x au lieu de changer la valeur de l'attribut Test class i .

partial comportement de la variable statique attendue, i.e., synchronisation de l'attribut entre plusieurs instances (mais pas avec la classe elle-même; voir "gotcha" ci-dessous), peut être réalisé en tournant la classe attribut dans une propriété:

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)

Maintenant vous pouvez faire:

x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i  # no error
assert x2.i == 50    # the property is synced

la variable statique restera désormais synchrone entre toutes les instances de classe .

(NOTE: sauf si une instance de classe décide de définir sa propre version de _i ! Mais si quelqu'un décide de faire ça, il mérite ce qu'il reçoit, non???)

notez que techniquement parlant, i n'est pas une "variable statique" du tout; c'est un property , qui est un type de descripteur. Cependant, le comportement property est maintenant équivalent à une variable statique (mutable) synchronisée dans toutes les instances de classe.

Immuable "Static Variables"

pour un comportement de variable statique immuable, il suffit d'omettre le property setter:

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    i = property(get_i)

tente maintenant de régler l'instance i attribut retournera un AttributeError :

x = Test()
assert x.i == 3  # success
x.i = 12         # ERROR

Une chasse aux sorcières pour être au Courant de

noter que les méthodes ci - dessus ne fonctionnent avec instances de votre classe-ils seront pas travailler en utilisant la classe elle-même . Ainsi par exemple:

x = Test()
assert x.i == Test.i  # ERROR

# x.i and Test.i are two different objects:
type(Test.i)  # class 'property'
type(x.i)     # class 'int'

la ligne assert Test.i == x.i produit une erreur, parce que l'attribut i de Test et x sont deux objets différents.

beaucoup de gens trouveront cela surprenant. Cependant, il ne devrait pas être. Si nous revenons en arrière et inspectons notre définition de classe Test (la deuxième version), nous prenons note de cette ligne:

    i = property(get_i) 

clairement, le membre i de Test doit être un objet property , qui est le type d'objet retourné de la fonction property .

Si vous trouvez ce qui précède confus, vous êtes très probablement encore penser à ce sujet du point de vue d'autres langues (par exemple Java ou c++). Vous devriez aller étudier l'objet property , à propos de l'ordre dans lequel les attributs Python sont retournés, le protocole de descripteur, et l'ordre de résolution de méthode (MRO).

je présente une solution au 'gotcha' ci-dessus ci-dessous; cependant je suggérerais-énergiquement - que vous n'essayez pas de faire quelque chose comme ce qui suit jusqu'à ce que - au minimum - vous comprenez parfaitement pourquoi assert Test.i = x.i cause une erreur.

réel, réel Variables statiques - Test.i == x.i

je présente la solution (Python 3) ci-dessous à titre informatif seulement. Je ne l'approuve pas en tant que "bonne solution". J'ai mes doutes quant à savoir si l'émulation du comportement de la variable statique d'autres langues en Python est vraiment nécessaire. Cependant, indépendamment de savoir si c'est vraiment utile, ce qui suit devrait aider à mieux comprendre le fonctionnement de Python.

mise à JOUR: cette tentative de est vraiment affreux ; si vous insistez sur le fait de faire quelque chose comme ceci (astuce: s'il vous plaît ne pas; Python est un très élégant de la langue et de la chaussure-horning en se comportant comme une autre langue n'est tout simplement pas nécessaire), utilisez le code dans Ethan Furman réponse à la place.

Emulation de la variable statique le comportement d'autres langues à l'aide d'une métaclasse

Une métaclasse est la classe d'une classe. La métaclasse par défaut pour toutes les classes en Python (i.e., les classes "new style" post Python 2.3 I believe) est type . Par exemple:

type(int)  # class 'type'
type(str)  # class 'type'
class Test(): pass
type(Test) # class 'type'

cependant, vous pouvez définir votre propre métaclasse comme ceci:

class MyMeta(type): pass

Et l'appliquer à votre propre classe comme ceci (Python 3):

class MyClass(metaclass = MyMeta):
    pass

type(MyClass)  # class MyMeta

ci-dessous est un metaclass que j'ai créé qui tente d'émuler le comportement" variable statique " d'autres langues. Il fonctionne essentiellement en remplaçant le getter, le setter et le deleter par défaut par des versions qui vérifient si l'attribut demandé est une "variable statique".

un catalogue des" variables statiques "est stocké dans l'attribut StaticVarMeta.statics . Toutes les requêtes d'attribut sont d'abord essayées pour être résolues en utilisant un ordre de résolution de substitution. J'ai surnommé "l'ordre de résolution statique", ou "SRO". Ceci est fait en recherchant l'attribut requis dans l'ensemble des "variables statiques" pour une classe donnée (ou ses classes mères). Si l'attribut n'apparaît pas dans le" SRO", la classe retombera sur l'attribut par défaut get/set/delete behavior (i.e.,"MRO").

from functools import wraps

class StaticVarsMeta(type):
    '''A metaclass for creating classes that emulate the "static variable" behavior
    of other languages. I do not advise actually using this for anything!!!

    Behavior is intended to be similar to classes that use __slots__. However, "normal"
    attributes and __statics___ can coexist (unlike with __slots__). 

    Example usage: 

        class MyBaseClass(metaclass = StaticVarsMeta):
            __statics__ = {'a','b','c'}
            i = 0  # regular attribute
            a = 1  # static var defined (optional)

        class MyParentClass(MyBaseClass):
            __statics__ = {'d','e','f'}
            j = 2              # regular attribute
            d, e, f = 3, 4, 5  # Static vars
            a, b, c = 6, 7, 8  # Static vars (inherited from MyBaseClass, defined/re-defined here)

        class MyChildClass(MyParentClass):
            __statics__ = {'a','b','c'}
            j = 2  # regular attribute (redefines j from MyParentClass)
            d, e, f = 9, 10, 11   # Static vars (inherited from MyParentClass, redefined here)
            a, b, c = 12, 13, 14  # Static vars (overriding previous definition in MyParentClass here)'''
    statics = {}
    def __new__(mcls, name, bases, namespace):
        # Get the class object
        cls = super().__new__(mcls, name, bases, namespace)
        # Establish the "statics resolution order"
        cls.__sro__ = tuple(c for c in cls.__mro__ if isinstance(c,mcls))

        # Replace class getter, setter, and deleter for instance attributes
        cls.__getattribute__ = StaticVarsMeta.__inst_getattribute__(cls, cls.__getattribute__)
        cls.__setattr__ = StaticVarsMeta.__inst_setattr__(cls, cls.__setattr__)
        cls.__delattr__ = StaticVarsMeta.__inst_delattr__(cls, cls.__delattr__)
        # Store the list of static variables for the class object
        # This list is permanent and cannot be changed, similar to __slots__
        try:
            mcls.statics[cls] = getattr(cls,'__statics__')
        except AttributeError:
            mcls.statics[cls] = namespace['__statics__'] = set() # No static vars provided
        # Check and make sure the statics var names are strings
        if any(not isinstance(static,str) for static in mcls.statics[cls]):
            typ = dict(zip((not isinstance(static,str) for static in mcls.statics[cls]), map(type,mcls.statics[cls])))[True].__name__
            raise TypeError('__statics__ items must be strings, not {0}'.format(typ))
        # Move any previously existing, not overridden statics to the static var parent class(es)
        if len(cls.__sro__) > 1:
            for attr,value in namespace.items():
                if attr not in StaticVarsMeta.statics[cls] and attr != ['__statics__']:
                    for c in cls.__sro__[1:]:
                        if attr in StaticVarsMeta.statics[c]:
                            setattr(c,attr,value)
                            delattr(cls,attr)
        return cls
    def __inst_getattribute__(self, orig_getattribute):
        '''Replaces the class __getattribute__'''
        @wraps(orig_getattribute)
        def wrapper(self, attr):
            if StaticVarsMeta.is_static(type(self),attr):
                return StaticVarsMeta.__getstatic__(type(self),attr)
            else:
                return orig_getattribute(self, attr)
        return wrapper
    def __inst_setattr__(self, orig_setattribute):
        '''Replaces the class __setattr__'''
        @wraps(orig_setattribute)
        def wrapper(self, attr, value):
            if StaticVarsMeta.is_static(type(self),attr):
                StaticVarsMeta.__setstatic__(type(self),attr, value)
            else:
                orig_setattribute(self, attr, value)
        return wrapper
    def __inst_delattr__(self, orig_delattribute):
        '''Replaces the class __delattr__'''
        @wraps(orig_delattribute)
        def wrapper(self, attr):
            if StaticVarsMeta.is_static(type(self),attr):
                StaticVarsMeta.__delstatic__(type(self),attr)
            else:
                orig_delattribute(self, attr)
        return wrapper
    def __getstatic__(cls,attr):
        '''Static variable getter'''
        for c in cls.__sro__:
            if attr in StaticVarsMeta.statics[c]:
                try:
                    return getattr(c,attr)
                except AttributeError:
                    pass
        raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
    def __setstatic__(cls,attr,value):
        '''Static variable setter'''
        for c in cls.__sro__:
            if attr in StaticVarsMeta.statics[c]:
                setattr(c,attr,value)
                break
    def __delstatic__(cls,attr):
        '''Static variable deleter'''
        for c in cls.__sro__:
            if attr in StaticVarsMeta.statics[c]:
                try:
                    delattr(c,attr)
                    break
                except AttributeError:
                    pass
        raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
    def __delattr__(cls,attr):
        '''Prevent __sro__ attribute from deletion'''
        if attr == '__sro__':
            raise AttributeError('readonly attribute')
        super().__delattr__(attr)
    def is_static(cls,attr):
        '''Returns True if an attribute is a static variable of any class in the __sro__'''
        if any(attr in StaticVarsMeta.statics[c] for c in cls.__sro__):
            return True
        return False
144
répondu Rick Teachey 2017-12-08 16:12:57

vous pouvez également ajouter des variables de classe aux classes à la volée

>>> class X:
...     pass
... 
>>> X.bar = 0
>>> x = X()
>>> x.bar
0
>>> x.foo
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: X instance has no attribute 'foo'
>>> X.foo = 1
>>> x.foo
1

et les instances de classe peuvent changer les variables de classe

class X:
  l = []
  def __init__(self):
    self.l.append(1)

print X().l
print X().l

>python test.py
[1]
[1, 1]
23
répondu Gregory 2014-08-24 17:43:30

personnellement, j'utiliserais une méthode de classe chaque fois que j'aurais besoin d'une méthode statique. Surtout parce que j'ai le cours comme argument.

class myObj(object):
   def myMethod(cls)
     ...
   myMethod = classmethod(myMethod) 

ou utiliser un décorateur

class myObj(object):
   @classmethod
   def myMethod(cls)

pour les propriétés statiques.. Son temps vous regardez python définition.. variable peut toujours changer. Il y a deux types d'entre eux mutables et immuables.. Il y a aussi des attributs de classe et des attributs d'instance.. Rien de tel que les attributs statiques au sens de java & c++

Pourquoi utiliser la méthode statique au sens pythonique, si elle n'a aucun rapport avec la classe! Si j'étais vous, j'utiliserais classmethod ou définirais la méthode indépendamment de la classe.

13
répondu emb 2008-09-16 23:29:49

méthodes Statiques en python sont appelés classmethod . Regardez le code suivant

class MyClass:

    def myInstanceMethod(self):
        print 'output from an instance method'

    @classmethod
    def myStaticMethod(cls):
        print 'output from a static method'

>>> MyClass.myInstanceMethod()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method myInstanceMethod() must be called [...]

>>> MyClass.myStaticMethod()
output from a static method

notez que lorsque nous appelons la méthode myInstanceMethod , nous obtenons une erreur. C'est parce qu'il exige que la méthode soit appelée sur une instance de cette classe. La méthode myStaticMethod est définie comme une méthode de classe utilisant le décorateur @classmethod .

juste pour les coups de pied et les rires, nous pourrions appeler myInstanceMethod sur la classe en passant dans une instance de la classe, comme cela:

>>> MyClass.myInstanceMethod(MyClass())
output from an instance method
12
répondu willurd 2017-07-12 10:23:57

une chose spéciale à noter sur les propriétés statiques et les propriétés d'instance, montré dans l'exemple ci-dessous:

class my_cls:
  my_prop = 0

#static property
print my_cls.my_prop  #--> 0

#assign value to static property
my_cls.my_prop = 1 
print my_cls.my_prop  #--> 1

#access static property thru' instance
my_inst = my_cls()
print my_inst.my_prop #--> 1

#instance property is different from static property 
#after being assigned a value
my_inst.my_prop = 2
print my_cls.my_prop  #--> 1
print my_inst.my_prop #--> 2

cela signifie qu'avant d'attribuer la valeur à la propriété instance, si nous essayons d'accéder à la propriété par l'intermédiaire de l'instance, la valeur statique est utilisée. chaque propriété déclarée en classe python a toujours une fente statique en mémoire .

10
répondu jondinham 2012-03-08 06:06:05

quand définir une variable membre en dehors de toute méthode membre, la variable peut être statique ou non statique selon la façon dont la variable est exprimée.

  • CLASSNAME.var est la variable statique
  • INSTANCENAME.var n'est pas une variable statique.
  • l'auto.var inside class n'est pas une variable statique.
  • var à l'intérieur de la fonction de membre de classe n'est pas défini.

par exemple:

#!/usr/bin/python

class A:
    var=1

    def printvar(self):
        print "self.var is %d" % self.var
        print "A.var is %d" % A.var


    a = A()
    a.var = 2
    a.printvar()

    A.var = 3
    a.printvar()

les résultats sont

self.var is 2
A.var is 1
self.var is 2
A.var is 3
8
répondu user2209576 2016-08-03 11:37:36

vous pouvez également appliquer une classe pour être statique en utilisant metaclass.

class StaticClassError(Exception):
    pass


class StaticClass:
    __metaclass__ = abc.ABCMeta

    def __new__(cls, *args, **kw):
        raise StaticClassError("%s is a static class and cannot be initiated."
                                % cls)

class MyClass(StaticClass):
    a = 1
    b = 3

    @staticmethod
    def add(x, y):
        return x+y

puis chaque fois que par accident vous essayez d'initialiser MyClass vous obtiendrez une erreur statique.

6
répondu Bartosz Ptaszynski 2011-11-20 12:06:23

un point très intéressant à propos de la recherche d'attribut de Python est qu'il peut être utilisé pour créer " virtuel variables":

class A(object):

  label="Amazing"

  def __init__(self,d): 
      self.data=d

  def say(self): 
      print("%s %s!"%(self.label,self.data))

class B(A):
  label="Bold"  # overrides A.label

A(5).say()      # Amazing 5!
B(3).say()      # Bold 3!

Normalement, il n'y a pas d'affectation, après ils sont créés. Notez que la recherche utilise self parce que, bien que label soit statique dans le sens de ne pas être associé à une instance particulière , la valeur dépend toujours de la (classe de l'instance).

5
répondu Davis Herring 2017-12-17 17:19:31

il est possible d'avoir des variables de classe static , mais cela n'en vaut probablement pas la peine.

voici une preuve de concept écrite en Python 3 -- si l'un des détails exacts est erroné le code peut être modifié pour correspondre à peu près tout ce que vous voulez dire par un static variable :


class Static:
    def __init__(self, value, doc=None):
        self.deleted = False
        self.value = value
        self.__doc__ = doc
    def __get__(self, inst, cls=None):
        if self.deleted:
            raise AttributeError('Attribute not set')
        return self.value
    def __set__(self, inst, value):
        self.deleted = False
        self.value = value
    def __delete__(self, inst):
        self.deleted = True

class StaticType(type):
    def __delattr__(cls, name):
        obj = cls.__dict__.get(name)
        if isinstance(obj, Static):
            obj.__delete__(name)
        else:
            super(StaticType, cls).__delattr__(name)
    def __getattribute__(cls, *args):
        obj = super(StaticType, cls).__getattribute__(*args)
        if isinstance(obj, Static):
            obj = obj.__get__(cls, cls.__class__)
        return obj
    def __setattr__(cls, name, val):
        # check if object already exists
        obj = cls.__dict__.get(name)
        if isinstance(obj, Static):
            obj.__set__(name, val)
        else:
            super(StaticType, cls).__setattr__(name, val)

et en usage:

class MyStatic(metaclass=StaticType):
    """
    Testing static vars
    """
    a = Static(9)
    b = Static(12)
    c = 3

class YourStatic(MyStatic):
    d = Static('woo hoo')
    e = Static('doo wop')

et certains essais:

ms1 = MyStatic()
ms2 = MyStatic()
ms3 = MyStatic()
assert ms1.a == ms2.a == ms3.a == MyStatic.a
assert ms1.b == ms2.b == ms3.b == MyStatic.b
assert ms1.c == ms2.c == ms3.c == MyStatic.c
ms1.a = 77
assert ms1.a == ms2.a == ms3.a == MyStatic.a
ms2.b = 99
assert ms1.b == ms2.b == ms3.b == MyStatic.b
MyStatic.a = 101
assert ms1.a == ms2.a == ms3.a == MyStatic.a
MyStatic.b = 139
assert ms1.b == ms2.b == ms3.b == MyStatic.b
del MyStatic.b
for inst in (ms1, ms2, ms3):
    try:
        getattr(inst, 'b')
    except AttributeError:
        pass
    else:
        print('AttributeError not raised on %r' % attr)
ms1.c = 13
ms2.c = 17
ms3.c = 19
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
MyStatic.c = 43
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19

ys1 = YourStatic()
ys2 = YourStatic()
ys3 = YourStatic()
MyStatic.b = 'burgler'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
assert ys1.d == ys2.d == ys3.d == YourStatic.d
assert ys1.e == ys2.e == ys3.e == YourStatic.e
ys1.a = 'blah'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
ys2.b = 'kelp'
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
ys1.d = 'fee'
assert ys1.d == ys2.d == ys3.d == YourStatic.d
ys2.e = 'fie'
assert ys1.e == ys2.e == ys3.e == YourStatic.e
MyStatic.a = 'aargh'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
4
répondu Ethan Furman 2016-03-25 09:02:25

pour éviter toute confusion potentielle, j'aimerais comparer les variables statiques et les objets immuables.

certains types d'objets primitifs comme les entiers, les flotteurs, les cordes et les touples sont immuables en Python. Cela signifie que l'objet qui est visé par un prénom ne peut pas changer si c'est de l'un de ces types d'objets. Le nom peut être réaffecté à un autre objet, mais l'objet lui-même ne peut pas être changé.

faisant un la variable static va un peu plus loin en refusant le nom de la variable pour pointer vers n'importe quel objet mais vers celui qu'elle pointe actuellement. (Note: il s'agit d'un concept logiciel général et non spécifique à Python; veuillez consulter les messages d'autres personnes pour des informations sur l'implémentation de statics en Python).

3
répondu Ross 2008-09-17 04:01:08

le meilleur moyen que j'ai trouvé est d'utiliser une autre classe. Vous pouvez créer un objet, puis de l'utiliser sur d'autres objets.

class staticFlag:
    def __init__(self):
        self.__success = False
    def isSuccess(self):
        return self.__success
    def succeed(self):
        self.__success = True

class tryIt:
    def __init__(self, staticFlag):
        self.isSuccess = staticFlag.isSuccess
        self.succeed = staticFlag.succeed

tryArr = []
flag = staticFlag()
for i in range(10):
    tryArr.append(tryIt(flag))
    if i == 5:
        tryArr[i].succeed()
    print tryArr[i].isSuccess()

Avec l'exemple ci-dessus, j'ai fait une classe nommée staticFlag .

cette classe doit présenter la var statique __success (Var statique privée).

La classe

tryIt représentait la classe régulière que nous devions utiliser.

Maintenant, j'ai fait un objet pour un drapeau ( staticFlag ). Ce drapeau sera envoyé comme référence à tous les objets réguliers.

Tous ces objets sont ajoutés à la liste tryArr .


Ce Script Résultats:

False
False
False
False
False
True
True
True
True
True
3
répondu Tomer Zait 2016-04-19 23:42:58

Absolument Oui, Python en lui-même n'a aucun membre de données statiques explicitement, mais nous pouvons avoir en faisant cela ""

class A:
    counter =0
    def callme (self):
        A.counter +=1
    def getcount (self):
        return self.counter  
>>> x=A()
>>> y=A()
>>> print(x.getcount())
>>> print(y.getcount())
>>> x.callme() 
>>> print(x.getcount())
>>> print(y.getcount())

sortie

0
0
1
1

explication

here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"
3
répondu Mari Selvan 2017-02-22 13:01:13

en ce qui concerne cette réponse , pour une constante variable statique, vous pouvez utiliser un descripteur. Voici un exemple:

class ConstantAttribute(object):
    '''You can initialize my value but not change it.'''
    def __init__(self, value):
        self.value = value

    def __get__(self, obj, type=None):
        return self.value

    def __set__(self, obj, val):
        pass


class Demo(object):
    x = ConstantAttribute(10)


class SubDemo(Demo):
    x = 10


demo = Demo()
subdemo = SubDemo()
# should not change
demo.x = 100
# should change
subdemo.x = 100
print "small demo", demo.x
print "small subdemo", subdemo.x
print "big demo", Demo.x
print "big subdemo", SubDemo.x

résultant en ...

small demo 10
small subdemo 100
big demo 10
big subdemo 10

vous pouvez toujours soulever une exception si ignorer calmement la valeur de réglage ( pass ci-dessus) n'est pas votre truc. Si vous cherchez une variable de classe statique C++, Style Java:

class StaticAttribute(object):
    def __init__(self, value):
        self.value = value

    def __get__(self, obj, type=None):
        return self.value

    def __set__(self, obj, val):
        self.value = val

Avoir un coup d'oeil cette réponse et le fonctionnaire docs HOWTO pour plus d'informations sur les descripteurs.

2
répondu Yann 2017-05-23 12:18:14

Variables Statiques dans la Classe de l'usine de python3.6

pour toute personne utilisant une usine de classe avec python3.6 et plus utilisez le mot-clé nonlocal pour l'ajouter à la portée / contexte de la classe créée comme suit:

>>> def SomeFactory(some_var=None):
...     class SomeClass(object):
...         nonlocal some_var
...         def print():
...             print(some_var)
...     return SomeClass
... 
>>> SomeFactory(some_var="hello world").print()
hello world
1
répondu jmunsch 2017-01-01 02:56:08