Wie erstelle ich statische Klassenvariablen oder Methoden in Python?
Antworten
Zu viele Anzeigen?Diesbezüglich Antwort für eine Konstante statischen Variablen können Sie einen Deskriptor verwenden. Hier ist 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 Sie den Einstellwert ignorieren ( pass
oben) ist nicht Ihr Ding. Wenn Sie nach einer statischen Klassenvariable im Stil von C++ oder Java suchen:
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
Werfen Sie einen Blick auf diese Antwort und die offiziellen Dokumente HOWTO für weitere Informationen über Deskriptoren.
Der beste Weg, den ich gefunden habe, ist, eine andere Klasse zu verwenden. Sie können ein Objekt erstellen und es dann auf andere Objekte anwenden.
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()
Für das obige Beispiel habe ich eine Klasse namens staticFlag
.
Diese Klasse sollte die statische var __success
(Private statische Var).
tryIt
Klasse repräsentiert die reguläre Klasse, die wir verwenden müssen.
Jetzt habe ich ein Objekt für eine Flagge ( staticFlag
). Dieses Kennzeichen wird als Referenz an alle regulären Objekte gesendet.
Alle diese Objekte werden in die Liste aufgenommen tryArr
.
Dieses Skript ergibt:
False
False
False
False
False
True
True
True
True
True
Wenn man die Antworten der anderen zusammenfasst und hinzufügt, gibt es viele Möglichkeiten, statische Methoden oder Variablen in python .
1. Verwendung von staticmethod() als Dekorateur:
Man kann einfach einen Dekorator über eine deklarierte Methode (Funktion) setzen, um sie zu einer statischen Methode zu machen. Zum Beispiel.
class Calculator:
@staticmethod
def multiply(n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 * n2 * Res
print(Calculator.multiply(1, 2, 3, 4)) # 24
2. Verwendung von staticmethod() als eine Parameterfunktion:
Diese Methode kann ein Argument vom Typ Funktion erhalten und gibt eine statische Version der übergebenen Funktion zurück. Zum Beispiel.
class Calculator:
def add(n1, n2, *args):
return n1 + n2 + sum(args)
Calculator.add = staticmethod(Calculator.add)
print(Calculator.add(1, 2, 3, 4)) # 10
3. Verwendung von classmethod() als Dekorateur:
@classmethod hat ähnliche Auswirkungen auf eine Funktion wie @staticmethod, aber dieses Mal wird ein zusätzliches Argument benötigt, um in der Funktion akzeptiert zu werden (ähnlich dem self-Parameter für Instanzvariablen). Zum Beispiel.
class Calculator:
num = 0
def __init__(self, digits) -> None:
Calculator.num = int(''.join(digits))
@classmethod
def get_digits(cls, num):
digits = list(str(num))
calc = cls(digits)
return calc.num
print(Calculator.get_digits(314159)) # 314159
4. Verwendung von classmethod() als eine Parameterfunktion:
@classmethod kann auch als Parameterfunktion verwendet werden, wenn man die Klassendefinition nicht ändern möchte. Zum Beispiel.
class Calculator:
def divide(cls, n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 / n2 / Res
Calculator.divide = classmethod(Calculator.divide)
print(Calculator.divide(15, 3, 5)) # 1.0
5. Direkte Erklärung
Eine Methode/Variable, die außerhalb aller anderen Methoden, aber innerhalb einer Klasse deklariert wird, ist automatisch statisch.
class Calculator:
def subtract(n1, n2, *args):
return n1 - n2 - sum(args)
print(Calculator.subtract(10, 2, 3, 4)) # 1
Das gesamte Programm
=======================
class Calculator:
num = 0
def __init__(self, digits) -> None:
Calculator.num = int(''.join(digits))
@staticmethod
def multiply(n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 * n2 * Res
def add(n1, n2, *args):
return n1 + n2 + sum(args)
@classmethod
def get_digits(cls, num):
digits = list(str(num))
calc = cls(digits)
return calc.num
def divide(cls, n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 / n2 / Res
def subtract(n1, n2, *args):
return n1 - n2 - sum(args)
Calculator.add = staticmethod(Calculator.add)
Calculator.divide = classmethod(Calculator.divide)
print(Calculator.multiply(1, 2, 3, 4)) # 24
print(Calculator.add(1, 2, 3, 4)) # 10
print(Calculator.get_digits(314159)) # 314159
print(Calculator.divide(15, 3, 5)) # 1.0
print(Calculator.subtract(10, 2, 3, 4)) # 1
Siehe Python-Dokumentation für die Beherrschung von OOP in Python.
Um jede mögliche Verwirrung zu vermeiden, möchte ich statische Variablen und unveränderliche Objekte gegenüberstellen.
Einige primitive Objekttypen wie Integers, Floats, Strings und Tuples sind in Python unveränderlich. Das bedeutet, dass sich das Objekt, auf das ein bestimmter Name verweist, nicht ändern kann, wenn es zu einem der oben genannten Objekttypen gehört. Der Name kann einem anderen Objekt zugewiesen werden, aber das Objekt selbst kann nicht geändert werden.
Eine Variable statisch zu machen, geht noch einen Schritt weiter, indem es dem Variablennamen untersagt, auf ein anderes Objekt zu zeigen als das, auf das er gerade zeigt. (Hinweis: Dies ist ein allgemeines Software-Konzept und nicht spezifisch für Python; Informationen zur Implementierung von Statik in Python finden Sie in anderen Beiträgen).
Statische Variablen in der Klassenfabrik python3.6
Für alle, die eine Klassenfabrik mit python3.6 und aufwärts verwenden die nonlocal
Schlüsselwort, um es dem Bereich/Kontext der zu erstellenden Klasse hinzuzufügen, wie folgt:
>>> 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