2569 Stimmen

Statische Klassenvariablen und Methoden in Python

Wie erstelle ich statische Klassenvariablen oder Methoden in Python?

25voto

jondinham Punkte 7893

Eine Besonderheit ist bei statischen Eigenschaften und Instanzeigenschaften zu beachten, wie im folgenden Beispiel gezeigt:

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, dass der statische Wert verwendet wird, bevor der Wert der Instanzeigenschaft zugewiesen wird, wenn wir versuchen, auf die Eigenschaft über die Instanz zuzugreifen. Jede in einer Python-Klasse deklarierte Eigenschaft hat immer einen statischen Platz im Speicher .

24voto

willurd Punkte 11009

Statische Methoden in Python heißen Klassenmethode 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 wir beim Aufruf der Methode myInstanceMethod erhalten wir einen Fehler. Das liegt daran, dass diese Methode auf einer Instanz dieser Klasse aufgerufen werden muss. Die Methode myStaticMethod wird als Klassenmethode mit der Methode Tapezierer @classmethod .

Nur so zum Spaß könnten wir anrufen myInstanceMethod auf die Klasse anwenden, indem Sie eine Instanz der Klasse übergeben, etwa so:

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

18voto

Ethan Furman Punkte 57238

Es ist möglich, Folgendes zu haben static Klassenvariablen, aber wahrscheinlich lohnt sich der Aufwand nicht.

Hier ist ein Proof-of-Concept, das in Python 3 geschrieben wurde - wenn einige der genauen Details falsch sind, kann der Code so angepasst werden, dass er genau dem entspricht, was Sie mit einem 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)

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

17voto

user2209576 Punkte 159

Wenn eine Mitgliedsvariable außerhalb einer Mitgliedsmethode definiert wird, kann die Variable entweder statisch oder nicht statisch sein, je nachdem, wie die Variable ausgedrückt wird.

  • CLASSNAME.var ist eine statische Variable
  • INSTANCENAME.var ist keine statische Variable.
  • self.var innerhalb der Klasse ist keine statische Variable.
  • var innerhalb der Klassenfunktion 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

16voto

Vlad Bezden Punkte 71128

@dataclass-Definitionen liefern Namen auf Klassenebene, die zur Definition der Instanzvariablen und der Initialisierungsmethode verwendet werden, __init__() . Wenn Sie eine Variable auf Klassenebene in @dataclass sollten Sie typing.ClassVar Typ-Hinweis. Die Website ClassVar Die Parameter des Typs definieren den Typ der Variablen auf Klassenebene.

from typing import ClassVar
from dataclasses import dataclass

@dataclass
class Test:
    i: ClassVar[int] = 10
    x: int
    y: int

    def __repr__(self):
        return f"Test({self.x=}, {self.y=}, {Test.i=})"

Beispiele für den Gebrauch:

> test1 = Test(5, 6)
> test2 = Test(10, 11)

> test1
Test(self.x=5, self.y=6, Test.i=10)
> test2
Test(self.x=10, self.y=11, Test.i=10)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X