Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python中字符串列表中的名称动态子类化_Python_Inheritance_Subclass - Fatal编程技术网

使用Python中字符串列表中的名称动态子类化

使用Python中字符串列表中的名称动态子类化,python,inheritance,subclass,Python,Inheritance,Subclass,我想使用字符串作为子类名称,从超类动态创建子类。例如,假设我有一个表示HTML标记的类 class标签: 定义初始化(自我、内容、**attr): 通过 定义报告(自我): 返回f“{content}” 我还有一份清单: class_names=[“Div”、“A”、“Body”、“Html”、“Nav”]#等基本上包含所有Html标记。 我想以某种方式创建标记类的子类(可能使用for循环),也就是说,我想有新的类,即Div、a、Body、Html、Nav等,它们都是标记类的子类。有没有快速

我想使用字符串作为子类名称,从超类动态创建子类。例如,假设我有一个表示HTML标记的类

class标签:
定义初始化(自我、内容、**attr):
通过
定义报告(自我):
返回f“{content}”
我还有一份清单:

class_names=[“Div”、“A”、“Body”、“Html”、“Nav”]#等基本上包含所有Html标记。
我想以某种方式创建标记类的子类(可能使用for循环),也就是说,我想有新的类,即
Div、a、Body、Html、Nav等,它们都是标记类的子类。有没有快速的方法可以做到这一点?不显式声明类也是一种不好的做法吗

编辑:我想创建子类,而不是对象

编辑2:正如Goyo所说,我的目的并不明确,我希望基本上一次性实现所有html标记类。许多人已经实现了HTML生成器,但对于,他们必须定义Tag类的所有子类,然后在子类中编写
pass
,如下所示:

。。。
类地址(HtmlTag):
“”“定义文档作者/所有者的联系信息”“”
通过
类小程序(HtmlTag):
“”“HTML5不支持。请改用或。”“”
通过
类区域(SelfClosingHtmlTag):
“”“定义图像映射内的区域”“”
通过
...
这就是我想要避免的,因为这看起来像是冗余的重复代码和大量的复制粘贴

编辑3:我很抱歉提到别人的代码是一个“坏”的例子。这根本不是我的本意。我只想学习如何编写更简短的代码。

查看以下文档:

类型(名称、基数、词条)
[…]
使用三个参数,返回一个新类型对象。这本质上是class语句的一种动态形式。名称字符串是类名,并成为
\uu name\uu
属性;bases元组逐项列出基类,并成为
\uuu bases\uuu
属性;dict dictionary是包含类主体定义的名称空间,它被复制到一个标准字典中,成为
\uu dict\uu
属性

因此,类似这样的内容应该创建您想要的类:

type(class_name, (Tag,), {})
如果您想为这些类别创建别名,这里已经多次询问并回答了这个问题。但既然你坚持,你就来了:

class Tag:
   def __init__(self, content, **attr):
       self.content = content

   def __repr__(self):
       return f"<{self.__class__.__name__.lower()}>{self.content}</{self.__class__.__name__.lower()}>"

class_names = ["Div", "A", "Body", "Html", "Nav"]

for class_name in class_names:
    globals()[class_name] = type(class_name, (Tag,), {})

div = Div('some content')
print(div)
你在毫无差别地做出区分 您正在创建一组行为相同的类。重点是什么?通过友好地创建它们,您甚至失去了静态类型检查的潜在好处。
Div
的实例与
a
的实例之间的唯一区别是在类名中编码的一些数据。通过将该数据存储在实例属性中,您可以省去所有这些类的需要,代码也变得更加简单

class Tag:
    def __init__(self, tag_name, content, **attr):
        self.tag_name = tag_name
        self.content = content

    def __repr__(self):
       return f"<{self.tag_name.lower()}>{self.content}</{self.tag_name.lower()}>" 

div = Tag('Div', 'some_content')
print(div)
class标签:
定义初始化(自我、标记名称、内容,**属性):
self.tag\u name=tag\u name
self.content=内容
定义报告(自我):
返回f“{self.content}”
div=标记('div','some_content')
印刷(部门)

如果希望通过动态创建类来节省代码行/键入时间,我建议不要这样做,尤其是如果您的子类除了名称之外基本上都是相同的。您需要在运行中执行此操作吗?@AGNGazer的可能副本我不知道它如何回答我的问题。这并不能真正回答我的问题,因为虽然设置了
\uu name\uuuuuuuuu
属性,但我无法用该名称实例化类,例如,我不能只执行
Div(“一些文本”,class=“我的类”)
。我已经在我的问题中添加了一个编辑,解释了我为什么要这样做。@MikePham我编辑了答案来添加它,但我认为您试图将它变得太复杂。
class Tag:
    def __init__(self, tag_name, content, **attr):
        self.tag_name = tag_name
        self.content = content

    def __repr__(self):
       return f"<{self.tag_name.lower()}>{self.content}</{self.tag_name.lower()}>" 

div = Tag('Div', 'some_content')
print(div)