Kann ich ein Namespace-Objekt von veränderlichen zu unveränderlichen konvertieren?

Ich bekomme ein Namespace-Objekt aus Befehlszeilenargumenten. Und ich will es nicht ändern. Kann ich das machen oder hast du mal Ideen?

# -*- coding: utf-8 -*- import argparse def parse_args(): parser = argparse.ArgumentParser(description='This script is ...') parser.add_argument('--confdir', type=str, required=True) parser.add_argument('--outdir', type=str, required=True) return parser.parse_args() if __name__ == '__main__': mutable_namespace = parse_args() # I want to prevent overwrite like that. mutable_namespace.confdir = "xxx" 

2 Solutions collect form web for “Kann ich ein Namespace-Objekt von veränderlichen zu unveränderlichen konvertieren?”

Ich habe zunächst die benutzerdefinierte Namespace-Klasse vorgeschlagen, aber ich mag diese Idee, args zu einem NamedTuple besser zu kopieren.

Namedtuple

Eine weitere Möglichkeit besteht darin, die Werte von args zu einem unveränderlichen Objekt / Klasse zu kopieren. Ein benannter Tupel könnte den Job gut machen.

Erstellen Sie einen Namespace

 In [1157]: dest=['x','y'] In [1158]: args=argparse.Namespace() In [1159]: for name in dest: ......: setattr(args, name, 23) ......: In [1160]: args Out[1160]: Namespace(x=23, y=23) 

Definiere nun ein namedtuple

 In [1161]: from collections import namedtuple In [1163]: Foo = namedtuple('Foo',dest) 

Du könntest auch die Tupelnamen aus dem Namespace selbst (nach dem Parsing)

 Foo = namedtuple('Foo',vars(args).keys()) 

Erstellen Sie ein solches Tupel mit Werten aus args :

 In [1165]: foo=Foo(**vars(args)) In [1166]: foo Out[1166]: Foo(x=23, y=23) In [1167]: foo.x Out[1167]: 23 

Und es ist unveränderlich:

 In [1168]: foo.x=34 ... AttributeError: can't set attribute 

Ein solches namedtuple kann nicht als Namespace verwendet werden, da setattr(foo,'x',34) denselben Fehler erzeugt.

Ein sauberer Weg, um all dies zu tun ist, um alles in einer Funktion zu wickeln:

 def do_parse(): parser = .... Foo = namedtuple(...) args = parser.parse_args() foo = Foo(**vars(args)) return foo 

Der rufende Code sieht nie die veränderlichen args , nur die unveränderliche foo .

Benutzerdefinierte Namespace-Klasse

Um auf Ingaz Antwort argparse kann argparse deine eigene Namespace Klasse verwenden.

https://docs.python.org/3/library/argparse.html#the-namespace-object

 class MyNamespace(argparse.Namespace): pass <customize one or more methods> anamespace = MyNamespace() args = parser.parse_args(namespace=anamespace) 

Jetzt anamespace und anamespace verweisen auf das gleiche MyNamespace Objekt. Solange getattr(anamespace, adest) und setattr(anamespace, adest, avalue) arbeiten, kann argparse dieses Namespace-Objekt verwenden.

Nun können Sie setattr(anamespace, 'string', 'value') erlauben, aber nicht anamespace.string = value ? Ich denke, Sie können, aber es wird ein gutes Verständnis davon verlangen, wie der letztere Ausdruck funktioniert. Es kann nur ein Customizing erforderlich sein .__setattr__ , aber ich habe diesen Aspekt von Python nicht in einer Weile studiert.

Mit dem Design ist es möglich und sogar akzeptabel, 'monkey patch' der argparse namespace – mit einer benutzerdefinierten Klasse wie diese.

Sie können __setattr__ in Ihrem mutable_namespace neu definieren:

 class NotMutableException(Exception):pass class SomeObject(object): def init(self): self.x = 10 self.y = 20 some_obj = SomeObject() some_obj.z = 30 def not_setattr(self, name, value): raise NotMutableException type(some_obj).__setattr__ = not_setattr some_obj.a = 1000 
  • Python3 AttributeError: 'list' Objekt hat kein Attribut 'clear'
  • Wie wähle man die Zeilen aus, die einen bestimmten Wert in mindestens einem der Elemente in einer Zeile enthalten?
  • Richtige Verwendung von Ctypen, um _Py_Mangle aufzurufen?
  • Catch "vor / nach Funktionsaufruf" Ereignisse für alle Funktionen in der Klasse
  • So verschieben Sie Dateien, die in einer Textdatei von einem Ordner zum anderen in python aufgeführt werden
  • Multiprocessing Freigeben von verrückten Objekten zwischen Prozessen
  • Wie man einen Baum in der Pythonschlange pflicht und druckt
  • Lambda wertet unerwartet aus
  • Was ist "pkg-resources == 0.0.0" in der Ausgabe von Pip-Freeze-Befehl
  • Gibt es eine eingebaute Identitätsfunktion in Python?
  • Ändern Sie "Quoted-printable" -Codierung auf "utf-8"
  • Python ist die beste Programmiersprache der Welt.