Frage

Ist es möglich, statische Klassenvariablen oder Methoden in Python haben? Welche Syntax erforderlich, dies zu tun?

War es hilfreich?

Lösung

Variablen innerhalb der Klassendefinition deklariert, aber nicht innerhalb einer Methode sind Klassen- oder statische Variablen:

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

Wie @ millerdev weist darauf hin, schafft dies eine Klassen- Ebene i variabel, aber dies unterscheidet sich von jeder Instanzebene i Variable, so könnten Sie haben

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

Dies unterscheidet sich von C ++ und Java, aber nicht so verschieden von C #, wobei ein statisches Element nicht mit einem Verweis auf eine Instanz zugegriffen werden kann.

Siehe was die Python-Tutorial haben zum Thema Klassen sagen und Klassenobjekte .

@Steve Johnson hat bereits in Bezug auf , dokumentierte auch unter "Built-in-Funktionen" in der Python Library Reference .

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

@beidy empfiehlt Class s über static, wie das Verfahren dann erhält den Klassentyp als erstes Argument, aber ich bin immer noch ein wenig über die Vorteile dieses Ansatzes gegenüber static unscharf. Wenn auch Sie sind, dann wahrscheinlich spielt es keine Rolle.

Andere Tipps

@Blair Conrad sagte statische Variablen innerhalb der Klassendefinition deklariert, aber nicht innerhalb einer Methode sind Klassen- oder „statisch“ Variablen:

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

Es gibt ein paar gotcha ist hier. Trage auf aus dem obigen Beispiel:

>>> 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__
{}

Beachten Sie, wie der Instanzvariable t.i mit dem „statischen“ Klassenvariable out of sync bekam, wenn das Attribut i direkt auf t gesetzt wurde. Dies liegt daran, i wurde im t Namespace neu gebunden, die aus dem Test Namespace unterscheiden. Wenn Sie den Wert eines „statischen“ Variable ändern möchten, müssen Sie es im Rahmen ändern (oder Objekt), wo sie ursprünglich definiert wurde. Ich habe „statisch“ in Anführungszeichen, weil Python nicht wirklich statische Variablen in dem Sinne, dass C ++ und Java zu tun.

Auch wenn es nicht sagt, etwas Bestimmtes über statische Variablen oder Methoden, die Python Tutorial hat einige relevante Informationen über Klassen und Klassen rel="nofollow Objekte .

@Steve Johnson auch in Bezug auf statische Methoden beantwortet, dokumentierten auch unter "Integrierte Funktionen" in dem Python Library Reference.

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

@beid auch erwähnt Class, die static ähnlich ist. Ein Class erstes Argument ist das Klassenobjekt. Beispiel:

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

Statische und Klassenmethoden

Wie die anderen Antworten erwähnt haben, statische und Klassenmethoden werden erreicht leicht die Einbau-Dekorateure mit:

class Test(object):

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

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

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

Wie üblich, das erste Argument MyMethod() an die Klasseninstanz Objekt gebunden. Im Gegensatz dazu das erste Argument MyClassMethod() ist gebunden auf das Klassenobjekt selbst (zum Beispiel in diesem Fall Test). Für MyStaticMethod(), keines der Argumente gebunden sind, und Argumente überhaupt aufweist, ist optional.

"Static Variables"

Allerdings: „statische Variablen“ (na ja, wandelbar statische Variablen, wie auch immer, wenn das in keinen Widerspruch ist ...) die Umsetzung ist nicht so einfach. Wie millerdev in seiner Antwort wies darauf hin, das Problem ist, dass Pythons Klassenattribute sind nicht wirklich „statische Variablen“. Bedenken Sie:

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

Das ist, weil die Linie x.i = 12 eine neue Instanz Attribut i hinzugefügt x stattdessen den Wert des Test Klasse i Attributs ändern.

Partial erwartetes statisches Variable Verhalten, dh die Synchronisierung des Attributs zwischen mehreren Instanzen (aber nicht mit der Klasse selbst, "Gotcha" weiter unten), kann erreicht werden, durch das Klassenattribut in eine Eigenschaft drehen:

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)

Jetzt können Sie tun:

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

Die statische Variable wird nun synchron bleiben zwischen allen Klasseninstanzen .

(HINWEIS: Das heißt, es sei denn, eine Klasseninstanz entscheidet, seine eigene Version von _i zu definieren, aber wenn jemand, das zu tun entscheidet, die sie verdienen, was sie bekommen, nicht wahr ???)

Beachten Sie, dass technisch gesehen, i ist noch keine ‚statische Variable‘ überhaupt; es ist ein property, die eine spezielle Art von Deskriptor. Allerdings ist das property Verhalten nun äquivalent zu einer (änderbaren) statischen Variable in allen Klasseninstanzen synchronisiert.

Immutable "Static Variables"

Für unveränderliches statisches Variablen Verhalten, einfach weglassen der property Setzer:

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)

versucht nun die Instanz i Attribut gesetzt werden eine AttributeError zurück:

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

Ein Gotcha Aware von

sein

Beachten Sie, dass die oben genannten Methoden mit nur funktionieren, Instanzen Ihrer Klasse - sie werden nicht Arbeit bei der Verwendung der Klasse selbst . So zum Beispiel:

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'

Die Linie assert Test.i == x.i erzeugt einen Fehler, weil das i Attribut Test und x sind zwei verschiedene Objekte.

Viele Menschen werden diese überraschend finden. Allerdings sollte es nicht sein. Wenn wir zurück und überprüfen unsere Test Klassendefinition (die zweite Version) gehen wir zur Kenntnis dieser Linie nehmen:

    i = property(get_i) 

Natürlich muss das Mitglied i von Test ein property Objekt sein, das die Art des Objekts aus der property Funktion zurückgegeben wird.

Wenn Sie die oben verwirrend finden, Sie sind am ehesten noch über sie aus der Perspektive von anderen Sprachen zu denken (zum Beispiel Java oder C ++). Sie sollten das property Objekt, über die Reihenfolge gehen studieren, in denen Python Attribute zurückgegeben werden, das Descriptor-Protokoll und das Verfahren Auflösung um (MRO).

präsentiere ich eine Lösung für die oben ‚Gotcha‘ unten; Ich würde jedoch vorschlagen - strenuously - dass Sie nicht versuchen, so etwas wie das zu tun, folgende, bis - mindestens - Sie gründlich verstehen, warum assert Test.i = x.i einen Fehler verursacht.

REAL, ACTUAL Statische Variablen - Test.i == x.i

Ich stelle die (Python 3) Lösung unten dienen nur zu Informationszwecken. Ich befürworte es nicht als „gute Lösung“. Ich habe meine Zweifel, whEther der statischen Variablen Verhalten anderer Sprachen in Python Emulation ist jemals wirklich notwendig ist. Doch unabhängig davon, ob es tatsächlich sinnvoll ist, sollte die unten weiter helfen zu verstehen, wie Python funktioniert.

UPDATE: dieser Versuch ist wirklich ziemlich schrecklich ; wenn Sie darauf bestehen, so etwas wie dies zu tun (Hinweis: bitte nicht, Python eine sehr elegante Sprache und Schuh-Horning es in wie eine andere Sprache zu verhalten ist einfach nicht notwendig), verwenden Sie den Code in Ethan Furman Antwort statt.

emulieren statisches Variable Verhalten anderer Sprachen eine Metaklasse mit

Eine Metaklasse ist die Klasse einer Klasse. Die Standard-Metaklasse für alle Klassen in Python (das heißt, die „neuen Stil“ Klassen schreiben Python 2.3 glaube ich) ist type. Zum Beispiel:

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

Allerdings können Sie Ihre eigene Metaklasse wie folgt definieren:

class MyMeta(type): pass

Und es auf Ihre eigene Klasse wie dieser (Python 3 nur):

class MyClass(metaclass = MyMeta):
    pass

type(MyClass)  # class MyMeta

Im Folgenden finden Sie eine Metaklasse ich geschaffen habe, die „statische Variable“ Verhalten anderer Sprachen nachzuahmen versucht. Es funktioniert im Grunde durch die Standard-Getter, Setter ersetzt und deleter mit Versionen, die zu überprüfen, ob das Attribut angefordert wird, eine „statische Variable“ ist.

Ein Katalog der „statischen Variablen“ im StaticVarMeta.statics Attribute gespeichert. Alle Attributanforderungen werden zunächst versucht, einen Ersatz Auflösung, um gelöst werden. Ich habe dies die „statische Auflösung Ordnung“ genannt, oder „SRO“. Dies wird durch die Suche nach dem gewünschten Attribute in dem Satz von „statischen Variablen“ für eine bestimmte Klasse (oder deren Mutter Klassen) durchgeführt. Wenn das Attribut in dem „SRO“ nicht angezeigt wird, wird die Klasse auf dem Standard zurückfallen Attribute get / set / löscht Verhalten (das heißt, „Technik“).

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

Sie können auch Klassenvariablen Klassen on the fly hinzufügen

>>> 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

Und Klasseninstanzen können Klassenvariablen ändern

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

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

>python test.py
[1]
[1, 1]

Persönlich würde ich einen Class verwenden, wenn ich eine statische Methode benötigt. Vor allem, weil ich die Klasse als Argument erhalten.

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

oder einen Dekorateur verwenden

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

Für die statische Eigenschaften .. Es ist Zeit, Sie einige Python Definition nachschlagen .. Variable kann sich jederzeit ändern. Es gibt zwei Arten von ihnen wandelbar und unveränderlich .. Auch gibt es Klassenattribute und Instanzattribute .. Nichts wirklich wie statische Attribute im Sinne von Java & C ++

Warum statische Methode in pythonic Sinne verwenden, wenn es keine Beziehung, was auch immer auf die Klasse hat! Wenn ich Sie wäre, würde ich entweder Class verwenden oder die Methode unabhängig von der Klasse definieren.

Eine besondere Sache zu beachten über statische Eigenschaften und Instanzeigenschaften, im Beispiel unten dargestellt:

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

Das bedeutet, bevor Sie den Wert auf Instanz Eigenschaft zuweisen, wenn wir versuchen, zuzugreifen, um die Eigenschaft durch‘Beispiel der statische Wert verwendet. Jede Eigenschaft in Python-Klasse deklariert hat immer einen statischen Schlitz im Speicher .

Statische Methoden in Python sind Class s. Werfen Sie einen Blick auf den folgenden Code

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

Beachten Sie, dass, wenn wir die Methode aufrufen myInstanceMethod , wir einen Fehler. Dies liegt daran, es erfordert, dass Verfahren auf eine Instanz dieser Klasse aufgerufen werden. Die Methode myStaticMethod als Class gesetzt Dekorateur mit @classmethod .

Nur für Kicks und kichert, den wir anrufen können myInstanceMethod auf der Klasse, indem sie in einer Instanz der Klasse vorbei, etwa so:

>>> MyClass.myInstanceMethod(MyClass())
output from an instance method

, wenn einige Elementvariable außerhalb jeden Mitglieds Verfahren definieren, kann die Variable entweder statisch oder nicht statisch sein, je nachdem, wie die Variable ausgedrückt wird.

  • CLASSNAME.var ist statische Variable
  • INSTANCENAME.var ist nicht statisch variabel.
  • self.var innerhalb der Klasse ist nicht statisch variabel.
  • var innerhalb der Klasse Member-Funktion ist nicht definiert.

Zum Beispiel:

#!/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()

Die Ergebnisse sind

self.var is 2
A.var is 1
self.var is 2
A.var is 3

Sie können auch eine Klasse erzwingen statisch sein Metaklasse verwendet wird.

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

Dann, wenn durch Zufall versuchen Sie zu initialisieren MyClass Sie erhalten eine StaticClassError erhalten.

Es ist möglich, static Klassenvariablen zu haben, aber wahrscheinlich nicht die Mühe wert.

Hier ist ein Proof-of-Concept in Python geschrieben 3 -, wenn eine der genauen Details sind falsch kann der Code optimiert wird nur etwa entsprechen, was Sie von einem static variable bedeuten:


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)

und im Einsatz:

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')

und einige Tests:

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

Ein sehr interessanter Punkt über Pythons Attribut-Lookup ist, dass es verwendet werden kann „ virtuelle Variablen ":

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!

Normalerweise gibt es keine Zuordnungen diese, nachdem sie erstellt werden. Beachten Sie, dass die Lookup-self verwendet, weil, obwohl label nicht statisch ist im Sinne des mit einem verbunden ist insbesondere Beispiel hängt der Wert immer noch auf der (Klasse der) Instanz.

In Bezug auf diese beantworten , für eine Konstante statische Variable, können Sie ein verwenden Descriptor. Hier ein Beispiel:

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

was zu ...

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

Sie können immer eine Ausnahme auslösen, wenn ruhig ignorieren Einstellungswert (pass oben) ist nicht Ihre Sache. Wenn Sie suchen für eine C ++, Java-Stil statische Klassenvariablen:

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

Hier finden Sie aktuelle diese Antwort und die offiziellen Dokumente HOWTO für weitere Informationen über Deskriptoren.

Absolut Ja,   Python selbst hat kein statischen Daten Mitglied explizit, aber wir können so durch tun haben

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())

Ausgang

0
0
1
1

Erklärung

here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"

eine mögliche Verwirrung zu vermeiden, würde Ich mag statische Variablen und unveränderliche Objekte zu kontrastieren.

Einige primitiven Objekttypen wie Integer, Schwimmern, Strings und touples sind unveränderlich in Python. Dies bedeutet, dass das Objekt, das von einem bestimmten Namen bezeichnet wird, kann nicht geändert werden, wenn es von einem der oben genannten Objekttypen ist. Der Name kann zu einem anderen Objekt zugewiesen werden, aber das Objekt selbst nicht verändert werden kann.

eine Variable statisch zu machen geht einen Schritt weiter, indem Sie den Variablennamen auf ein beliebiges Objekt zeigen disallowing aber das, auf die er zeigt zur Zeit. (Hinweis: Dies ist ein allgemeines Software-Konzept ist und nicht spezifisch für Python, bitte Beiträge andere Informationen sehen über Statik in Python implementiert werden).

Der beste Weg, fand ich eine andere Klasse zu verwenden. Sie können ein Objekt erstellen und dann auf andere Objekte verwendet werden.

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()

Mit dem obigen Beispiel habe ich eine Klasse mit dem Namen staticFlag.

Diese Klasse soll die statische var __success (Private Static Var) präsentieren.

tryIt Klasse repräsentiert die reguläre Klasse, die wir verwenden müssen.

Jetzt habe ich ein Objekt für einen Flag (staticFlag). Diese Flagge wird als Referenz auf alle regulären Objekte gesendet werden.

All diese Objekte werden in der Liste tryArr hinzugefügt.


Dieses Skript Ergebnisse:

False
False
False
False
False
True
True
True
True
True

Ja, auf jeden Fall möglich, statische Variablen und Methoden in Python zu schreiben.

Statische Variablen: Variable auf Klassenebene deklariert sind statische Variable genannt, die direkt Klassennamen zugegriffen werden kann.

    >>> class A:
        ...my_var = "shagun"

    >>> print(A.my_var)
        shagun

Instanzvariablen:. Variablen, die von Instanz einer Klasse sind Instanzvariablen verwendet und zugegriffen wird

   >>> a = A()
   >>> a.my_var = "pruthi"
   >>> print(A.my_var,a.my_var)
       shagun pruthi

Statische Methoden: Ähnlich wie Variablen können statische Methoden direkt zugegriffen werden Klassennamen. Keine Notwendigkeit, eine Instanz zu erstellen.

Aber bedenken Sie, eine statische Methode eine nicht-statische Methode in Python nicht aufrufen kann.

    >>> class A:
   ...     @staticmethod
   ...     def my_static_method():
   ...             print("Yippey!!")
   ... 
   >>> A.my_static_method()
   Yippey!!

Statische Variablen in der Klasse Fabrik python3.6

Für jedermann eine Klasse Fabrik mit mit python3.6 und auf das nonlocal Schlüsselwort verwenden, um den Umfang / Kontext der Klasse hinzuzufügen ist wie so erstellt:

>>> 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

Sie einfach eine Klasse erstellen, enthält unabhängig von variablen oder Objekttypen. Zugang dass Variablen-Klasse Namen wie unten:


    class StaticVariable:
        myvar1 = 1
        myvar2 = 2


    StaticVariable.myvar1 = StaticVariable.myvar1 +1
    StaticVariable.myvar2 = StaticVariable.myvar2 +1

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top