python:读取一行,然后实例化一个在该行中命名的类

python:读取一行,然后实例化一个在该行中命名的类,python,dynamic,Python,Dynamic,如果我在标题中不够清楚,我很抱歉,如果你能找到更好的表达方式,请不要犹豫更正: 我有一个包含类名的文件,即: classa classb classb classc classc classc 然后我想逐行阅读并动态创建该类。 我会在php中执行类似的操作: while (!eof()) { $class=fread(..) $tab[] = new $class(); } 如果可能的话,您将如何在python中实现这一点 非常感谢 编辑:阅读答案后,为了更准确地说明我的计划:

如果我在标题中不够清楚,我很抱歉,如果你能找到更好的表达方式,请不要犹豫更正:

我有一个包含类名的文件,即:

classa
classb
classb
classc
classc
classc
然后我想逐行阅读并动态创建该类。 我会在php中执行类似的操作:

while (!eof())
{
   $class=fread(..)
   $tab[] = new $class();
}
如果可能的话,您将如何在python中实现这一点

非常感谢

编辑:阅读答案后,为了更准确地说明我的计划: 我不打算做这么简单的事。这将要复杂得多:我希望一个不懂编程的用户编辑一个简单的文本文件,复制/粘贴一些声明并更改它们的属性,然后重新启动一种解析器,它将重新运行批处理并显示复杂操作的结果。 文件的简化示例:

car:(red,4_wheels,4_places)
bike:(blue,2_wheels,1_place)
然后用户将其更改为:

car:(red,4_wheels,4_places)
car:(yellow,4_wheels,2_places)
bike:(blue,2_wheels,1_place)
bike:(green,2_wheels,2_places)
然后用python阅读这个文件,创建两个car类实例和两个bike类实例。因此,不理解/不了解python的用户将能够编辑该文件,而无需触摸一行代码。 我认为这是正确的方法,如果您对这段代码有任何其他建议,欢迎您


Olivier Pons

读取文件中的每一行非常简单:

with open(filename) as f:
    for line in f:
创建类时首先想到的是类型函数:

        cls = type(line, (object,), {})
这将创建一个新的空类,该类是object的子类,并且具有由行内容给定的名称


我想知道你为什么要这么做。像这样的空类在Python中似乎不是很有用。

假设您的类已经在范围内,即它们不在单独的模块中,您可以通过globals dict很容易地通过其名称引用类。例如:

class Foo:
    pass

foo_cls = globals()['Foo']
foo = foo_cls()
# foo is now an instance of __main__.Foo

使用类字典应该很容易做到这一点,但这不一定是一个限制,因为每个python名称空间都可以作为字典访问,所以如果您希望这些类都位于一个模块或另一个类中,只需将类替换为该类的_dict__;属性,或者按照其他人的建议使用globals即可:

classes = dict()
with open('filename') as f:
    for line in f:
        classes[line] = class()
实施细节可能有所不同


但是,您可能希望研究使用pickle,因为从表面上看,这种方法似乎有缺陷,但在PHP中可能工作得很好:-.

假设所有类都在模块foo中声明:


要访问同一模块中的类,请使用内置的globals函数。

其他答案按照您的要求执行,但我想增加一点灵活性和保护性。我会使用字典将行名称映射到类对象,这样就不会让文本文件实例化它想要的任何内容。它必须是您允许它在代码中使用的类。这也使它变得更容易,因为您可以毫无困难地更改任意一侧的名称,并且如果需要,可以将多个行名映射到单个类名

classes = {'classa': classa, 'classb': classb}
cls = type(classes[line], (object,), {})  ## or whichever method to instantiate you prefer

但是,在我看来,这不是一个非常复杂的事情。

无论如何,当你使用YAML时,考虑使用从YAML.YAMROBUPCAT元类派生的序列化类或注册自己的代表。 从Pyaml的文档中:

class Monster(yaml.YAMLObject):
    yaml_tag = u'!Monster'
    def __init__(self, name, hp, ac, attacks):
        self.name = name
        self.hp = hp
        self.ac = ac
        self.attacks = attacks
    def __repr__(self):
        return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % (
            self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)

print yaml.load("""
--- !Monster
name: Cave spider
hp: [2,6]    # 2d6
ac: 16
attacks: [BITE, HURT]
""")
打印怪物名称='洞穴蜘蛛',生命=[2,6],ac=16,攻击=['BITE','HURT']


通过这种方式,您可以省去错误处理所需的许多代码,例如类不存在,并且您的系统对恶意配置文件更为健壮。另外,您还可以将程序中的对象转储到YAML文件中。

为什么要这样做?我想不出有什么理由让大量基于文件的空类四处浮动。。。但也不是说没有!我可能不会这样做,除非我有一个很好的理由,并且不能以任何其他方式完成它,仅供参考。你的意思是“基于行创建类实例”吗?我调整了你的标题以反映你的问题,希望你不介意。不,相反:谢谢!我想,动态创建那个类应该被理解为动态创建那个类的实例。这就是OP中的PHP代码片段所做的。哦,我知道我不应该浏览PHP代码示例。呃,很抱歉,我不得不投票否决它,因为它不能正确回答我的问题,但这是一段很好的代码,如果有一天我需要它,我会保留它以备将来使用!谢谢again@Olivier当前位置请记住,这是一件非常粗糙的事情,如果你发现它有很好的用途,我会有点惊讶。回想起来,我很想删除这个…我会使用你的代码。更准确地说,我的YAML文件将有类声明,即car,然后稍后将有类实例,即car:id=145,color='blue'等等。我必须动态创建新类,然后稍后实例化它们。再次感谢你的提示!告诉我,如果我错了,但你的例子说,嘿,派特
请创建一个名为“line”的新类。我说得对吗?如果是这样,稍后,我将通过以下命令实例化这个类:myobject=new cls。我仍然是对的吗?这是一个很好的答案,我只是想知道访问全局是否不是一种技巧,因为我一直被教导避免全局性…这是class={'classa':classa,'classb':'classb'}还是class={'classa':classa,'classb':classb}还是class={'classa':'classa','classb':'classb'}啊,它应该是{'classfilename':classname}。我写的是走出门。上面的答案反映了这一点。根据他所做的,YAML语法的开销可能会超过它的价值。考虑到他的问题,检查类是否存在似乎是他需要的唯一检查。但是我也喜欢YAAML。最初的海报上有一个关于这个问题的评论:它要复杂得多:我将阅读一个复杂的YAML文件…-所以我得出结论,因为你正在使用YAML…嗯,乍一看,我认为嘿,这正是我需要的,但它不是100%的情况。比这更复杂。我想你让我走上了正轨,真的非常感谢你!
class Monster(yaml.YAMLObject):
    yaml_tag = u'!Monster'
    def __init__(self, name, hp, ac, attacks):
        self.name = name
        self.hp = hp
        self.ac = ac
        self.attacks = attacks
    def __repr__(self):
        return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % (
            self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)

print yaml.load("""
--- !Monster
name: Cave spider
hp: [2,6]    # 2d6
ac: 16
attacks: [BITE, HURT]
""")