我目前有一个包含 200 多个条目的 CSV 文件,其中每一行都需要制作成自己的类文件。这些类将继承自具有一些字段变量的基类,这些变量将继承并根据 CSV 文件设置值。此外,python 模块的名称需要基于 CSV 文件的条目。
我真的不想手动制作超过 200 个单独的 python 类文件,并且想知道是否有一种方法可以轻松地做到这一点。谢谢!
编辑* 我绝对更像是一个 java/C# 编码器,所以我对 python 不太熟悉。 更多细节:我正在尝试为现有的网络游戏创建一个 AI,我可以通过实时流文本框从中提取实时数据。 玩家每回合可以使用 200 多个 Action ,而且每个 Action 都大不相同。我可能会在使用移动类时创建新的实例,但是每次使用移动时我都必须遍历所有移动及其效果的数据库,这看起来效率很低。因此,我正在考虑为每个 Action 创建类,名称与文本框中出现的名称相同,以便我可以更快地创建该特定 Action 的新实例。
最佳答案
正如其他人所说,您通常希望为此类事情生成运行时类,而不是创建单独的文件。
但我想:如果您有充分的理由这样做,比如为一堆文件制作类模板,以便您以后可以进去扩展它们,那该怎么办?假设我计划编写很多代码,所以我想自动化样板代码部分,这样我就不会被困在繁琐的工作中。
事实证明,为 Python 类编写一个简单的模板引擎并不那么难。这是我的尝试,它能够从 csv 文件进行模板化。
from os import path
from sys import argv
import csv
INIT = 'def __init__'
def csvformat(csvpath):
""" Read a csv file containing a class name and attrs.
Returns a list of the form [['ClassName', {'attr':'val'}]].
"""
csv_lines = []
with open(csvpath) as f:
reader = csv.reader(f)
_ = [csv_lines.append(line)
for line in reader]
result = []
for line in csv_lines:
attr_dict = {}
attrs = line[1:]
last_attr = attrs[0]
for attr in attrs[1:]:
if last_attr:
attr_dict[last_attr] = attr
last_attr = ''
else:
last_attr = attr
result.append([line[0], attr_dict])
return result
def attr_template(attrs):
""" Format a list of default attribute setting code. """
attr_list = []
for attr, val in attrs.items():
attr_list.append(str.format(' if {} is None:\n', attr, val))
attr_list.append(str.format(' self.{} = {}\n', attr, val))
attr_list.append(' else:\n')
attr_list.append(str.format(' self.{} = {}\n', attr, attr))
return attr_list
def import_template(imports):
""" Import superclasses.
Assumes the .py files are named based on the lowercased class name.
"""
imp_lines = []
for imp in imports:
imp_lines.append(str.format('from {} import {}\n',
imp.lower(), imp))
return imp_lines
def init_template(attrs):
""" Template a series of optional arguments based on a dict of attrs.
"""
init_string = 'self'
for key in attrs:
init_string += str.format(', {}=None', key)
return init_string
def gen_code(foldername, superclass, name, attrs):
""" Generate python code in foldername.
Uses superclass for the superclass, name for the class name,
and attrs as a dict of {attr:val} for the generated class.
Writes to a file with lowercased name as the name of the class.
"""
imports = [superclass]
pathname = path.join(foldername, name.lower() + '.py')
with open(pathname, 'w') as pyfile:
_ = [pyfile.write(imp)
for imp
in import_template(imports)]
pyfile.write('\n')
pyfile.write((str.format('class {}({}):\n', name, superclass)))
pyfile.write((str.format(' {}({}):\n',
INIT, init_template(attrs))))
_ = [pyfile.write(attribute)
for attribute
in attr_template(attrs)]
pyfile.write(' super().__init__()')
def read_and_generate(csvpath, foldername, superclass):
class_info = csvformat(csvpath)
for line in class_info:
gen_code(foldername, superclass, *line)
def main():
read_and_generate(argv[1], argv[2], argv[3])
if __name__ == "__main__":
main()
上面的代码将这样格式的 csv 文件作为其第一个参数(此处保存为 a.csv
):
Magistrate,foo,42,fizz,'baz'
King,fizz,'baz'
第一个字段是类名,后面是属性名及其默认值。第二个参数是输出文件夹的路径。
如果我创建一个名为 classes
的文件夹,并在其中创建一个具有基本类结构的 classes/mysuper.py
:
class MySuper():
def __init__(*args, **kwargs):
pass
然后像这样运行代码:
$ python3 codegen.py a.csv classes MySuper
我得到了包含以下内容的文件 classes/magistrate.py
:
from mysuper import MySuper
class Magistrate(MySuper):
def __init__(self, fizz=None, foo=None):
if fizz is None:
self.fizz = 'baz'
else:
self.fizz = fizz
if foo is None:
self.foo = 42
else:
self.foo = foo
super().__init__()
和classes/king.py
:
from mysuper import MySuper
class King(MySuper):
def __init__(self, fizz=None):
if fizz is None:
self.fizz = 'baz'
else:
self.fizz = fizz
super().__init__()
您实际上也可以加载并使用它们!
$ cd classes
classes$ python3 -i magistrate.py
>>> m = Magistrate()
>>> m.foo
42
>>> m.fizz
'baz'
>>>
上面生成的是我习惯的 Python 3 代码,因此您需要进行一些小的更改才能在 Python 2 中运行。
关于python - 如何动态创建新的python类文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24233477/