首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >混合类型()和使用__init__() .__init__()定制的.__init__()

混合类型()和使用__init__() .__init__()定制的.__init__()
EN

Stack Overflow用户
提问于 2016-04-27 12:47:33
回答 2查看 94关注 0票数 2

到目前为止,我已经成功地做到了:

我创建了一个elem类来表示html元素(divhtmlspanbody等)。

我能够像这样派生这个类,为每个元素创建子类:

代码语言:javascript
运行
复制
class elem:
    def __init__(self, content="", tag="div", attr={}, tag_type="double"):
        """Builds the element."""
        self.tag = tag
        self.attr = attr
        self.content = content
        self.tag_type = tag_type

class head(elem):
    """A head html element."""

    def __init__(self, content=None, **kwargs):
        super().__init__(tag="head", content=content, **kwargs)

而且效果很好。

但是我必须为每个子类声明编写这段代码,如果我想要完成每个HTML标记类型,这是非常重复和多余的。

因此,我试图创建一个make_elem()函数,通过将相应的标记名作为字符串参数来创建类。

因此,与以前的类定义不同,我只需要如下所示:

代码语言:javascript
运行
复制
head = make_elem_class("head")

我被困在那里

这个函数应该创建一个类。这个类中的__init__()方法应该从它继承的类中调用__init__()方法。

我试图使这个make_elem_class()函数如下所示:

代码语言:javascript
运行
复制
def make_elem_class(name):
    """Dynamically creates the class with a type() call."""

    def init(self, content=None, **kwargs):
        super().__init__(tag=name, content=None, **kwargs)

    return type(name, (elem,), {"__init__" : init})

但是,在运行html = make_elem_class('html')时,html("html element")会得到以下错误:

代码语言:javascript
运行
复制
Traceback (most recent call last):
  File "elements.py", line 118, in <module>
    html("html element")
  File "elements.py", line 20, in init
    super().__init__(tag=name, content=None, **kwargs)
TypeError: object.__init__() takes no parameters

我想这与空的super()调用有关,所以我尝试使用super(elem, self)。但显然效果不太好。

我怎样才能做到这一点?

NB : --如果我从type()调用中的字典中删除"__init__":init,它可以正常工作,但是标记在elem中没有正确设置。我还试图将{"tag":name}直接传递给type(),但也没有成功。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-27 12:53:07

这里不能使用super()的非参数形式,因为这里没有class语句来提供该函数通常需要的上下文。

或者说,除非您自己提供该上下文,否则不能这样做;您需要在这里将名称__class__设置为闭包:

代码语言:javascript
运行
复制
def make_elem_class(name):
    """Dynamically creates the class with a type() call."""

    def init(self, content=None, **kwargs):
        super().__init__(tag=name, content=content, **kwargs)

    __class__ = type(name, (elem,), {"__init__" : init})
    return __class__

super()将自动从闭包中获取__class__值。请注意,我将content的值,而不是None的值传递给elem.__init__方法;您不会想失去这个值。

如果是too magical,那么在调用super()时显式地命名类和super();同样,类将从闭包中取出:

代码语言:javascript
运行
复制
def make_elem_class(name):
    """Dynamically creates the class with a type() call."""

    def init(self, content=None, **kwargs):
        super(elemcls, self).__init__(tag=name, content=content, **kwargs)

    elemcls = type(name, (elem,), {"__init__" : init})
    return elemcls
票数 4
EN

Stack Overflow用户

发布于 2016-04-27 16:20:04

我认为这是一个有点XY的问题。在这方面,您已经询问了如何在动态创建的类中使用super,但是您真正想要的是一种不那么冗长的方法来为您的子类设置各种类变量和默认值。

由于您并不期望相同标记类的所有实例共享相同的标记名,所以最好将其设置为类变量而不是实例变量。例如:

代码语言:javascript
运行
复制
from abc import ABC, abstractmethod

class Elem(ABC):
    tag_type = "double" # the default tag type

    def __init__(self, content="", attr=None, tag_type=None):
        """Builds the element."""
        self.attr = attr if attr is not None else {}
        self.content = content
        if tag_type is not None:
            self.tag_type = tag_type

    @property
    @abstractmethod
    def tag(self):
        """All base classes should identify the tag they represent"""
        raise TypeError("undefined tag for {}".format(type(self)))

class Head(Elem):
    tag = "head"
    tag_type = "text"

class Div(Elem):
    tag = "div"

h = Head()
d = Div()
h1 = Head(tag_type="int")

assert h.tag == "head"
assert d.tag == "div"
assert h1.tag == "head"
assert h.tag_type == "text"
assert d.tag_type == "double"
assert h1.tag_type == "int"

现在您可以编写非常短的子类,并且仍然可以显式声明类。您将注意到,我将一些默认值更改为None。对于attr来说,这是因为拥有可变的默认参数将不像您所期望的那样工作--它的行为更像是一个共享类变量。相反,如果没有指定None,则默认为attr,然后为每个实例创建一个新的attr。第二个实例(tag_type)是这样的,如果指定了tag_type,那么实例将具有它的tag_type集,但是所有其他实例都将依赖于这个类来获得默认值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36890291

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档