Почему декоратор свойств определен только для классов?

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кажется естественным местом для добавления такой функциональности.

Есть ли какая-то конкретная причина или мотивация, почему это не встроено напрямую?

10
задан mvanveen 1 August 2012 в 04:23
поделиться