Вопрос по python – Динамическое создание класса из файла в Python

5

Я видел эти вопросы «Динамически создать класс», на которые отвечали: «используйте функцию type ()». Я уверен, что мне придется в какой-то момент, но точно знаю, что я не знаю. Но из того, что я видел, вы уже должны кое-что знать о классе, например, имя.

То, что я пытаюсь сделать, это проанализировать тип файла idl и создать класс, который будет иметь методы и атрибуты. Так что я не знаю, что будет с именем класса, функциями, аргументами или чем-либо еще, пока я не проанализирую строку.

Любые идеи

Не могли бы вы привести краткий пример создания входного файла и класса? Simon Bergot

Ваш Ответ

3   ответа
14

http: //docs.python.org/library/functions.html#typ

Это немного сложно для Google, но вы можете искатьpython type(name, bases, dict) function examples получить

http: //www.voidspace.org.uk/python/articles/metaclasses.shtm

Выдержка из вышесказанного, которая доходит до сути вашего вопроса:

Следующее в основном эквивалентно:

def __init__(self, x):
    self.x = x

def printX(self):
    print self.x

Test = type('Test', (object,), {'__init__': __init__, 'printX': printX})

а также

class Test(object):
    def __init__(self, x):
        self.x = x

    def printX(self):
        print self.x

Есть два способа создания функций на лету, которые я могу придумать. Обычно плохим способом является написание кода и его повторная обработка (хотя все сделано правильно, это может значительно увеличить производительность). Разумным способом является реализация функции, которая интерпретирует ваш IDL. Это называется функцией высшего порядка:http: //effbot.org/pyfaq/how-do-you-make-a-higher-order-function-in-python.ht

В качестве примера того, что вы бы написали, если вы не можете найти переводчика для вашей IDL (или, если это пользовательская IDL), это что-то вроде ссылки выше, например:

def makeMethod(idlCode):
    syntax = MyIDL.parse(idlCode)

    def newMethod(*args, **kw):
        if syntax.statementType == MyIDL.IF_STATEMENT:
            if secureLookup(mySyntaxTree.IF):
               return secureLookup(args[0]) 
            else:
               return secureLookup(args[1])
        ...

    return (syntax.methodName, newMethod)

Есть много более элегантных способов расширить этот метод, если вы настроите отображение между конструкциями вашего IDL и синтаксисом * args и ** kw, но это дает вам наибольшую гибкость и является наиболее простым и простым способом мог придумать.

Тогда ты бы прошел:

class DynamicIdlClass(object):
    ...

for idlObject in idlCode:
    methods = dict(makeMethod(clause) for clause in idlObject.clauses})
    methods['__init__'] = makeInitMethod(idlObject.initClause)
    idlObject = type('Test', (DynamicIdlClass,), methods)

    yield idlObject  # or idlObjectsList.push(idlObject), etc.
Код здесь все еще требует, чтобы я знал, что пользователь определяет__init__ а такжеprintX. Ссылка на voidspace.org была довольно интересной, немного запутанной, но после того, как я запуталась в ней, она была довольно близка. jiveturkey
jnbbender: пользователю не нужно определять эти функции (возможно, в том смысле, в каком вы используете фразу ...). Есть два способа создания функций на лету, которые я могу придумать. Плохой способ - написать код и проанализировать его. Разумным способом является реализация функции, которая интерпретирует ваш IDL. Это называется функцией высшего порядка: Effbot.org / pyfaq / ... ninjagecko
1

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

Первое место, где я бы искал идеи, это стандартный источник библиотеки дляxmlrpclib - посмотрите конкретно на то, как он использует__getattr__ для обработки несуществующих вызовов методов на лету.

Я знаю, что я действительно не понимал, почему они называют Python динамическим языком, пока я полностью не смирился с этими возможностями.

1

который предоставляет конкретный метод, который имеет возможность добавлять вызываемые атрибуты. Мы разбираем множество yaml-файлов для схемы и собираем эти объекты динамически.

Что-то похоже

def add_method(name, callable):
    setattr(self,name,callable)

Но это очень наивный пример, но вы поняли идею. Схема хранится внутри каждого динамического класса под чем-то вроде__schema это словарь, содержащий прототипы kwarg и строки документов.

Для настоящих призывных сил скелет похож на

def skel(self, *args, **kwargs):
    if '_schema' in kwargs:
        parse_yml, add control statements
    handle args and kwargs based on schema

some_instance.add_method('blah',skel)

Снова, это оба чрезвычайно наивные примеры, которые не охватывают большинство проблем и крайних случаев, возникающих при работе с этим типом проблемы. Это также один из нескольких способов найти решение.

Примеры

IonObject

Генератор моделей объектов

Это не создает вызываемые атрибуты. Это удобный метод для вызоваsetattr. Это не позволяет вам самим определять методы (которые имеют неявныйself первый аргумент), или произвольно установить базовые классы. Это позволяет только делать то, что синтаксически эквивалентноmyObject.fieldName = value. Единственная причина, по которой это работает в коде IonObject, заключается в том, что он копирует уже созданные значения из идентичного класса, поэтому методы сохраняются (хотя они могут работать некорректно, если не реализованы с помощьюучебный клас, может даже тогда), а базовые классы уже одинаковы. ninjagecko
Один из способов выполнить этот взлом, которыйвол работает над методами (и если вам не нужно менять базовые классы), это Code.activestate.com / Рецепты / ... - это кажется довольно хрупким, если вы делаете какие-либо размышления / осмотра. ninjagecko
Я пришел из c ++, я думаю, вы захотите добавить вызываемое к себе (это какой-то другой объект), какое имя я не знаю. то есdef add_method(self, callable, value): setattr(self, callable, value). Можешь так сделать jiveturkey
setattr(self - это то, что добавляет вызываемый атрибут к себе. Это не так просто, как в примере, много крайних случаев и сгущений, но это иллюстрирует модель (мы) решили использовать. Если вы посмотрите на приведенные более подробные примеры, это даст вам лучшее представление о том, что происходит. lukecampbell
@ jnbbender: Как я уже объяснил, нет, вы не можете без хаков, подобных тому, который я связал. Методы PythonmyObject.method(a,b,c) на самом деле звониmethod(myObject,a,b,c). Вы можете сделать это, если вы делаете это правильно, то есть сtype(name, bases, dict). ninjagecko

Похожие вопросы