Генерировать код python класса из экземпляра python этого класса

#python #code-generation #metaprogramming

#python #генерация кода #метапрограммирование

Вопрос:

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

Допустим, я динамически создал класс A: type('A', (), {'bar':True} , который эквивалентен коду:

 class A(object): 
    bar=True
  

Я хочу сгенерировать этот эквивалентный код из моего динамического класса.
Я пытаюсь реализовать функцию «generate_A_code»

 kls_A = type('A', (), {'bar':True}
kls_A.generate_A_code()
  

Надеюсь, это немного поможет.

Спасибо

Комментарии:

1. Не могли бы вы привести простой пример с некоторым кодом и объяснением того, чего вы пытаетесь достичь?

2. Спасибо за разъяснение. Теперь, что точно вы подразумеваете под «Я создал динамически класс A»? Похоже, что это не часть вашего .py файла, и при этом вы не генерируете код в виде строки, и eval это … так что же именно вы делаете?

3. Вот пример того, что я написал для динамического создания класса: Foo = type(‘Foo’, (), {‘bar’:True})

Ответ №1:

Сгенерировать код Python из самого объекта класса практически невозможно. Вам нужно сохранить инструкции для создания класса другим способом.


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

 kwargs = {answer=42, name='foo'}

import class_maker
SomeClass1 = class_maker.make_class(**kwargs)
  

Другой вариант — сгенерируйте код Python, который вы хотите напрямую, exec чтобы создать класс, а затем сохраните его вместе с классом.

 code = '''class MyClass:
    pass
'''

the_locals = {}
exec(code, globals(), the_locals)
MyClass = the_locals['MyClass']
MyClass._code = code
  

Как всегда с exec , будьте очень осторожны при его использовании. Он может запускать любой Python-код. Подумайте хорошенько, есть ли какой-либо способ сделать все, что вам нужно, по-другому. Люди будут кричать на вас за использование exec . (Но даже стандартная библиотека Python иногда использует его для динамических классов.)

Комментарии:

1. Да, это кажется действительно сложным. Я попытаюсь сгенерировать его другим способом. Спасибо.

Ответ №2:

Вы можете использовать compile() , exec() или eval() в зависимости от ваших конкретных потребностей.

Комментарии:

1. Спасибо за ваш ответ, но я думаю, что я не был ясен в своем сообщении.

Ответ №3:

Возможно, вы могли бы использовать inspect.getsource:

 import inspect

def generate_kls_A(num):
    class A(object):
        def __init__(self):
            self.init = num
    return A
kls_A=generate_kls_A(1)
print(inspect.getsource(kls_A))
  

выдает:

 class A(object):
    def __init__(self):
        self.init = num
  

Комментарии:

1. спасибо, но, к сожалению, inspect.getsource не работает, если вы создаете свой класс с типом(‘A’, () {‘bar’:True})