比方说,我有一个包含有效python类(不是类名)的字符串。例如:
class_template = """
class MyClass(object):
def __init__(self, name):
self.name = name
def print_name(self):
print('My name is: ' + self.name)
def add_whatever(a, b):
return a + b
"""
是否可以在python中实现一个函数(在下面的示例中为string_to_class
),该函数接收该字符串并从中创建一个python类,以便稍后可以实例化该类?
class_template = """
class MyClass(object):
def __init__(self, name):
self.name = name
def print_name(self):
print('My name is: ' + self.name)
def add_whatever(a, b):
return a + b
"""
MyClass = string_to_class(class_template)
my_class_instance = MyClass('Ben')
print(MyClass.add_whatever(2, 3))
my_class_instance.print_name()
输出应为:
5
My name is: Ben
一种可能的解决方案是将字符串写到MyClass.py
文件中,然后使用__import__()
进行加载。还有其他(内存中)解决方案吗?
谢谢您的回答。
答案 0 :(得分:1)
评论者提到exec
;这是将其组合在一起的方式:
def string_to_class(python_text):
local_vars = {}
exec(python_text, {}, local_vars)
# assume just a single new symbol was created (the class), and return it
return list(local_vars.values())[0]
class_template = """
class MyClass(object):
def __init__(self, name):
self.name = name
def print_name(self):
print('My name is: ' + self.name)
@staticmethod
def add_whatever(a, b):
return a + b
"""
MyClass = string_to_class(class_template)
my_class_instance = MyClass('Ben')
print(MyClass.add_whatever(2, 3))
my_class_instance.print_name()
但是,就像其他评论者提到的那样,它不是一种普遍应用的技术,因此请谨慎使用。随着用例变得越来越复杂,您还将很快遇到问题:
some_string_that_defines_a_base_class = "case Base..."
some_string_that_defines_a_derived_class = "case Derived(Base):..."
Base = string_to_class(some_string_that_defines_a_base_class)
# this will crash because Base isn't defined in the scope that the string
# is being evaluated with
Derived = string_to_class(some_string_that_defines_a_derived_class)
您可以通过直接调用exec
来解决此问题(string_to_class
函数根本不够强大),但使用起来很快就很棘手:我什至没有提到{{ 1}} s可以工作了。还有其他技术(函数装饰器,元类)可以使您做的事更少痛苦,但是有时候import
确实是您唯一的选择。