Python:通过函数构造class(和变量名)?
Python: Construct class (and variable names) through a function?
我最近开始使用 Python 的 classes,因为我需要通过使用 OTree(一个用于在线实验的 Python 框架)来使用它。
在一个文件中,我使用 classes 定义了我想要创建的页面。所以本质上,在 OTree 系统中,每个 class 对应一个新页面。问题是,所有页面(所以 classes)基本相同,除了某些两个参数外,如以下代码所示:
class Task1(Page):
form_model = 'player'
form_fields = ['Envie_WordsList_Toy']
def is_displayed(self):
return self.round_number == self.participant.vars['task_rounds'][1]
def vars_for_template(player):
WordsList_Toy= Constants.WordsList_Toy.copy()
random.shuffle(WordsList_Toy)
return dict(
WordsList_Toy=WordsList_Toy
)
@staticmethod
def live_method(player, data):
player.WTP_WordsList_Toy = int(data)
def before_next_page(self):
self.participant.vars['Envie_WordsList_Toy'] = self.player.Envie_WordsList_Toy
self.participant.vars['WTP_WordsList_Toy'] = self.player.WTP_WordsList_Toy
所以在这里,唯一会改变的是 class 的名称,以及整个代码中使用的变量 WordsList_
的后缀,即 Toy
.
天真地,我试图做的是定义一个函数来接受这两个参数,例如:
def page_creation(Task_Number,name_type):
class Task+str(Task_Number)(Page):
form_model = 'player'
form_fields = ['Envie_WordsList_'+str(name_type)]
def is_displayed(self):
return self.round_number == self.participant.vars['task_rounds'][1]
def vars_for_template(player):
WordsList_+str(name_type) = Constants.WordsList+str(name_type).copy()
random.shuffle(WordsList_+str(name_type))
return dict(
WordsList_+str(name_type)=WordsList_+str(name_type)
)
@staticmethod
def live_method(player, data):
player.WTP_WordsList_+str(name_type) = int(data)
def before_next_page(self):
self.participant.vars['Envie_WordsList_+str(name_type)'] = self.player.Envie_WordsList_+str(name_type)
self.participant.vars['WTP_WordsList_+str(name_type)'] = self.player.WTP_WordsList_+str(name_type)
显然,它不起作用,因为我觉得不可能以这种方式构造变量(或 classes 标识符)。几周前我才真正开始研究 Python,所以它的某些方面可能仍然让我不知所措。你能帮我解决这个问题吗?谢谢。
您可以使用 type
构造函数生成动态 classes:
MyClass = type("MyClass", (BaseClass1, BaseClass2), {"attr1": "value1", ...})
因此,根据您的情况,应该是:
cls = type(f"Task{TaskNumber}", (Page, ), {"form_fields": [f"Envive_WordList_{name_type}"], ...})
请注意,您仍然需要构建 __init__
、is_displayed
等常用方法,作为 class 工厂的内部函数:
def class_factory(*args, **kwargs):
...
def is_displayed(self):
return self.round_number == self.participant.vars['task_rounds']
def vars_for_template(player):
...
# Classmethod wrapping is done below
def live_method(player, data):
...
cls = type(..., {
"is_displayed": is_displayed,
"vars_for_template": vars_for_template,
"live_method": classmethod(live_method),
...,
}
@classmethod
可以用作函数 - {"live_method": classmethod(my_method)}
我最近开始使用 Python 的 classes,因为我需要通过使用 OTree(一个用于在线实验的 Python 框架)来使用它。
在一个文件中,我使用 classes 定义了我想要创建的页面。所以本质上,在 OTree 系统中,每个 class 对应一个新页面。问题是,所有页面(所以 classes)基本相同,除了某些两个参数外,如以下代码所示:
class Task1(Page):
form_model = 'player'
form_fields = ['Envie_WordsList_Toy']
def is_displayed(self):
return self.round_number == self.participant.vars['task_rounds'][1]
def vars_for_template(player):
WordsList_Toy= Constants.WordsList_Toy.copy()
random.shuffle(WordsList_Toy)
return dict(
WordsList_Toy=WordsList_Toy
)
@staticmethod
def live_method(player, data):
player.WTP_WordsList_Toy = int(data)
def before_next_page(self):
self.participant.vars['Envie_WordsList_Toy'] = self.player.Envie_WordsList_Toy
self.participant.vars['WTP_WordsList_Toy'] = self.player.WTP_WordsList_Toy
所以在这里,唯一会改变的是 class 的名称,以及整个代码中使用的变量 WordsList_
的后缀,即 Toy
.
天真地,我试图做的是定义一个函数来接受这两个参数,例如:
def page_creation(Task_Number,name_type):
class Task+str(Task_Number)(Page):
form_model = 'player'
form_fields = ['Envie_WordsList_'+str(name_type)]
def is_displayed(self):
return self.round_number == self.participant.vars['task_rounds'][1]
def vars_for_template(player):
WordsList_+str(name_type) = Constants.WordsList+str(name_type).copy()
random.shuffle(WordsList_+str(name_type))
return dict(
WordsList_+str(name_type)=WordsList_+str(name_type)
)
@staticmethod
def live_method(player, data):
player.WTP_WordsList_+str(name_type) = int(data)
def before_next_page(self):
self.participant.vars['Envie_WordsList_+str(name_type)'] = self.player.Envie_WordsList_+str(name_type)
self.participant.vars['WTP_WordsList_+str(name_type)'] = self.player.WTP_WordsList_+str(name_type)
显然,它不起作用,因为我觉得不可能以这种方式构造变量(或 classes 标识符)。几周前我才真正开始研究 Python,所以它的某些方面可能仍然让我不知所措。你能帮我解决这个问题吗?谢谢。
您可以使用 type
构造函数生成动态 classes:
MyClass = type("MyClass", (BaseClass1, BaseClass2), {"attr1": "value1", ...})
因此,根据您的情况,应该是:
cls = type(f"Task{TaskNumber}", (Page, ), {"form_fields": [f"Envive_WordList_{name_type}"], ...})
请注意,您仍然需要构建 __init__
、is_displayed
等常用方法,作为 class 工厂的内部函数:
def class_factory(*args, **kwargs):
...
def is_displayed(self):
return self.round_number == self.participant.vars['task_rounds']
def vars_for_template(player):
...
# Classmethod wrapping is done below
def live_method(player, data):
...
cls = type(..., {
"is_displayed": is_displayed,
"vars_for_template": vars_for_template,
"live_method": classmethod(live_method),
...,
}
@classmethod
可以用作函数 - {"live_method": classmethod(my_method)}