Tatsächlich ist die Möglichkeit, schreibgeschützte Variablen zu erstellen, über die Eigenschaftsfunktion / den Dekorator von Python möglich . Die Antwort von inv ist ein Beispiel für eine benutzerdefinierte Verwendung davon. Eigenschaft ist allgemeiner als das, aber eine gute Analyse, wie es funktioniert, ist auf Shalabh Chaturvedis Python-Attribute und -Methoden .
n611x007
20
IMHO ist das Erzwingen von Konstanz "nicht pythonisch". In Python 2.7 können Sie sogar schreiben True=Falseund (2+2==4)==Truekehren dann zurück False.
osa
8
Wie andere Antworten vermuten lassen, gibt es keine Möglichkeit oder Notwendigkeit, Konstanten zu deklarieren. Sie können diesen PEP jedoch über Konventionen lesen . zB THIS_IS_A_CONSTANT
Rasika Perera
34
@osa: Das kannst du in Python 3 nicht machen - SyntaxError: can't assign to keyword. Dies scheint eine gute Sache zu sein.
naught101
3
Überrascht wurde dies bisher noch nicht erwähnt, aber Enums scheinen eine gute Möglichkeit zu sein, aufgezählte Konstanten zu definieren.
CS95
Antworten:
973
Nein, da ist kein. Sie können eine Variable oder einen Wert in Python nicht als Konstante deklarieren. Ändere es einfach nicht.
Wenn Sie in einer Klasse sind, wäre das Äquivalent:
classFoo(object):
CONST_NAME ="Name"
wenn nicht, ist es einfach
CONST_NAME ="Name"
Vielleicht möchten Sie sich aber das Code-Snippet Constants in Python von Alex Martelli ansehen .
Ab Python 3.8 gibt es eine typing.FinalVariablenanmerkung, die statischen Typprüfern (wie mypy) mitteilt, dass Ihre Variable nicht neu zugewiesen werden sollte. Dies ist das nächste Äquivalent zu Java final. Eine Neuzuweisung wird jedoch nicht verhindert :
from typing importFinal
a:Final=1# Executes fine, but mypy will report an error if you run mypy on this:
a =2
Anstatt das zu tun, was in "Konstanten in Python" steht, sollten Sie die Funktion "Eigenschaft" oder den Dekorator verwenden.
Seth Johnson
26
Die Leute fragen nach der gleichen Funktion in Perl. Es gibt ein Importmodul namens "Use Constant", aber (AFAIK) ist nur ein Wrapper, um eine winzige Funktion zu erstellen, die den Wert zurückgibt. Ich mache das gleiche in Python. Beispiel:def MY_CONST_VALUE(): return 123
Kevinarpe
8
"Nein, da ist kein." Es stimmt, aber ich baue auf der Arbeit anderer Leute auf und habe weit unten eine Antwort mit einer kurzen und einfachen Implementierung von "Constants" für Python 2.7 (dem "enum" fehlt) hinzugefügt. Diese sind enum-like schreibgeschützt name.attributeund können einen beliebigen Wert enthalten. Die Deklaration ist einfach Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0), die Verwendung ist unkompliziert print 10 + Nums.PI. Versuchen Sie, die Ergebnisse in Ausnahme Nums.PI = 22=> ValueError (..) zu ändern .
ToolmakerSteve
108
Ändere es einfach nicht. Du hast meinen Tag gemacht
Hi-Angel
89
"Ändere es einfach nicht" ist überhaupt nicht hilfreich. Es beantwortet die Frage nicht und ich würde vorschlagen, dass es entfernt wird.
Bartek Banachewicz
354
Es gibt kein constSchlüsselwort wie in anderen Sprachen, es ist jedoch möglich, eine Eigenschaft zu erstellen, die eine "Getter-Funktion" zum Lesen der Daten hat, aber keine "Setter-Funktion" zum erneuten Schreiben der Daten. Dies schützt die Kennung im Wesentlichen vor Änderungen.
Hier ist eine alternative Implementierung unter Verwendung der Klasseneigenschaft:
Beachten Sie, dass der Code für einen Leser, der sich über Konstanten wundert, alles andere als einfach ist. Siehe Erklärung unten
Definieren Sie eine Funktion constant, die einen Ausdruck nimmt und daraus einen "Getter" erstellt - eine Funktion, die ausschließlich den Wert des Ausdrucks zurückgibt.
Die Setter-Funktion löst einen TypeError aus, sodass er schreibgeschützt ist
Verwenden Sie die constantsoeben erstellte Funktion als Dekoration, um schnell schreibgeschützte Eigenschaften zu definieren.
Und auf eine andere altmodischere Weise:
(Der Code ist ziemlich knifflig, weitere Erklärungen unten)
Beachten Sie, dass der @ applly-Dekorator veraltet zu sein scheint.
Um den Bezeichner FOO zu definieren, definieren firs zwei Funktionen (fset, fget - die Namen sind nach meiner Wahl).
Verwenden Sie dann die integrierte propertyFunktion, um ein Objekt zu erstellen, das "gesetzt" oder "get" werden kann.
Beachten Sie, dass die propertyersten beiden Parameter der Funktion mit fsetund benannt sind fget.
Verwenden Sie die Tatsache, dass wir genau diese Namen für unseren eigenen Getter & Setter ausgewählt haben, und erstellen Sie ein Schlüsselwortwörterbuch mit dem ** (Doppelsternchen), das auf alle lokalen Definitionen dieses Bereichs angewendet wird, um Parameter an die propertyFunktion zu übergeben
Basierend auf der Dokumentation zu AttributeErrorund TypeErrordenke ich, dass die ausgelöste Ausnahme ein neuer Fehler sein sollte, den ich benenne, ConstantErroroder so ähnlich, der eine Unterklasse von ist TypeError. Der Abschnitt in den Dokumenten, der mich denken lässt, dass: docs.python.org/2/library/exceptions.html
ArtOfWarfare
3
Ich bin mit diesem Code überrascht. Warum haben die Methoden FOO () und BAR () die Schriftart self als Argument? Meine IDE unterstreicht die Klammern in Rot (Fehler "Kompilieren"). Ich war müde, mich darauf einzulassen, aber dann bekomme ich einen Fehler.
user3770060
10
Wenn Sie zu diesen Längen gehen, wird ein deutlicher Mangel in der Python-Sprache festgestellt. Warum hatten sie nicht das Bedürfnis, dies zu Python 3 hinzuzufügen? Ich kann nicht glauben, dass niemand es vorgeschlagen hat, und ich kann einfach nicht die Logik hinter einem Komitee sehen, das nah geht, Konstanten? nee. '
Andrew S
8
Und Ihre Lösung kann immer noch von einem entschlossenen Python-Programmierer mitCONST.__dict__['FOO'] = 7
pppery
11
@OscarSmith, ich denke, es würde das Design des selbstdokumentierten Codes verbessern. Wenn ich im Code deutlich mache, dass sich ein Wert nicht ändern kann, ist es einfacher zu verstehen, als den gesamten Quellcode zu lesen und zu erkennen, dass sich ein Wert nie ändert. Außerdem wird die Möglichkeit blockiert, dass jemand einen Wert ändert, der konstant sein sollte. Denken Sie daran: explizit ist besser als implizit.
Gabriel
112
In Python verwenden Benutzer anstelle von etwas, das die Sprache erzwingt, Namenskonventionen, z. B. __methodfür private Methoden und _methodfür geschützte Methoden.
Auf die gleiche Weise können Sie die Konstante einfach als alle Kappen deklarieren, z
MY_CONSTANT ="one"
Wenn Sie möchten, dass sich diese Konstante nie ändert, können Sie sich in den Attributzugriff einbinden und Tricks ausführen. Ein einfacherer Ansatz besteht jedoch darin, eine Funktion zu deklarieren
def MY_CONSTANT():return"one"
Das einzige Problem ist, dass Sie überall MY_CONSTANT () ausführen müssen, aber auch dies MY_CONSTANT = "one"ist (normalerweise) der richtige Weg in Python.
Sie können namedtuple auch verwenden , um Konstanten zu erstellen:
>>>from collections import namedtuple
>>>Constants= namedtuple('Constants',['pi','e'])>>> constants =Constants(3.14,2.718)>>> constants.pi
3.14>>> constants.pi =3Traceback(most recent call last):File"<stdin>", line 1,in<module>AttributeError: can't set attribute
Wenn Sie dies tun, def MY_CONSTANT(): return "one"wird jemand später im Code nicht daran gehindert, etwas zu tun MY_CONSTANT = "two"(oder die Funktion neu zu deklarieren).
Matthew Schinckel
6
@MatthewSchinckel es geht um Konvention, auch das Ändern von MY_CONSTANT ändert nicht die Verwendung von MY_CONSTANT (), sondern wirft einen Fehler aus, und in Python kann Sie kein cleverer Trick schützen, wenn Sie möchten, dass Sie etwas ändern können.
Anurag Uniyal
3
Vielen Dank, dass Sie den Namedtuple-Ansatz angesprochen haben. Auf jeden Fall innovativ. Vielleicht finden Sie hier auch meinen "Kommentar" relevant.
RayLuo
@MatthewSchinckel Sie können ALLES in Python neu definieren, das ist also kein wirklich guter Punkt.
cslotty
@MatthewSchinckel Die Idee ist nicht zu schreiben MY_CONSTANT = MY_CONSTANT(), sondern MY_CONSTANT()als Konstante zu verwenden. Natürlich das. Dies ist jedoch in Ordnung und entspricht weitgehend dem Python-Prinzip "Wir sind alle Erwachsene hier" - dh es wird dem Entwickler selten verboten , eine Regel zu überschreiben, wenn er gute Gründe hat und weiß, was er tut.
jonathan.scholbach
69
Ich habe kürzlich ein sehr kurzes Update gefunden, das automatisch aussagekräftige Fehlermeldungen auslöst und den Zugriff über Folgendes verhindert __dict__:
class CONST(object):
__slots__ =()
FOO =1234
CONST = CONST()# ----------print(CONST.FOO)# 1234
CONST.FOO =4321# AttributeError: 'CONST' object attribute 'FOO' is read-only
CONST.__dict__['FOO']=4321# AttributeError: 'CONST' object has no attribute '__dict__'
CONST.BAR =5678# AttributeError: 'CONST' object has no attribute 'BAR'
Wir definieren uns selbst als Instanz und verwenden dann Slots, um sicherzustellen, dass keine zusätzlichen Attribute hinzugefügt werden können. Dadurch wird auch der __dict__Zugangsweg entfernt . Natürlich kann das gesamte Objekt immer noch neu definiert werden.
Bearbeiten - Ursprüngliche Lösung
Ich vermisse hier wahrscheinlich einen Trick, aber das scheint für mich zu funktionieren:
Durch das Erstellen der Instanz kann die magische __setattr__Methode Versuche zum Festlegen der FOOVariablen starten und abfangen . Sie könnten hier eine Ausnahme auslösen, wenn Sie möchten. Das Instanziieren der Instanz über den Klassennamen verhindert den direkten Zugriff über die Klasse.
Es ist ein totaler Schmerz für einen Wert, aber Sie könnten viel an Ihr CONSTObjekt anhängen . Mit einer Oberschicht scheint der Klassenname auch ein bisschen grottig zu sein, aber ich denke, dass er insgesamt ziemlich prägnant ist.
Dies ist die beste und klarste Antwort, da sie den geringsten "Mechanismus", aber die meisten Funktionen aufweist. Das Auslösen einer Ausnahme ist jedoch wichtig ... keine Option.
Erik Aronesty
Ich habe eine kürzere Route ausgearbeitet, die automatisch bedeutungsvolle Fehler erzeugt, aber weitgehend dem gleichen Stil entspricht. Ich habe die ursprüngliche Idee hier zum Vergleich gelassen.
Jon Betts
Schade, dass Sie dieses CONST.Präfix noch brauchen . Auch in Situationen mit mehreren Modulen wird dies kompliziert.
Alfe
1
Ich denke, normalerweise möchten Sie Konstanten in dieser Situation sowieso in verwandte Bündel gruppieren (anstatt ein riesiges CONST-Objekt zu haben), also ist es wahrscheinlich keine so schlechte Sache.
Jon Betts
Warum ist diese Antwort immer noch so weit unten?! Die __slots__Lösung ist so elegant und effektiv. Nach allem, was ich gelesen habe, ist dies ungefähr so nah wie das Erstellen von Konstanten in Python. Vielen Dank. Und für alle Interessierten gibt es hier eine brillante und ausführliche Erklärung der __slots__Magie.
JohnGalt
34
Python hat keine Konstanten.
Die vielleicht einfachste Alternative besteht darin, eine Funktion dafür zu definieren:
def MY_CONSTANT():return42
MY_CONSTANT() hat jetzt alle Funktionen einer Konstanten (plus einige nervige Klammern).
Ich wollte nur diesen Vorschlag hinzufügen, aber zum Glück habe ich zu den Antworten mit niedriger Bewertung gescrollt. Ich hoffe, dass es weiter verbessert wird und ich stimme voll und ganz zu, dass es alle Funktionen einer Konstanten hat und sehr einfach und unkompliziert ist. Wenn ich mir die Menge an Boilerplate-Code in all den ausgeklügelten Lösungen anschaue, finde ich die Klammern relativ nervig.
Yaccob
1
Dies ist die einfachste Antwort, obwohl zu beachten ist, dass sie einen gewissen Overhead hat und Idioten nicht davon abhält, den Rückgabewert zu ändern. Es wird nur verhindern, dass der Code weiter unten die Quelle ändert
MrMesees
@ MrMesees Ändern des Rückgabewerts? Meinen Sie damit, die Quelle zu bearbeiten? Aber auch in C ++, wo Konstanten (wie constexpr) echte harte Konstanten sind, sind Sie nicht davor geschützt .
Ruslan
@Ruslan Ich meinte damit, dass Python, da es keinen Constexpr hat, die Bearbeitung des Werts nicht stoppen würde, nachdem es in einen äußeren Kontext zurückgegeben wurde. In diesem Beispiel wurde nichts unternommen, um den eingefrorenen Zustand zu erzwingen.
MrMesees
20
Zusätzlich zu den beiden wichtigsten Antworten (verwenden Sie einfach Variablen mit UPPERCASE-Namen oder verwenden Sie Eigenschaften, um die Werte schreibgeschützt zu machen) möchte ich erwähnen, dass es möglich ist, Metaklassen zu verwenden, um benannte Konstanten zu implementieren . Ich biete eine sehr einfache Lösung mit Metaklassen bei GitHub an, die hilfreich sein kann, wenn die Werte informativer über ihren Typ / Namen sein sollen:
>>>from named_constants importConstants>>>classColors(Constants):... black =0... red =1... white =15...>>> c =Colors.black
>>> c ==0True>>> c
Colors.black
>>> c.name()'black'>>>Colors(0)is c
True
Dies ist etwas fortgeschritteneres Python, aber immer noch sehr einfach zu bedienen und praktisch. (Das Modul verfügt über einige weitere Funktionen, einschließlich schreibgeschützter Konstanten, siehe README-Datei.)
Es gibt ähnliche Lösungen, die in verschiedenen Repositories im Umlauf sind, aber meines Wissens fehlt ihnen entweder eines der grundlegenden Merkmale, die ich von Konstanten erwarten würde (wie Konstante oder beliebiger Typ), oder es wurden esoterische Merkmale hinzugefügt machen sie weniger allgemein anwendbar. Aber YMMV, ich wäre dankbar für Feedback. :-)
Ich mag deine Implementierung auf GitHub. Ich war fast bereit, eine Basisklasse zu schreiben, die die Reverse-Lookup-Funktionalität implementierte, aber ich sehe, dass Sie das und mehr getan haben!
Kerr
Danke, @Kerr, es ist das erste Feedback, das ich bekommen habe und das mich glücklich gemacht hat. :-)
hans_meine
Genial. Ich habe das gerade ausprobiert. Schön, dies als Option zu haben. Obwohl ich mich noch nicht entschieden habe, ob mir der schreibgeschützte Aspekt wichtig genug ist, um ihn zu verwenden, anstatt ihn einfach zu tun def enum(**enums): return type('Enum', (), enums). Numbers = enum(ONE=1, TWO=2, THREE='three'), gemäß stackoverflow.com/a/1695250/199364 , Abschnitt "In früheren Versionen ..."
ToolmakerSteve
19
Eigenschaften sind eine Möglichkeit, Konstanten zu erstellen. Sie können dies tun, indem Sie eine Getter-Eigenschaft deklarieren, den Setter jedoch ignorieren. Zum Beispiel:
Unterbewertete Lösung. Ich habe dies gerade implementiert, nachdem ich diese Seite gefunden hatte (nicht diese Antwort) und bin zurückgekreist, um sie hinzuzufügen, wenn nicht bereits. Ich wollte die Nützlichkeit dieser Antwort unterstreichen.
Marc
18
Bearbeiten: Beispielcode für Python 3 hinzugefügt
Hinweis: Diese andere Antwort scheint eine viel vollständigere Implementierung zu bieten, die der folgenden ähnelt (mit mehr Funktionen).
Sie können ein namedtuple als Problemumgehung verwenden, um effektiv eine Konstante zu erstellen, die genauso funktioniert wie eine statische endgültige Variable in Java (eine Java- "Konstante"). Umgehungen sind irgendwie elegant. (Ein eleganterer Ansatz wäre, einfach die Python-Sprache zu verbessern - welche Art von Sprache können Sie neu definieren math.pi? - aber ich schweife ab.)
(Während ich dies schreibe, stelle ich eine andere Antwort auf diese Frage fest, die als namedtuple bezeichnet wird, aber ich werde hier fortfahren, da ich eine Syntax zeige, die den in Java erwarteten Erwartungen besser entspricht, da kein Name erstellt werden muss geben Sie als namedtuple zwingt Sie zu tun.)
Wenn Sie Ihrem Beispiel folgen, werden Sie sich daran erinnern, dass wir in Java die Konstante innerhalb einer Klasse definieren müssen . Da Sie keinen Klassennamen erwähnt haben, nennen wir ihn Foo. Hier ist die Java-Klasse:
public classFoo{
public static final String CONST_NAME ="Name";}
Hier ist das entsprechende Python.
from collections import namedtuple
Foo= namedtuple('_Foo','CONST_NAME')('Name')
Der wichtigste Punkt, den ich hier hinzufügen möchte, ist, dass Sie keinen separaten FooTyp benötigen (ein "anonymes benanntes Tupel" wäre nett, obwohl das wie ein Oxymoron klingt), also benennen wir unser benanntes Tupel, damit es _Foohoffentlich nicht funktioniert Escape zum Importieren von Modulen.
Der zweite Punkt hier ist, dass wir sofort eine Instanz des Nametupels erstellen und es aufrufen Foo; Es ist nicht erforderlich, dies in einem separaten Schritt zu tun (es sei denn, Sie möchten). Jetzt können Sie das tun, was Sie in Java tun können:
>>>Foo.CONST_NAME
'Name'
Aber Sie können es nicht zuordnen:
>>>Foo.CONST_NAME ='bar'…AttributeError: can't set attribute
Bestätigung: Ich dachte, ich hätte den Namedtuple-Ansatz erfunden, aber dann sehe ich, dass jemand anderes eine ähnliche (wenn auch weniger kompakte) Antwort gegeben hat. Dann bemerkte ich auch Was sind "benannte Tupel" in Python? , was darauf hinweist, dass sys.version_infoes sich nun um ein Namedtupel handelt, sodass die Python-Standardbibliothek diese Idee vielleicht schon viel früher hatte.
Beachten Sie, dass Sie leider (dies ist immer noch Python) die gesamte FooZuweisung insgesamt löschen können :
>>>Foo='bar'
(Gesichtspalme)
Aber zumindest verhindern wir, dass sich der Foo.CONST_NAMEWert ändert, und das ist besser als nichts. Viel Glück.
Hier ist eine Implementierung einer "Constants" -Klasse, die Instanzen mit schreibgeschützten (konstanten) Attributen erstellt. ZB kann verwendet werden Nums.PI, um einen Wert abzurufen, der als initialisiert wurde 3.14159, und Nums.PI = 22löst eine Ausnahme aus.
# ---------- Constants.py ----------classConstants(object):"""
Create objects with read-only (constant) attributes.
Example:
Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0)
print 10 + Nums.PI
print '----- Following line is deliberate ValueError -----'
Nums.PI = 22
"""def __init__(self,*args,**kwargs):
self._d = dict(*args,**kwargs)def __iter__(self):return iter(self._d)def __len__(self):return len(self._d)# NOTE: This is only called if self lacks the attribute.# So it does not interfere with get of 'self._d', etc.def __getattr__(self, name):return self._d[name]# ASSUMES '_..' attribute is OK to set. Need this to initialize 'self._d', etc.#If use as keys, they won't be constant.def __setattr__(self, name, value):if(name[0]=='_'):
super(Constants, self).__setattr__(name, value)else:raiseValueError("setattr while locked", self)if(__name__ =="__main__"):# Usage example.Nums=Constants(ONE=1, PI=3.14159,DefaultWidth=100.0)print10+Nums.PI
print'----- Following line is deliberate ValueError -----'Nums.PI =22
Dank @MikeGrahams FrozenDict , das ich als Ausgangspunkt verwendet habe. Geändert, also anstelle Nums['ONE']der Verwendungssyntax Nums.ONE.
Und dank der Antwort von @ Raufio für die Idee, __ setattr __ zu überschreiben.
Python ist eine Sprache, in der Erwachsene zustimmen. Es gibt keinen Schutz gegen so etwas. Nums._d['PI'] = 22 Ich glaube, die Sprache selbst bietet keine Möglichkeit, Dinge als nicht veränderlich zu kennzeichnen.
Ajay M
8
Ein Tupel qualifiziert sich technisch als Konstante, da ein Tupel einen Fehler auslöst, wenn Sie versuchen, einen seiner Werte zu ändern. Wenn Sie ein Tupel mit einem Wert deklarieren möchten, setzen Sie ein Komma nach dem einzigen Wert wie folgt:
my_tuple =(0"""Or any other value""",)
Verwenden Sie Folgendes, um den Wert dieser Variablen zu überprüfen:
if my_tuple[0]==0:#Code goes here
Wenn Sie versuchen, diesen Wert zu ändern, wird ein Fehler ausgegeben.
Ich würde eine Klasse erstellen, die die __setattr__Methode der Basisobjektklasse überschreibt, und meine Konstanten damit umschließen. Beachten Sie, dass ich Python 2.7 verwende:
class const(object):def __init__(self, val):
super(const, self).__setattr__("value", val)def __setattr__(self, name, val):raiseValueError("Trying to change a constant value", self)
So wickeln Sie eine Zeichenfolge ein:
>>> constObj = const("Try to change me")>>> constObj.value
'Try to change me'>>> constObj.value ="Changed"Traceback(most recent call last):...ValueError:Trying to change a constant value
>>> constObj2 = const(" or not")>>> mutableObj = constObj.value + constObj2.value
>>> mutableObj #just a string'Try to change me or not'
Es ist ziemlich einfach, aber wenn Sie Ihre Konstanten genauso verwenden möchten wie ein nicht konstantes Objekt (ohne constObj.value zu verwenden), ist es etwas intensiver. Es ist möglich, dass dies zu Problemen führen kann. .valueDaher ist es möglicherweise am besten, die Anzeige beizubehalten und zu wissen, dass Sie Operationen mit Konstanten ausführen (möglicherweise jedoch nicht die "pythonischste" Methode).
+1 für interessanten Ansatz. Obwohl nicht so sauber wie die Antworten, die bereits gegeben wurden. Und selbst die einfachste früher vorgeschlagene Lösung def ONE(): return 1ist einfacher zu verwenden ONE()als diese Antwort ONE.value.
ToolmakerSteve
7
Leider hat der Python noch keine Konstanten und es ist eine Schande. ES6 hat JavaScript bereits Unterstützungskonstanten hinzugefügt ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/const ), da dies in jeder Programmiersprache sehr nützlich ist. Wie in anderen Antworten in der Python-Community beantwortet, verwenden Sie die Konvention - Benutzer-Großbuchstabenvariable als Konstanten, sie schützt jedoch nicht vor willkürlichen Fehlern im Code. Wenn Sie möchten, kann es sein, dass Sie als Nächstes eine Einzeldateilösung als nützlich erachten (siehe Dokumentation zu deren Verwendung).
Datei constants.py
import collections
__all__ =('const',)classConstant(object):"""
Implementation strict constants in Python 3.
A constant can be set up, but can not be changed or deleted.
Value of constant may any immutable type, as well as list or set.
Besides if value of a constant is list or set, it will be converted in an immutable type as next:
list -> tuple
set -> frozenset
Dict as value of a constant has no support.
>>> const = Constant()
>>> del const.temp
Traceback (most recent call last):
NameError: name 'temp' is not defined
>>> const.temp = 1
>>> const.temp = 88
Traceback (most recent call last):
...
TypeError: Constanst can not be changed
>>> del const.temp
Traceback (most recent call last):
...
TypeError: Constanst can not be deleted
>>> const.I = ['a', 1, 1.2]
>>> print(const.I)
('a', 1, 1.2)
>>> const.F = {1.2}
>>> print(const.F)
frozenset([1.2])
>>> const.D = dict()
Traceback (most recent call last):
...
TypeError: dict can not be used as constant
>>> del const.UNDEFINED
Traceback (most recent call last):
...
NameError: name 'UNDEFINED' is not defined
>>> const()
{'I': ('a', 1, 1.2), 'temp': 1, 'F': frozenset([1.2])}
"""def __setattr__(self, name, value):"""Declaration a constant with value. If mutable - it will be converted to immutable, if possible.
If the constant already exists, then made prevent againt change it."""if name in self.__dict__:raiseTypeError('Constanst can not be changed')ifnot isinstance(value, collections.Hashable):if isinstance(value, list):
value = tuple(value)elif isinstance(value, set):
value = frozenset(value)elif isinstance(value, dict):raiseTypeError('dict can not be used as constant')else:raiseValueError('Muttable or custom type is not supported')
self.__dict__[name]= value
def __delattr__(self, name):"""Deny against deleting a declared constant."""if name in self.__dict__:raiseTypeError('Constanst can not be deleted')raiseNameError("name '%s' is not defined"% name)def __call__(self):"""Return all constans."""return self.__dict__
const =Constant()if __name__ =='__main__':import doctest
doctest.testmod()
Wenn dies nicht ausreicht, lesen Sie den vollständigen Testfall.
import decimal
import uuid
import datetime
import unittest
from..constants importConstantclassTestConstant(unittest.TestCase):"""
Test for implementation constants in the Python
"""def setUp(self):
self.const =Constant()def tearDown(self):del self.const
def test_create_constant_with_different_variants_of_name(self):
self.const.CONSTANT =1
self.assertEqual(self.const.CONSTANT,1)
self.const.Constant=2
self.assertEqual(self.const.Constant,2)
self.const.ConStAnT=3
self.assertEqual(self.const.ConStAnT,3)
self.const.constant =4
self.assertEqual(self.const.constant,4)
self.const.co_ns_ta_nt =5
self.assertEqual(self.const.co_ns_ta_nt,5)
self.const.constant1111 =6
self.assertEqual(self.const.constant1111,6)def test_create_and_change_integer_constant(self):
self.const.INT =1234
self.assertEqual(self.const.INT,1234)with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.INT =.211def test_create_and_change_float_constant(self):
self.const.FLOAT =.1234
self.assertEqual(self.const.FLOAT,.1234)with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.FLOAT =.211def test_create_and_change_list_constant_but_saved_as_tuple(self):
self.const.LIST =[1,.2,None,True, datetime.date.today(),[],{}]
self.assertEqual(self.const.LIST,(1,.2,None,True, datetime.date.today(),[],{}))
self.assertTrue(isinstance(self.const.LIST, tuple))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.LIST =.211def test_create_and_change_none_constant(self):
self.const.NONE =None
self.assertEqual(self.const.NONE,None)with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.NONE =.211def test_create_and_change_boolean_constant(self):
self.const.BOOLEAN =True
self.assertEqual(self.const.BOOLEAN,True)with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.BOOLEAN =Falsedef test_create_and_change_string_constant(self):
self.const.STRING ="Text"
self.assertEqual(self.const.STRING,"Text")with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.STRING +='...'with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.STRING ='TEst1'def test_create_dict_constant(self):with self.assertRaisesRegexp(TypeError,'dict can not be used as constant'):
self.const.DICT ={}def test_create_and_change_tuple_constant(self):
self.const.TUPLE =(1,.2,None,True, datetime.date.today(),[],{})
self.assertEqual(self.const.TUPLE,(1,.2,None,True, datetime.date.today(),[],{}))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.TUPLE ='TEst1'def test_create_and_change_set_constant(self):
self.const.SET ={1,.2,None,True, datetime.date.today()}
self.assertEqual(self.const.SET,{1,.2,None,True, datetime.date.today()})
self.assertTrue(isinstance(self.const.SET, frozenset))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.SET =3212def test_create_and_change_frozenset_constant(self):
self.const.FROZENSET = frozenset({1,.2,None,True, datetime.date.today()})
self.assertEqual(self.const.FROZENSET, frozenset({1,.2,None,True, datetime.date.today()}))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.FROZENSET =Truedef test_create_and_change_date_constant(self):
self.const.DATE = datetime.date(1111,11,11)
self.assertEqual(self.const.DATE, datetime.date(1111,11,11))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.DATE =Truedef test_create_and_change_datetime_constant(self):
self.const.DATETIME = datetime.datetime(2000,10,10,10,10)
self.assertEqual(self.const.DATETIME, datetime.datetime(2000,10,10,10,10))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.DATETIME =Nonedef test_create_and_change_decimal_constant(self):
self.const.DECIMAL = decimal.Decimal(13123.12312312321)
self.assertEqual(self.const.DECIMAL, decimal.Decimal(13123.12312312321))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.DECIMAL =Nonedef test_create_and_change_timedelta_constant(self):
self.const.TIMEDELTA = datetime.timedelta(days=45)
self.assertEqual(self.const.TIMEDELTA, datetime.timedelta(days=45))with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.TIMEDELTA =1def test_create_and_change_uuid_constant(self):
value = uuid.uuid4()
self.const.UUID = value
self.assertEqual(self.const.UUID, value)with self.assertRaisesRegexp(TypeError,'Constanst can not be changed'):
self.const.UUID =[]def test_try_delete_defined_const(self):
self.const.VERSION ='0.0.1'with self.assertRaisesRegexp(TypeError,'Constanst can not be deleted'):del self.const.VERSION
def test_try_delete_undefined_const(self):with self.assertRaisesRegexp(NameError,"name 'UNDEFINED' is not defined"):del self.const.UNDEFINED
def test_get_all_defined_constants(self):
self.assertDictEqual(self.const(),{})
self.const.A =1
self.assertDictEqual(self.const(),{'A':1})
self.const.B ="Text"
self.assertDictEqual(self.const(),{'A':1,'B':"Text"})
Vorteile: 1. Zugriff auf alle Konstanten für das gesamte Projekt 2. Strikte Kontrolle der Werte von Konstanten
Fehlt: 1. Keine Unterstützung für benutzerdefinierte Typen und den Typ 'Dikt'
Anmerkungen:
Getestet mit Python3.4 und Python3.5 (ich benutze das 'Tox' dafür)
Testumgebung:
.
$ uname -a
Linux wlysenko-Aspire3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Sie können dies leicht verbessern, indem Sie Wörterbücher automatisch in benannte Tupel konvertieren
Peter Schorn
6
Die pythonische Art, "Konstanten" zu deklarieren, ist im Grunde eine Variable auf Modulebene:
RED =1
GREEN =2
BLUE =3
Und dann schreiben Sie Ihre Klassen oder Funktionen. Da Konstanten fast immer ganze Zahlen sind und auch in Python unveränderlich sind, haben Sie nur eine sehr geringe Chance, sie zu ändern.
Es sei denn natürlich, wenn Sie explizit festlegen RED = 2.
Ja aber Blockieren der Fähigkeit zum "expliziten Setzen RED = 2" ist der gesamte Vorteil (in anderen Sprachen), einen Variablennamen als "konstant" deklarieren zu können!
ToolmakerSteve
6
Würden Sie davon profitieren, wenn Sie das blockieren? Das Nützlichste an const sind normalerweise Compiler-Optimierungen, was in Python eigentlich nicht der Fall ist. Willst du, dass etwas konstant ist? Ändere es einfach nicht. Wenn Sie sich Sorgen machen, dass jemand anderes es ändert, können Sie es einfach außerhalb seines Anwendungsbereichs platzieren oder einfach erkennen, dass, wenn jemand es ändert, dies sein Problem ist und er sich damit befassen muss, nicht Sie.
Kevin
@ Kevin: " Würde davon profitieren, würdest du ... ", der Vorteil vonstatic , einen einzigen Speicher für den Wert für alle Instanzen einer Klasse zu haben? Es sei denn, es besteht tatsächlich die Möglichkeit, eine statische / Klassenvariable zu deklarieren.
Minuten
8
Das Hauptproblem ist, dass einige es als einen Wert betrachten, der eine Quelle der Wahrheit ist, der nicht geändert werden kann, und ihn als Quelle der Wahrheit in ihrem gesamten Code verwenden, anstatt magische Werte einzuführen (von denen ich in Python viel sehe). - und andere sehen es vielleicht als etwas, das sie nach Belieben ändern dürfen. Wenn jemand eine globale Variable ändert und Sie nicht sagen können, wo sie geändert wurde, und die Anwendung abstürzt, weil ROT = "blau" statt "rot", führen Sie ein völlig unnötiges Problem ein, das bereits so einfach und gelöst wurde wird allgemein verstanden.
Dagrooms
5
Wir können ein Deskriptorobjekt erstellen.
classConstant:def __init__(self,value=None):
self.value = value
def __get__(self,instance,owner):return self.value
def __set__(self,instance,value):raiseValueError("You can't change a constant")
1) Wenn wir mit Konstanten auf Instanzebene arbeiten wollten, dann:
class A:
NULL =Constant()
NUM =Constant(0xFF)class B:
NAME =Constant('bar')
LISTA =Constant([0,1,'INFINITY'])>>> obj=A()>>>print(obj.NUM)#=> 255>>> obj.NUM =100Traceback(most recent call last):File"<stdin>", line 1,in<module>ValueError:You can't change a constant
2) Wenn wir Konstanten nur auf Klassenebene erstellen möchten, können wir eine Metaklasse verwenden, die als Container für unsere Konstanten (unsere Deskriptorobjekte) dient. Alle Klassen, die absteigen, erben unsere Konstanten (unsere Deskriptorobjekte) ohne das Risiko, dass sie geändert werden können.
# metaclass of my class FooclassFooMeta(type):pass# class FooclassFoo(metaclass=FooMeta):pass# I create constants in my metaclassFooMeta.NUM =Constant(0xff)FooMeta.NAME =Constant('FOO')>>>Foo.NUM #=> 255>>>Foo.NAME #=> 'FOO'>>>Foo.NUM =0#=> ValueError: You can't change a constant
Wenn ich eine Unterklasse von Foo erstelle, erbt diese Klasse die Konstante, ohne dass die Möglichkeit besteht, sie zu ändern
classBar(Foo):pass>>>Bar.NUM #=> 255>>>Bar.NUM =0#=> ValueError: You can't change a constant
In Python ist eine Konstante einfach eine Variable mit einem Namen in allen Großbuchstaben, wobei die Wörter durch den Unterstrich getrennt sind.
z.B
DAYS_IN_WEEK = 7
Der Wert ist veränderbar, da Sie ihn ändern können. Aber angesichts der Regeln für den Namen, die Ihnen sagen, dass es sich um eine Konstante handelt, warum sollten Sie das tun? Ich meine, es ist doch dein Programm!
Dies ist der Ansatz, der in Python verfolgt wird. Aus privatedemselben Grund gibt es kein Schlüsselwort. Stellen Sie dem Namen einen Unterstrich voran, und Sie wissen, dass er privat sein soll. Code kann gegen die Regel verstoßen ... genau wie ein Programmierer das private Schlüsselwort sowieso entfernen könnte.
Python hätte ein constSchlüsselwort hinzufügen können ... aber ein Programmierer könnte das Schlüsselwort entfernen und dann die Konstante ändern, wenn er möchte, aber warum? Wenn Sie die Regel brechen möchten, können Sie die Regel trotzdem ändern. Aber warum sollte man sich die Mühe machen, die Regel zu brechen, wenn der Name die Absicht klar macht?
Vielleicht gibt es einen Unit-Test, bei dem es sinnvoll ist, eine Wertänderung vorzunehmen? Um zu sehen, was für eine 8-Tage-Woche passiert, obwohl in der realen Welt die Anzahl der Tage in der Woche nicht geändert werden kann. Wenn die Sprache Sie daran gehindert hat, eine Ausnahme zu machen, wenn es nur diesen einen Fall gibt, müssen Sie die Regel brechen ... Sie müssten dann aufhören, sie als Konstante zu deklarieren, obwohl sie in der Anwendung immer noch eine Konstante ist, und es gibt sie Nur dieser eine Testfall zeigt, was passiert, wenn er geändert wird.
Der Name in Großbuchstaben gibt an, dass es sich um eine Konstante handeln soll. Das ist wichtig. Keine Sprache, die Einschränkungen für Code erzwingt, die Sie ohnehin ändern können.
Es gibt keinen perfekten Weg, dies zu tun. So wie ich es verstehe, werden die meisten Programmierer nur den Bezeichner großschreiben, so dass PI = 3.142 leicht als Konstante verstanden werden kann.
Wenn Sie andererseits etwas wollen, das sich tatsächlich wie eine Konstante verhält, bin ich mir nicht sicher, ob Sie es finden werden. Bei allem, was Sie tun, gibt es immer eine Möglichkeit, die "Konstante" zu bearbeiten, sodass sie nicht wirklich eine Konstante ist. Hier ist ein sehr einfaches, schmutziges Beispiel:
In Wirklichkeit braucht jemand nur Folgendes, um den Wert zu ändern:
globals()["PI"+str(id("PI"))]=3.1415
Dies gilt auch für alle anderen Lösungen, die Sie hier finden - selbst für die cleveren, die eine Klasse bilden und die Set-Attribut-Methode neu definieren -, es wird immer einen Weg geben, sie zu umgehen. So ist Python eben.
Meine Empfehlung ist, einfach den ganzen Ärger zu vermeiden und nur Ihre Identifikatoren groß zu schreiben. Es wäre nicht wirklich eine richtige Konstante, aber nichts würde es tun.
Beachten Sie für alle, die dies lesen, bitte, dass jeder seinen internen Wert ändern kann, wenn Sie ein veränderliches Objekt als eine dieser Konstanten festlegen. Wenn Sie beispielsweise bar = [1, 2, 3] verwenden, können Sie wie folgt vorgehen: CONSTS.bar [1] = 'a' und es wird nicht abgelehnt. Also sei vorsichtig damit.
Juan Ignacio Sánchez
Anstelle dieser hackigen Methode, die ich nur zum Spaß gemacht habe, empfehle ich, stattdessen Pythons Eigenschaftsdekorator zu verwenden.
Juan Ignacio Sánchez
4
Vielleicht hilft dir die pconst Bibliothek ( github ).
$ pip install pconst
from pconst import const
const.APPLE_PRICE =100
const.APPLE_PRICE =200
[Out] Constant value of "APPLE_PRICE" is not editable.
(Dieser Absatz sollte einen Kommentar zu den hier und da erwähnten Antworten sein , die erwähnt wurden namedtuple, aber es wird zu lang, um in einen Kommentar zu passen, also geht es los.)
Der oben erwähnte Namedtuple-Ansatz ist definitiv innovativ. Der Vollständigkeit halber heißt es jedoch am Ende des NamedTuple-Abschnitts seiner offiziellen Dokumentation :
Aufzählungskonstanten können mit benannten Tupeln implementiert werden, aber es ist einfacher und effizienter, eine einfache Klassendeklaration zu verwenden:
classStatus:
open, pending, closed = range(3)
Mit anderen Worten, die offizielle Dokumentation bevorzugt eine praktische Methode, anstatt das schreibgeschützte Verhalten tatsächlich zu implementieren. Ich denke, es wird ein weiteres Beispiel dafür Zen of Python :
Hier ist eine Sammlung von Redewendungen, die ich erstellt habe, um einige der bereits verfügbaren Antworten zu verbessern.
Ich weiß, dass die Verwendung von Konstanten nicht pythonisch ist, und Sie sollten dies nicht zu Hause tun!
Python ist jedoch eine so dynamische Sprache! Dieses Forum zeigt, wie es möglich ist, Konstrukte zu erstellen, die wie Konstanten aussehen und sich anfühlen. Diese Antwort hat in erster Linie den Zweck zu untersuchen, was durch die Sprache ausgedrückt werden kann.
In diesem Beitrag werde ich eine konstante Variable auf eine konstante Referenz auf Werte (unveränderlich oder anderweitig) aufrufen. Außerdem sage ich, dass eine Variable einen eingefrorenen Wert hat, wenn sie auf ein veränderliches Objekt verweist, dessen Wert ein Client-Code nicht aktualisieren kann.
Ein Raum von Konstanten (SpaceConstants)
Diese Redewendung erstellt einen Namespace konstanter Variablen (auch bekannt als SpaceConstants). Es ist eine Modifikation eines Code-Snippets von Alex Martelli , um die Verwendung von Modulobjekten zu vermeiden. Diese Modifikation verwendet insbesondere eine sogenannte Klassenfactory, da innerhalb der SpaceConstants- Funktion eine Klasse namens SpaceConstants verwendet wird definiert und eine Instanz davon zurückgegeben wird.
Ein Leerzeichen mit eingefrorenen Werten (SpaceFrozenValues)
Diese nächste Redewendung ist eine Modifikation der SpaceConstants, in denen referenzierbare veränderbare Objekte eingefroren sind. Diese Implementierung nutzt das, was ich als Shared Closure zwischen setattr- und getattr- Funktionen bezeichne. Der Wert des veränderlichen Objekts wird kopiert und von der Variablen- Cache- Definition innerhalb des gemeinsam genutzten Funktionsabschlusses referenziert . Es bildet eine so genannte schließungsgeschützte Kopie eines veränderlichen Objekts .
Sie müssen bei der Verwendung dieser Redewendung vorsichtig sein, da getattr den Wert des Caches durch eine tiefe Kopie zurückgibt . Dieser Vorgang kann erhebliche Auswirkungen auf die Leistung großer Objekte haben!
from copy import deepcopy
defSpaceFrozenValues():
cache ={}def setattr(self, name, value):nonlocal cache
if name in cache:raiseAttributeError("Cannot reassign members")
cache[name]= deepcopy(value)def getattr(self, name):nonlocal cache
if name notin cache:raiseAttributeError("Object has no attribute '{}'".format(name))return deepcopy(cache[name])
cls = type('SpaceFrozenValues',(),{'__getattr__': getattr,'__setattr__': setattr
})return cls()
fv =SpaceFrozenValues()print(fv.x)# AttributeError: Object has no attribute 'x'
fv.x =2# bind attribute xprint(fv.x)# print "2"
fv.x =3# raise "AttributeError: Cannot reassign members"
fv.y ={'name':'y','value':2}# bind attribute yprint(fv.y)# print "{'name': 'y', 'value': 2}"
fv.y['name']='yprime'# you can try to change mutable objectsprint(fv.y)# print "{'name': 'y', 'value': 2}"
fv.y ={}# raise "AttributeError: Cannot reassign members"
Ein konstanter Raum (ConstantSpace)
Diese Redewendung ist ein unveränderlicher Namespace von konstanten Variablen oder ConstantSpace . Es ist eine Kombination aus einer unglaublich einfachen Antwort von Jon Betts im Stackoverflow mit einer Klassenfabrik .
defConstantSpace(**args):
args['__slots__']=()
cls = type('ConstantSpace',(), args)return cls()
cs =ConstantSpace(
x =2,
y ={'name':'y','value':2})print(cs.x)# print "2"
cs.x =3# raise "AttributeError: 'ConstantSpace' object attribute 'x' is read-only"print(cs.y)# print "{'name': 'y', 'value': 2}"
cs.y['name']='yprime'# mutable object can be changedprint(cs.y)# print "{'name': 'yprime', 'value': 2}"
cs.y ={}# raise "AttributeError: 'ConstantSpace' object attribute 'x' is read-only"
cs.z =3# raise "AttributeError: 'ConstantSpace' object has no attribute 'z'"
Ein gefrorener Raum (FrozenSpace)
Diese Redewendung ist ein unveränderlicher Namespace von eingefrorenen Variablen oder FrozenSpace . Es wird aus dem vorherigen Muster abgeleitet, indem jede Variable durch Schließen der generierten FrozenSpace- Klasse zu einer geschützten Eigenschaft gemacht wird .
from copy import deepcopy
defFreezeProperty(value):
cache = deepcopy(value)return property(lambda self: deepcopy(cache))defFrozenSpace(**args):
args ={k:FreezeProperty(v)for k, v in args.items()}
args['__slots__']=()
cls = type('FrozenSpace',(), args)return cls()
fs =FrozenSpace(
x =2,
y ={'name':'y','value':2})print(fs.x)# print "2"
fs.x =3# raise "AttributeError: 'FrozenSpace' object attribute 'x' is read-only"print(fs.y)# print "{'name': 'y', 'value': 2}"
fs.y['name']='yprime'# try to change mutable objectprint(fs.y)# print "{'name': 'y', 'value': 2}"
fs.y ={}# raise "AttributeError: 'FrozenSpace' object attribute 'x' is read-only"
fs.z =3# raise "AttributeError: 'FrozenSpace' object has no attribute 'z'"
In Python sind Konstanten nicht vorhanden. Sie können jedoch angeben, dass eine Variable eine Konstante ist und nicht geändert werden darf, indem Sie CONST_am Anfang des Variablennamens hinzufügen und in einem Kommentar angeben, dass es sich um eine Konstante handelt:
myVariable =0
CONST_daysInWeek =7# This is a constant - do not change its value.
CONSTANT_daysInMonth =30# This is also a constant - do not change this value.
Alternativ können Sie eine Funktion erstellen, die sich wie eine Konstante verhält:
In meinem Fall benötigte ich unveränderliche Bytearrays für die Implementierung einer Kryptobibliothek mit vielen Literalzahlen, die ich sicherstellen wollte, dass sie konstant sind.
Diese Antwort funktioniert, aber die versuchte Neuzuweisung von Bytearray-Elementen führt nicht zu einem Fehler.
def const(func):'''implement const decorator'''def fset(self, val):'''attempting to set a const raises `ConstError`'''classConstError(TypeError):'''special exception for const reassignment'''passraiseConstErrordef fget(self):'''get a const'''return func()return property(fget, fset)classConsts(object):'''contain all constants'''@constdef C1():'''reassignment to C1 fails silently'''return bytearray.fromhex('deadbeef')@constdef pi():'''is immutable'''return3.141592653589793
Konstanten sind unveränderlich, aber die konstante Bytearray-Zuweisung schlägt lautlos fehl:
>>> c =Consts()>>> c.pi =6.283185307179586# (https://en.wikipedia.org/wiki/Tau_(2%CF%80))Traceback(most recent call last):File"<stdin>", line 1,in<module>File"consts.py", line 9,in fset
raiseConstError
__main__.ConstError>>> c.C1[0]=0>>> c.C1[0]222>>> c.C1
bytearray(b'\xde\xad\xbe\xef')
Ein leistungsfähigerer, einfacher und vielleicht sogar "pythonischer" Ansatz beinhaltet die Verwendung von Memoryview-Objekten (Pufferobjekte in <= python-2.6).
import sys
PY_VER = sys.version.split()[0].split('.')if int(PY_VER[0])==2:if int(PY_VER[1])<6:raiseNotImplementedErrorelif int(PY_VER[1])==6:
memoryview = buffer
classConstArray(object):'''represent a constant bytearray'''def __init__(self, init):'''
create a hidden bytearray and expose a memoryview of that bytearray for
read-only use
'''if int(PY_VER[1])==6:
self.__array = bytearray(init.decode('hex'))else:
self.__array = bytearray.fromhex(init)
self.array = memoryview(self.__array)def __str__(self):return str(self.__array)def __getitem__(self,*args,**kwargs):return self.array.__getitem__(*args,**kwargs)
Die Zuordnung von ConstArray-Elementen ist TypeError:
>>> C1 =ConstArray('deadbeef')>>> C1[0]=0Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError:'ConstArray' object does not support item assignment
>>> C1[0]222
Ich schreibe eine util lib für python const:
kkconst - pypi
support str, int, float, datetime
Die const-Feldinstanz behält ihr Basistypverhalten bei.
Zum Beispiel:
from __future__ import print_function
from kkconst import(BaseConst,ConstFloatField,)classMathConst(BaseConst):
PI =ConstFloatField(3.1415926, verbose_name=u"Pi")
E =ConstFloatField(2.7182818284, verbose_name=u"mathematical constant")# Euler's number"
GOLDEN_RATIO =ConstFloatField(0.6180339887, verbose_name=u"Golden Ratio")
magic_num =MathConst.GOLDEN_RATIO
assert isinstance(magic_num,ConstFloatField)assert isinstance(magic_num, float)print(magic_num)# 0.6180339887print(magic_num.verbose_name)# Golden Ratio
Weitere Details Verwendung Sie können die Pypi-URL lesen:
Pypi oder Github
Sie können eine Konstante in ein Numpy-Array einschließen, sie nur als Schreibzugriff kennzeichnen und sie immer mit dem Index Null aufrufen.
import numpy as np
# declare a constant
CONSTANT ='hello'# put constant in numpy and make read only
CONSTANT = np.array([CONSTANT])
CONSTANT.flags.writeable =False# alternatively: CONSTANT.setflags(write=0)# call our constant using 0 index print'CONSTANT %s'% CONSTANT[0]# attempt to modify our constant with try/except
new_value ='goodbye'try:
CONSTANT[0]= new_value
except:print"cannot change CONSTANT to '%s' it's value '%s' is immutable"%(
new_value, CONSTANT[0])# attempt to modify our constant producing ValueError
CONSTANT[0]= new_value
>>>
CONSTANT hello
cannot change CONSTANT to 'goodbye' it's value 'hello' is immutable
Traceback (most recent call last):
File "shuffle_test.py", line 15, in <module>
CONSTANT[0] = new_value
ValueError: assignment destination is read-only
Dies schützt natürlich nur den Inhalt des Numpys, nicht die Variable "CONSTANT" selbst; Sie können immer noch tun:
CONSTANT ='foo'
und CONSTANTwürde sich ändern, aber das würde schnell einen TypeError auslösen, wenn das erste Mal CONSTANT[0]später im Skript aufgerufen wird.
obwohl ... ich nehme an, wenn du es irgendwann geändert hast
CONSTANT =[1,2,3]
Jetzt würden Sie den TypeError nicht mehr bekommen. hmmmm ....
True=False
und(2+2==4)==True
kehren dann zurückFalse
.SyntaxError: can't assign to keyword
. Dies scheint eine gute Sache zu sein.Antworten:
Nein, da ist kein. Sie können eine Variable oder einen Wert in Python nicht als Konstante deklarieren. Ändere es einfach nicht.
Wenn Sie in einer Klasse sind, wäre das Äquivalent:
wenn nicht, ist es einfach
Vielleicht möchten Sie sich aber das Code-Snippet Constants in Python von Alex Martelli ansehen .
Ab Python 3.8 gibt es eine
typing.Final
Variablenanmerkung, die statischen Typprüfern (wie mypy) mitteilt, dass Ihre Variable nicht neu zugewiesen werden sollte. Dies ist das nächste Äquivalent zu Javafinal
. Eine Neuzuweisung wird jedoch nicht verhindert :quelle
def MY_CONST_VALUE(): return 123
name.attribute
und können einen beliebigen Wert enthalten. Die Deklaration ist einfachNums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0)
, die Verwendung ist unkompliziertprint 10 + Nums.PI
. Versuchen Sie, die Ergebnisse in AusnahmeNums.PI = 22
=> ValueError (..) zu ändern .Es gibt kein
const
Schlüsselwort wie in anderen Sprachen, es ist jedoch möglich, eine Eigenschaft zu erstellen, die eine "Getter-Funktion" zum Lesen der Daten hat, aber keine "Setter-Funktion" zum erneuten Schreiben der Daten. Dies schützt die Kennung im Wesentlichen vor Änderungen.Hier ist eine alternative Implementierung unter Verwendung der Klasseneigenschaft:
Beachten Sie, dass der Code für einen Leser, der sich über Konstanten wundert, alles andere als einfach ist. Siehe Erklärung unten
Code Erläuterung:
constant
, die einen Ausdruck nimmt und daraus einen "Getter" erstellt - eine Funktion, die ausschließlich den Wert des Ausdrucks zurückgibt.constant
soeben erstellte Funktion als Dekoration, um schnell schreibgeschützte Eigenschaften zu definieren.Und auf eine andere altmodischere Weise:
(Der Code ist ziemlich knifflig, weitere Erklärungen unten)
Beachten Sie, dass der @ applly-Dekorator veraltet zu sein scheint.
property
Funktion, um ein Objekt zu erstellen, das "gesetzt" oder "get" werden kann.property
ersten beiden Parameter der Funktion mitfset
und benannt sindfget
.property
Funktion zu übergebenquelle
AttributeError
undTypeError
denke ich, dass die ausgelöste Ausnahme ein neuer Fehler sein sollte, den ich benenne,ConstantError
oder so ähnlich, der eine Unterklasse von istTypeError
. Der Abschnitt in den Dokumenten, der mich denken lässt, dass: docs.python.org/2/library/exceptions.htmlCONST.__dict__['FOO'] = 7
In Python verwenden Benutzer anstelle von etwas, das die Sprache erzwingt, Namenskonventionen, z. B.
__method
für private Methoden und_method
für geschützte Methoden.Auf die gleiche Weise können Sie die Konstante einfach als alle Kappen deklarieren, z
Wenn Sie möchten, dass sich diese Konstante nie ändert, können Sie sich in den Attributzugriff einbinden und Tricks ausführen. Ein einfacherer Ansatz besteht jedoch darin, eine Funktion zu deklarieren
Das einzige Problem ist, dass Sie überall MY_CONSTANT () ausführen müssen, aber auch dies
MY_CONSTANT = "one"
ist (normalerweise) der richtige Weg in Python.Sie können namedtuple auch verwenden , um Konstanten zu erstellen:
quelle
def MY_CONSTANT(): return "one"
wird jemand später im Code nicht daran gehindert, etwas zu tunMY_CONSTANT = "two"
(oder die Funktion neu zu deklarieren).MY_CONSTANT = MY_CONSTANT()
, sondernMY_CONSTANT()
als Konstante zu verwenden. Natürlich das. Dies ist jedoch in Ordnung und entspricht weitgehend dem Python-Prinzip "Wir sind alle Erwachsene hier" - dh es wird dem Entwickler selten verboten , eine Regel zu überschreiben, wenn er gute Gründe hat und weiß, was er tut.Ich habe kürzlich ein sehr kurzes Update gefunden, das automatisch aussagekräftige Fehlermeldungen auslöst und den Zugriff über Folgendes verhindert
__dict__
:Wir definieren uns selbst als Instanz und verwenden dann Slots, um sicherzustellen, dass keine zusätzlichen Attribute hinzugefügt werden können. Dadurch wird auch der
__dict__
Zugangsweg entfernt . Natürlich kann das gesamte Objekt immer noch neu definiert werden.Bearbeiten - Ursprüngliche Lösung
Ich vermisse hier wahrscheinlich einen Trick, aber das scheint für mich zu funktionieren:
Durch das Erstellen der Instanz kann die magische
__setattr__
Methode Versuche zum Festlegen derFOO
Variablen starten und abfangen . Sie könnten hier eine Ausnahme auslösen, wenn Sie möchten. Das Instanziieren der Instanz über den Klassennamen verhindert den direkten Zugriff über die Klasse.Es ist ein totaler Schmerz für einen Wert, aber Sie könnten viel an Ihr
CONST
Objekt anhängen . Mit einer Oberschicht scheint der Klassenname auch ein bisschen grottig zu sein, aber ich denke, dass er insgesamt ziemlich prägnant ist.quelle
CONST.
Präfix noch brauchen . Auch in Situationen mit mehreren Modulen wird dies kompliziert.__slots__
Lösung ist so elegant und effektiv. Nach allem, was ich gelesen habe, ist dies ungefähr so nah wie das Erstellen von Konstanten in Python. Vielen Dank. Und für alle Interessierten gibt es hier eine brillante und ausführliche Erklärung der__slots__
Magie.Python hat keine Konstanten.
Die vielleicht einfachste Alternative besteht darin, eine Funktion dafür zu definieren:
MY_CONSTANT()
hat jetzt alle Funktionen einer Konstanten (plus einige nervige Klammern).quelle
constexpr
) echte harte Konstanten sind, sind Sie nicht davor geschützt .Zusätzlich zu den beiden wichtigsten Antworten (verwenden Sie einfach Variablen mit UPPERCASE-Namen oder verwenden Sie Eigenschaften, um die Werte schreibgeschützt zu machen) möchte ich erwähnen, dass es möglich ist, Metaklassen zu verwenden, um benannte Konstanten zu implementieren . Ich biete eine sehr einfache Lösung mit Metaklassen bei GitHub an, die hilfreich sein kann, wenn die Werte informativer über ihren Typ / Namen sein sollen:
Dies ist etwas fortgeschritteneres Python, aber immer noch sehr einfach zu bedienen und praktisch. (Das Modul verfügt über einige weitere Funktionen, einschließlich schreibgeschützter Konstanten, siehe README-Datei.)
Es gibt ähnliche Lösungen, die in verschiedenen Repositories im Umlauf sind, aber meines Wissens fehlt ihnen entweder eines der grundlegenden Merkmale, die ich von Konstanten erwarten würde (wie Konstante oder beliebiger Typ), oder es wurden esoterische Merkmale hinzugefügt machen sie weniger allgemein anwendbar. Aber YMMV, ich wäre dankbar für Feedback. :-)
quelle
def enum(**enums): return type('Enum', (), enums)
.Numbers = enum(ONE=1, TWO=2, THREE='three')
, gemäß stackoverflow.com/a/1695250/199364 , Abschnitt "In früheren Versionen ..."Eigenschaften sind eine Möglichkeit, Konstanten zu erstellen. Sie können dies tun, indem Sie eine Getter-Eigenschaft deklarieren, den Setter jedoch ignorieren. Zum Beispiel:
In einem Artikel, den ich geschrieben habe , finden Sie weitere Möglichkeiten zur Verwendung von Python-Eigenschaften.
quelle
Bearbeiten: Beispielcode für Python 3 hinzugefügt
Hinweis: Diese andere Antwort scheint eine viel vollständigere Implementierung zu bieten, die der folgenden ähnelt (mit mehr Funktionen).
Erstellen Sie zunächst eine Metaklasse :
Dadurch wird verhindert, dass statische Eigenschaften geändert werden. Erstellen Sie dann eine andere Klasse, die diese Metaklasse verwendet:
Oder wenn Sie Python 3 verwenden:
Dies sollte verhindern, dass Instanz-Requisiten geändert werden. Um es zu verwenden, erben Sie:
Jetzt sollten die Requisiten, auf die direkt oder über eine Instanz zugegriffen wird, konstant sein:
Hier ist ein Beispiel von oben in Aktion. Hier ist ein weiteres Beispiel für Python 3.
quelle
Sie können ein namedtuple als Problemumgehung verwenden, um effektiv eine Konstante zu erstellen, die genauso funktioniert wie eine statische endgültige Variable in Java (eine Java- "Konstante"). Umgehungen sind irgendwie elegant. (Ein eleganterer Ansatz wäre, einfach die Python-Sprache zu verbessern - welche Art von Sprache können Sie neu definieren
math.pi
? - aber ich schweife ab.)(Während ich dies schreibe, stelle ich eine andere Antwort auf diese Frage fest, die als namedtuple bezeichnet wird, aber ich werde hier fortfahren, da ich eine Syntax zeige, die den in Java erwarteten Erwartungen besser entspricht, da kein Name erstellt werden muss geben Sie als namedtuple zwingt Sie zu tun.)
Wenn Sie Ihrem Beispiel folgen, werden Sie sich daran erinnern, dass wir in Java die Konstante innerhalb einer Klasse definieren müssen . Da Sie keinen Klassennamen erwähnt haben, nennen wir ihn
Foo
. Hier ist die Java-Klasse:Hier ist das entsprechende Python.
Der wichtigste Punkt, den ich hier hinzufügen möchte, ist, dass Sie keinen separaten
Foo
Typ benötigen (ein "anonymes benanntes Tupel" wäre nett, obwohl das wie ein Oxymoron klingt), also benennen wir unser benanntes Tupel, damit es_Foo
hoffentlich nicht funktioniert Escape zum Importieren von Modulen.Der zweite Punkt hier ist, dass wir sofort eine Instanz des Nametupels erstellen und es aufrufen
Foo
; Es ist nicht erforderlich, dies in einem separaten Schritt zu tun (es sei denn, Sie möchten). Jetzt können Sie das tun, was Sie in Java tun können:Aber Sie können es nicht zuordnen:
Bestätigung: Ich dachte, ich hätte den Namedtuple-Ansatz erfunden, aber dann sehe ich, dass jemand anderes eine ähnliche (wenn auch weniger kompakte) Antwort gegeben hat. Dann bemerkte ich auch Was sind "benannte Tupel" in Python? , was darauf hinweist, dass
sys.version_info
es sich nun um ein Namedtupel handelt, sodass die Python-Standardbibliothek diese Idee vielleicht schon viel früher hatte.Beachten Sie, dass Sie leider (dies ist immer noch Python) die gesamte
Foo
Zuweisung insgesamt löschen können :(Gesichtspalme)
Aber zumindest verhindern wir, dass sich der
Foo.CONST_NAME
Wert ändert, und das ist besser als nichts. Viel Glück.quelle
PEP 591 hat das "letzte" Qualifikationsmerkmal. Die Durchsetzung liegt bei der Typprüfung.
So können Sie tun:
Hinweis: Das
Final
Schlüsselwort gilt nur für die Python 3.8-Versionquelle
Hier ist eine Implementierung einer "Constants" -Klasse, die Instanzen mit schreibgeschützten (konstanten) Attributen erstellt. ZB kann verwendet werden
Nums.PI
, um einen Wert abzurufen, der als initialisiert wurde3.14159
, undNums.PI = 22
löst eine Ausnahme aus.Dank @MikeGrahams FrozenDict , das ich als Ausgangspunkt verwendet habe. Geändert, also anstelle
Nums['ONE']
der VerwendungssyntaxNums.ONE
.Und dank der Antwort von @ Raufio für die Idee, __ setattr __ zu überschreiben.
Eine Implementierung mit mehr Funktionen finden Sie unter @Hans_meine named_constants bei GitHub
quelle
Nums._d['PI'] = 22
Ich glaube, die Sprache selbst bietet keine Möglichkeit, Dinge als nicht veränderlich zu kennzeichnen.Ein Tupel qualifiziert sich technisch als Konstante, da ein Tupel einen Fehler auslöst, wenn Sie versuchen, einen seiner Werte zu ändern. Wenn Sie ein Tupel mit einem Wert deklarieren möchten, setzen Sie ein Komma nach dem einzigen Wert wie folgt:
Verwenden Sie Folgendes, um den Wert dieser Variablen zu überprüfen:
Wenn Sie versuchen, diesen Wert zu ändern, wird ein Fehler ausgegeben.
quelle
Ich würde eine Klasse erstellen, die die
__setattr__
Methode der Basisobjektklasse überschreibt, und meine Konstanten damit umschließen. Beachten Sie, dass ich Python 2.7 verwende:So wickeln Sie eine Zeichenfolge ein:
Es ist ziemlich einfach, aber wenn Sie Ihre Konstanten genauso verwenden möchten wie ein nicht konstantes Objekt (ohne constObj.value zu verwenden), ist es etwas intensiver. Es ist möglich, dass dies zu Problemen führen kann.
.value
Daher ist es möglicherweise am besten, die Anzeige beizubehalten und zu wissen, dass Sie Operationen mit Konstanten ausführen (möglicherweise jedoch nicht die "pythonischste" Methode).quelle
def ONE(): return 1
ist einfacher zu verwendenONE()
als diese AntwortONE.value
.Leider hat der Python noch keine Konstanten und es ist eine Schande. ES6 hat JavaScript bereits Unterstützungskonstanten hinzugefügt ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/const ), da dies in jeder Programmiersprache sehr nützlich ist. Wie in anderen Antworten in der Python-Community beantwortet, verwenden Sie die Konvention - Benutzer-Großbuchstabenvariable als Konstanten, sie schützt jedoch nicht vor willkürlichen Fehlern im Code. Wenn Sie möchten, kann es sein, dass Sie als Nächstes eine Einzeldateilösung als nützlich erachten (siehe Dokumentation zu deren Verwendung).
Datei constants.py
Wenn dies nicht ausreicht, lesen Sie den vollständigen Testfall.
Vorteile: 1. Zugriff auf alle Konstanten für das gesamte Projekt 2. Strikte Kontrolle der Werte von Konstanten
Fehlt: 1. Keine Unterstützung für benutzerdefinierte Typen und den Typ 'Dikt'
Anmerkungen:
Getestet mit Python3.4 und Python3.5 (ich benutze das 'Tox' dafür)
Testumgebung:
.
quelle
Die pythonische Art, "Konstanten" zu deklarieren, ist im Grunde eine Variable auf Modulebene:
Und dann schreiben Sie Ihre Klassen oder Funktionen. Da Konstanten fast immer ganze Zahlen sind und auch in Python unveränderlich sind, haben Sie nur eine sehr geringe Chance, sie zu ändern.
Es sei denn natürlich, wenn Sie explizit festlegen
RED = 2
.quelle
RED = 2
" ist der gesamte Vorteil (in anderen Sprachen), einen Variablennamen als "konstant" deklarieren zu können!static
, einen einzigen Speicher für den Wert für alle Instanzen einer Klasse zu haben? Es sei denn, es besteht tatsächlich die Möglichkeit, eine statische / Klassenvariable zu deklarieren.Wir können ein Deskriptorobjekt erstellen.
1) Wenn wir mit Konstanten auf Instanzebene arbeiten wollten, dann:
2) Wenn wir Konstanten nur auf Klassenebene erstellen möchten, können wir eine Metaklasse verwenden, die als Container für unsere Konstanten (unsere Deskriptorobjekte) dient. Alle Klassen, die absteigen, erben unsere Konstanten (unsere Deskriptorobjekte) ohne das Risiko, dass sie geändert werden können.
Wenn ich eine Unterklasse von Foo erstelle, erbt diese Klasse die Konstante, ohne dass die Möglichkeit besteht, sie zu ändern
quelle
Python-Wörterbücher sind veränderbar, daher scheinen sie keine gute Möglichkeit zu sein, Konstanten zu deklarieren:
quelle
Hier ist ein Trick, wenn Sie Konstanten wollen und sich nicht um ihre Werte kümmern:
Definieren Sie einfach leere Klassen.
z.B:
quelle
In Python ist eine Konstante einfach eine Variable mit einem Namen in allen Großbuchstaben, wobei die Wörter durch den Unterstrich getrennt sind.
z.B
DAYS_IN_WEEK = 7
Der Wert ist veränderbar, da Sie ihn ändern können. Aber angesichts der Regeln für den Namen, die Ihnen sagen, dass es sich um eine Konstante handelt, warum sollten Sie das tun? Ich meine, es ist doch dein Programm!
Dies ist der Ansatz, der in Python verfolgt wird. Aus
private
demselben Grund gibt es kein Schlüsselwort. Stellen Sie dem Namen einen Unterstrich voran, und Sie wissen, dass er privat sein soll. Code kann gegen die Regel verstoßen ... genau wie ein Programmierer das private Schlüsselwort sowieso entfernen könnte.Python hätte ein
const
Schlüsselwort hinzufügen können ... aber ein Programmierer könnte das Schlüsselwort entfernen und dann die Konstante ändern, wenn er möchte, aber warum? Wenn Sie die Regel brechen möchten, können Sie die Regel trotzdem ändern. Aber warum sollte man sich die Mühe machen, die Regel zu brechen, wenn der Name die Absicht klar macht?Vielleicht gibt es einen Unit-Test, bei dem es sinnvoll ist, eine Wertänderung vorzunehmen? Um zu sehen, was für eine 8-Tage-Woche passiert, obwohl in der realen Welt die Anzahl der Tage in der Woche nicht geändert werden kann. Wenn die Sprache Sie daran gehindert hat, eine Ausnahme zu machen, wenn es nur diesen einen Fall gibt, müssen Sie die Regel brechen ... Sie müssten dann aufhören, sie als Konstante zu deklarieren, obwohl sie in der Anwendung immer noch eine Konstante ist, und es gibt sie Nur dieser eine Testfall zeigt, was passiert, wenn er geändert wird.
Der Name in Großbuchstaben gibt an, dass es sich um eine Konstante handeln soll. Das ist wichtig. Keine Sprache, die Einschränkungen für Code erzwingt, die Sie ohnehin ändern können.
Das ist die Philosophie von Python.
quelle
Es gibt keinen perfekten Weg, dies zu tun. So wie ich es verstehe, werden die meisten Programmierer nur den Bezeichner großschreiben, so dass PI = 3.142 leicht als Konstante verstanden werden kann.
Wenn Sie andererseits etwas wollen, das sich tatsächlich wie eine Konstante verhält, bin ich mir nicht sicher, ob Sie es finden werden. Bei allem, was Sie tun, gibt es immer eine Möglichkeit, die "Konstante" zu bearbeiten, sodass sie nicht wirklich eine Konstante ist. Hier ist ein sehr einfaches, schmutziges Beispiel:
Dies scheint eine Konstante im PHP-Stil zu sein.
In Wirklichkeit braucht jemand nur Folgendes, um den Wert zu ändern:
Dies gilt auch für alle anderen Lösungen, die Sie hier finden - selbst für die cleveren, die eine Klasse bilden und die Set-Attribut-Methode neu definieren -, es wird immer einen Weg geben, sie zu umgehen. So ist Python eben.
Meine Empfehlung ist, einfach den ganzen Ärger zu vermeiden und nur Ihre Identifikatoren groß zu schreiben. Es wäre nicht wirklich eine richtige Konstante, aber nichts würde es tun.
quelle
Es gibt einen saubereren Weg, dies mit namedtuple zu tun:
Anwendungsbeispiel
Mit genau diesem Ansatz können Sie Ihre Konstanten mit einem Namespace versehen.
quelle
Vielleicht hilft dir die pconst Bibliothek ( github ).
$ pip install pconst
[Out] Constant value of "APPLE_PRICE" is not editable.
quelle
Sie können StringVar oder IntVar usw. verwenden. Ihre Konstante ist const_val
quelle
Sie können es tun mit
collections.namedtuple
unditertools
:quelle
(Dieser Absatz sollte einen Kommentar zu den hier und da erwähnten Antworten sein , die erwähnt wurden
namedtuple
, aber es wird zu lang, um in einen Kommentar zu passen, also geht es los.)Der oben erwähnte Namedtuple-Ansatz ist definitiv innovativ. Der Vollständigkeit halber heißt es jedoch am Ende des NamedTuple-Abschnitts seiner offiziellen Dokumentation :
Mit anderen Worten, die offizielle Dokumentation bevorzugt eine praktische Methode, anstatt das schreibgeschützte Verhalten tatsächlich zu implementieren. Ich denke, es wird ein weiteres Beispiel dafür Zen of Python :
quelle
Hier ist eine Sammlung von Redewendungen, die ich erstellt habe, um einige der bereits verfügbaren Antworten zu verbessern.
Ich weiß, dass die Verwendung von Konstanten nicht pythonisch ist, und Sie sollten dies nicht zu Hause tun!
Python ist jedoch eine so dynamische Sprache! Dieses Forum zeigt, wie es möglich ist, Konstrukte zu erstellen, die wie Konstanten aussehen und sich anfühlen. Diese Antwort hat in erster Linie den Zweck zu untersuchen, was durch die Sprache ausgedrückt werden kann.
Bitte sei nicht zu hart mit mir :-).
Für weitere Details habe ich einen Begleitblog über diese Redewendungen geschrieben .
In diesem Beitrag werde ich eine konstante Variable auf eine konstante Referenz auf Werte (unveränderlich oder anderweitig) aufrufen. Außerdem sage ich, dass eine Variable einen eingefrorenen Wert hat, wenn sie auf ein veränderliches Objekt verweist, dessen Wert ein Client-Code nicht aktualisieren kann.
Ein Raum von Konstanten (SpaceConstants)
Diese Redewendung erstellt einen Namespace konstanter Variablen (auch bekannt als SpaceConstants). Es ist eine Modifikation eines Code-Snippets von Alex Martelli , um die Verwendung von Modulobjekten zu vermeiden. Diese Modifikation verwendet insbesondere eine sogenannte Klassenfactory, da innerhalb der SpaceConstants- Funktion eine Klasse namens SpaceConstants verwendet wird definiert und eine Instanz davon zurückgegeben wird.
Ich habe die Verwendung von Class Factory untersucht, um ein richtlinienbasiertes Design in Python im Stackoverflow und auch in einem Blogpost zu implementieren .
Ein Leerzeichen mit eingefrorenen Werten (SpaceFrozenValues)
Diese nächste Redewendung ist eine Modifikation der SpaceConstants, in denen referenzierbare veränderbare Objekte eingefroren sind. Diese Implementierung nutzt das, was ich als Shared Closure zwischen setattr- und getattr- Funktionen bezeichne. Der Wert des veränderlichen Objekts wird kopiert und von der Variablen- Cache- Definition innerhalb des gemeinsam genutzten Funktionsabschlusses referenziert . Es bildet eine so genannte schließungsgeschützte Kopie eines veränderlichen Objekts .
Sie müssen bei der Verwendung dieser Redewendung vorsichtig sein, da getattr den Wert des Caches durch eine tiefe Kopie zurückgibt . Dieser Vorgang kann erhebliche Auswirkungen auf die Leistung großer Objekte haben!
Ein konstanter Raum (ConstantSpace)
Diese Redewendung ist ein unveränderlicher Namespace von konstanten Variablen oder ConstantSpace . Es ist eine Kombination aus einer unglaublich einfachen Antwort von Jon Betts im Stackoverflow mit einer Klassenfabrik .
Ein gefrorener Raum (FrozenSpace)
Diese Redewendung ist ein unveränderlicher Namespace von eingefrorenen Variablen oder FrozenSpace . Es wird aus dem vorherigen Muster abgeleitet, indem jede Variable durch Schließen der generierten FrozenSpace- Klasse zu einer geschützten Eigenschaft gemacht wird .
quelle
In Python sind Konstanten nicht vorhanden. Sie können jedoch angeben, dass eine Variable eine Konstante ist und nicht geändert werden darf, indem Sie
CONST_
am Anfang des Variablennamens hinzufügen und in einem Kommentar angeben, dass es sich um eine Konstante handelt:Alternativ können Sie eine Funktion erstellen, die sich wie eine Konstante verhält:
quelle
In meinem Fall benötigte ich unveränderliche Bytearrays für die Implementierung einer Kryptobibliothek mit vielen Literalzahlen, die ich sicherstellen wollte, dass sie konstant sind.
Diese Antwort funktioniert, aber die versuchte Neuzuweisung von Bytearray-Elementen führt nicht zu einem Fehler.
Konstanten sind unveränderlich, aber die konstante Bytearray-Zuweisung schlägt lautlos fehl:
Ein leistungsfähigerer, einfacher und vielleicht sogar "pythonischer" Ansatz beinhaltet die Verwendung von Memoryview-Objekten (Pufferobjekte in <= python-2.6).
Die Zuordnung von ConstArray-Elementen ist
TypeError
:quelle
Ich schreibe eine util lib für python const: kkconst - pypi support str, int, float, datetime
Die const-Feldinstanz behält ihr Basistypverhalten bei.
Zum Beispiel:
Weitere Details Verwendung Sie können die Pypi-URL lesen: Pypi oder Github
quelle
Sie können eine Konstante in ein Numpy-Array einschließen, sie nur als Schreibzugriff kennzeichnen und sie immer mit dem Index Null aufrufen.
Dies schützt natürlich nur den Inhalt des Numpys, nicht die Variable "CONSTANT" selbst; Sie können immer noch tun:
und
CONSTANT
würde sich ändern, aber das würde schnell einen TypeError auslösen, wenn das erste MalCONSTANT[0]
später im Skript aufgerufen wird.obwohl ... ich nehme an, wenn du es irgendwann geändert hast
Jetzt würden Sie den TypeError nicht mehr bekommen. hmmmm ....
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html
quelle