tl; dr:プロパティデコレータがクラスレベルの関数定義で機能するのに、モジュールレベルの定義では機能しないのはなぜですか?
私はいくつかのモジュールレベルの関数にプロパティデコレータを適用していました。それらは単なる属性ルックアップによってメソッドを呼び出すことができると考えていました。
これは特に魅力的でした。なぜなら、、などの構成関数のセットを定義していたからですget_port
。これらの関数get_hostname
はすべて、より単純で簡潔なプロパティの対応物port
であるhostname
、などに置き換えることができました。
したがって、config.get_port()
はるかに良いでしょうconfig.port
次のトレースバックを見つけたとき、私は驚きました。これは実行可能なオプションではないことを証明しました。
TypeError: int() argument must be a string or a number, not 'property'
エレガントでハッキーなpbsライブラリを使用してシェルコマンドをスクリプト化するために使用していたので、モジュールレベルでプロパティのような機能の前例を見たことがあることを私は知っていました。
以下の興味深いハックは、pbsライブラリのソースコードにあります。モジュールレベルでプロパティのような属性ルックアップを実行する機能を有効にしますが、それは恐ろしく、恐ろしくハックです。
# 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]
以下は、このクラスをインポート名前空間に挿入するためのコードです。実際にsys.modules
直接パッチを当てます!
# 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)
どのくらいの長さpbs
を経なければならないかを見たので、なぜこのPythonの機能が言語に直接組み込まれていないのか疑問に思います。特にデコレータは、そのproperty
ような機能を追加するための自然な場所のようです。
これが直接組み込まれていない理由や動機はありますか?