Зависящие от пакета крючки импорта в Python

Я работаю над созданием модуля Python, который сопоставляет API, предоставляемый другим языком/инфраструктурой, с Python. В идеале, я бы хотел, чтобы это было представлено как единый корневой пакет, который предоставляет вспомогательные методы, и который сопоставляет все пространства имен в этой другой рамке пакетам/модулям Python. Для удобства рассмотрим CLR в качестве примера:

import clr.System.Data
import clr.System.Windows.Forms

Вот clr - это волшебный пакет верхнего уровня, в котором представлены пространства имен CLR System.Data и System.Windows.Forms (насколько я вижу, пакет - это просто модуль с дочерними модулями по-прежнему допустимо иметь в нем другие виды членов).

Я прочитал PEP-302 и написал простой прототип программы, который достигает аналогичного эффекта, установив пользовательский meta _ path hook. Сам модуль clr является правильным модулем Python, который при импорте задает __ path __ = [] (делая его пакетом, так что import даже пытается найти подмодули) и регистрирует трубку. Крюк сам перехватывает любую загрузку пакета, где полное имя пакета начинается с «clr». , динамически создает новый модуль с помощью imp.new _ module () , регистрирует его в sys.modules и использует pixie dust и rainbows для заполнения его классами и методами из исходного API. Вот код:

clr.py

import sys
import imp

class MyLoader:
    def load_module(self, fullname):
        try:
            return sys.modules[fullname]
        except KeyError:
            pass
        print("--- load ---")
        print(fullname)
        m = imp.new_module(fullname)
        m.__file__ = "clr:" + fullname
        m.__path__ = []
        m.__loader__ = self
        m.speak = lambda: print("I'm " + fullname)
        sys.modules.setdefault(fullname, m)
        return m

class MyFinder:
    def find_module(self, fullname, path = None):
        print("--- find ---")
        print(fullname)
        print(path)
        if fullname.startswith("clr."):
            return MyLoader()            
        return None

print("--- init ---")
__path__ = []
sys.meta_path.append(MyFinder())

test.py

import clr.Foo.Bar.Baz

clr.Foo.speak()
clr.Foo.Bar.speak()
clr.Foo.Bar.Baz.speak()

Все это, кажется, работает нормально. Python гарантирует, что модули в цепочке импортируются слева направо, поэтому clr всегда импортируется первым, и он настраивает крючок, который позволяет импортировать оставшуюся часть цепочки.

Однако мне интересно, не является ли то, что я здесь делаю, чрезмерным. Я, в конце концов, устанавливаю глобальный крюк, который будет вызван для любого импорта модуля, даже если я отфильтровываю те, которые мне безразличны. Есть ли, возможно, какой-то способ установить крючок, который будет вызываться только для импорта из моего конкретного пакета, а не других? Или приведенный выше Верный Путь для такого рода вещей в Python?

-121--813130-

Правильно ли я считаю, что этот фрагмент является O (n ^ 3)? collection.Where (i = > i.condition) .ToList () .ForКаждый (i = > SomeComplicatedOpInvolving_i); Я не ищу ответов, говорящих мне, что есть более простой способ сделать это, просто относиться к этому как к мысли...
collection.Where(i => i.condition)
.ToList()
.ForEach(i => SomeComplicatedOpInvolving_i);

Я не ищу ответов, говорящих мне, что есть более простой способ сделать это, просто относитесь к этому как к мысленному эксперименту.

Во-первых, я прав, думая, что это три цикла? Где () , ToList () и для каждого () ?
Во-вторых, (при условии, что это три цикла)Я прав, думая, что это n к силе 3 в большой O нотации?

Спасибо всем.

6
задан Adam Naylor 1 September 2011 в 09:57
поделиться