1275 Stimmen

Wie erstelle ich eine Konstante in Python?

Wie deklariere ich eine Konstante in Python?

In Java machen wir:

public static final String CONST_NAME = "Name";

0voto

Kostas Mouratidis Punkte 1018

Hinweis: Dies ist eine schreckliche Idee und eine schreckliche Umsetzung. Außerdem funktioniert es nur für das kleine Beispiel am Ende, eine vollständige Implementierung würde viel Arbeit bedeuten, die ich zu faul bin zu tun. Außerdem sind Audit-Hooks wahrscheinlich erst ab Python 3.8 verfügbar.

Ich habe größtenteils eine andere Frage beantwortet und es stellt sich heraus, dass sie mit dieser hier zusammenhängt. Die Idee ist, dass man die Audit-Hooks nutzen kann, um die Ausführung jeder Zeile zu erfassen, das Code-Objekt zu analysieren und wenn es einer bestimmten Bedingung entspricht (z.B. ein bestimmtes Präfix hat und einmal definiert wurde), einen Fehler zu werfen.

Man müsste wahrscheinlich andere Zuweisungstypen unterstützen (z.B. für importierte Sachen, vielleicht für lokale Variablen innerhalb von Funktionen, mit Entpacken usw.), nicht globals verwenden, da dieses Dictionary leicht geändert werden kann, tatsächlich untersuchen, ob das sicher ist, den Leistungsabzug akzeptieren, den diese Implementierung für die gesamte Anwendung haben wird, sicherstellen, dass dies außerhalb der REPL, innerhalb von ipython usw. funktioniert usw. Wie auch immer, hier sind wir:

>>> import sys
>>> import ast
>>> import dis
>>> import types
>>> 
>>> 
>>> def hook(name, tup):
...     if name == "exec" and tup:
...         if tup and isinstance(tup[0], types.CodeType):
...             code = tup[0]
...             store_instruction_arg = None
...             instructions = [dis.opname[op] for op in code.co_code]
...             
...             for i, instruction in enumerate(instructions):
...                 if instruction == "STORE_NAME":
...                     store_instruction_arg = code.co_code[i + 1]
...                     break
...             
...             if store_instruction_arg is not None:
...                 var_name = code.co_names[store_instruction_arg]
...                 if var_name in globals():
...                     raise Exception("Kann die Variable nicht neu zuweisen")
... 
>>> 
>>> sys.addaudithook(hook)
>>> 
>>> a = '123'
>>> a = 456
Traceback (most recent call last):
  File "", line 16, in hook
Exception: Kann die Variable nicht neu zuweisen
>>> 
>>> a
'123'

Wenn Sie sich entscheiden, diesen Weg zu gehen, was Sie nicht tun sollten, abgesehen von Fixes und Verallgemeinerung des Codes werden Sie wahrscheinlich einen Weg finden wollen, nur einige Sachen konstant zu machen, z.B. nur die Objekte mit einem speziellen Präfix oder nur Objekte, die eine bestimmte Annotation haben.

-2voto

sergzach Punkte 6232

Sie können mit Hilfe der folgenden Klasse Konstante Variablen emulieren. Ein Beispiel für die Verwendung:

# Const
const = Const().add(two=2, three=3)

print 'const.two: ', const.two
print 'const.three: ', const.three

const.add(four=4)

print 'const.four: ', const.four

#const.four = 5 # ein Fehler hier: four ist eine Konstante

const.add(six=6)

print 'const.six: ', const.six

const2 = Const().add(five=5) # Erstellung eines neuen Namensraums mit Const()
print 'const2.five: ', const2.five
#print 'const2.four: ', const2.four # ein Fehler hier: four existiert nicht im const2-Namensraum

const2.add(five=26)

Rufen Sie den Konstruktor auf, wenn Sie einen neuen konstanten Namensraum starten möchten. Beachten Sie, dass die Klasse vor unerwarteten Änderungen von Sequenztypkonstanten geschützt ist, wenn Martellis const-Klasse nicht ist.

Der Quellcode ist unten.

from copy import copy

class Const(object):
"Eine Klasse zum Erstellen von Objekten mit konstanten Feldern."

def __init__(self):
    object.__setattr__(self, '_names', [])

def add(self, **nameVals):
    for name, val in nameVals.iteritems():          
        if hasattr(self, name):
            raise ConstError('Ein Feld mit dem Namen \'%s\' existiert bereits in der Const-Klasse.' % name)

        setattr(self, name, copy(val)) # Getter einrichten

        self._names.append(name)

    return self

def __setattr__(self, name, val):
    if name in self._names:
        raise ConstError('Sie können den Wert einer gespeicherten Konstanten nicht ändern.')

    object.__setattr__(self, name, val)

-2voto

Erweitern Sie Raufios Antwort um ein __repr__, um den Wert zurückzugeben.

class const(object):
    def __init__(self, val):
        super(const, self).__setattr__("value", val)
    def __setattr__(self, name, val):
        raise ValueError("Trying to change a constant value", self)
    def __repr__(self):
        return ('{0}'.format(self.value))

dt = const(float(0.01))
print dt

dann verhält sich das Objekt ein wenig mehr wie erwartet, Sie können direkt darauf zugreifen, anstatt '.value'

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