tl; dr: Wie funktionieren Eigenschaftsdekoratoren mit Funktionsdefinitionen auf Klassenebene, nicht mit Definitionen auf Modulebene?Warum ist die Eigenschaft Dekorator nur für Klassen definiert?
Ich habe Property Decorators auf einige Funktionen auf Modulebene angewendet und dachte, dass sie mir ermöglichen würden, die Methoden durch bloße Attributsuche aufzurufen.
Dies war besonders verlockend, weil ich eine Reihe von Konfigurationsfunktionen wurde definiert, wie get_port
, get_hostname
usw., die alle mit ihrem einfacheren, terse Eigenschaft Pendants ersetzt worden sein könnte: port
, hostname
usw.
So config.get_port()
wäre nur die viel schöner config.port
ich war überrascht, als ich die folgende Zurückverfolgungs gefunden, was beweist, dass dies kein gangbarer Weg:
TypeError: int() argument must be a string or a number, not 'property'
Ich wusste, dass ich einen Vorläufer für eigenschaftsähnliche Funktionalität auf Modulebene gesehen hatte, da ich es für das Schreiben von Shellbefehlen mit dem eleganten aber hacky pbs library verwendet hatte.
Der interessante Hack unten finden Sie in der pbs library source code. Es ermöglicht die Fähigkeit, Eigenschaften-ähnliche Attribut-Lookups auf Modulebene durchzuführen, aber es ist schrecklich, schrecklich hackish.
# this is a thin wrapper around THIS module (we patch sys.modules[__name__]).
# this is in the case that the user does a "from pbs import whatever"
# in other words, they only want to import certain programs, not the whole
# system PATH worth of commands. in this case, we just proxy the
# import lookup to our Environment class
class SelfWrapper(ModuleType):
def __init__(self, self_module):
# this is super ugly to have to copy attributes like this,
# but it seems to be the only way to make reload() behave
# nicely. if i make these attributes dynamic lookups in
# __getattr__, reload sometimes chokes in weird ways...
for attr in ["__builtins__", "__doc__", "__name__", "__package__"]:
setattr(self, attr, getattr(self_module, attr))
self.self_module = self_module
self.env = Environment(globals())
def __getattr__(self, name):
return self.env[name]
Unten ist der Code zum Einfügen dieser Klasse in den Import-Namespace. Es patcht tatsächlich sys.modules
direkt!
# we're being run as a stand-alone script, fire up a REPL
if __name__ == "__main__":
globs = globals()
f_globals = {}
for k in ["__builtins__", "__doc__", "__name__", "__package__"]:
f_globals[k] = globs[k]
env = Environment(f_globals)
run_repl(env)
# we're being imported from somewhere
else:
self = sys.modules[__name__]
sys.modules[__name__] = SelfWrapper(self)
Nun, da ich gesehen habe, was Längen pbs
durchlaufen hat, frage ich mich nach links, warum diese Einrichtung von Python nicht in die Sprache direkt eingebaut ist. Insbesondere der Dekorateur property
scheint ein natürlicher Ort zu sein, um eine solche Funktionalität hinzuzufügen.
Gibt es einen besonderen Grund oder eine Motivation dafür, warum dies nicht direkt eingebaut ist?
Zum leichteren Finden: Es gibt jetzt ein Modul namens mprop, das dies für Sie tut https://pypi.python.org/pypi/mprop – AbdealiJK