Я работаю над созданием модуля 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. Вот код:
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())
import clr.Foo.Bar.Baz
clr.Foo.speak()
clr.Foo.Bar.speak()
clr.Foo.Bar.Baz.speak()
Все это, кажется, работает нормально. Python гарантирует, что модули в цепочке импортируются слева направо, поэтому clr
всегда импортируется первым, и он настраивает крючок, который позволяет импортировать оставшуюся часть цепочки.
Однако мне интересно, не является ли то, что я здесь делаю, чрезмерным. Я, в конце концов, устанавливаю глобальный крюк, который будет вызван для любого импорта модуля, даже если я отфильтровываю те, которые мне безразличны. Есть ли, возможно, какой-то способ установить крючок, который будет вызываться только для импорта из моего конкретного пакета, а не других? Или приведенный выше Верный Путь для такого рода вещей в Python?
-121--813130-
collection.Where(i => i.condition)
.ToList()
.ForEach(i => SomeComplicatedOpInvolving_i);
Я не ищу ответов, говорящих мне, что есть более простой способ сделать это, просто относитесь к этому как к мысленному эксперименту.
Во-первых, я прав, думая, что это три цикла? Где ()
, ToList ()
и для каждого ()
?
Во-вторых, (при условии, что это три цикла)Я прав, думая, что это n к силе 3 в большой O нотации?
Спасибо всем.