#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})