Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.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 混合类型(),以及使用super()的自定义初始化 到目前为止,我成功地做到了:_Python_Python 3.x_Super - Fatal编程技术网

Python 混合类型(),以及使用super()的自定义初始化 到目前为止,我成功地做到了:

Python 混合类型(),以及使用super()的自定义初始化 到目前为止,我成功地做到了:,python,python-3.x,super,Python,Python 3.x,Super,我制作了一个elem类来表示html元素(div,html,span,body,等等) 我可以像这样派生这个类,为每个元素创建子类: class elem: def __init__(self, content="", tag="div", attr={}, tag_type="double"): """Builds the element.""" self.tag = tag self.attr = attr self.c

我制作了一个
elem
类来表示html元素(
div
html
span
body
,等等)

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

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()
函数,通过将相应的标记名作为字符串参数来生成我的类

因此,与前面的类定义不同,我将使用如下内容:

head = make_elem_class("head")
我被困的地方 此函数应创建一个类。这个类中的
\uuuu init\uuu()
方法应该从它继承的类中调用
\uuuu init\uuu()
方法

我试图使这个函数成为
make_elem_class()
函数,它看起来是这样的:

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元素”)
我得到以下错误:

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
回溯(最近一次呼叫最后一次):
文件“elements.py”,第118行,在
html(“html元素”)
文件“elements.py”,第20行,在init中
super()
TypeError:object.\uuuu init\uuuu()不接受任何参数
我猜这与空的
super()
调用有关,所以我尝试使用
super(elem,self)
。但它显然没有更好的效果

我怎样才能做到这一点


NB:如果我在
type()
调用中从字典中删除
“\uuuuu init\uuuuu”:init
,它可以正常工作,但标记在元素中没有正确设置。我还尝试将
{“tag”:name}
直接传递给
type()
,但也没有效果。

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

或者更确切地说,你不能,除非你自己提供上下文;您需要在此处将名称
\uuuuuu类\uuuuuu
设置为闭包:

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()。请注意,我将
content
的值传递给
elem.\uuuu init\uuu
方法,而不是
None
;你不想失去这个价值

如果是这样,请在调用
super()
时显式命名类和
self
;同样,课程将从结尾处开始:

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

一个更直截了当的解决方案,比如推断类的标记
\uuuuu name\uuuu
,是什么意思

class elem:
    def __init__(self, content="", tag=None, attr={}, tag_type="double"):
        """Builds the element."""
        self.tag = tag or self.__class__.__name__
        ...
然后:

class div(elem): pass
class head(elem): "Optional docstring for <head>"
...
class div(elem):通过
类头(元素):“的可选文档字符串”
...

少一点魔力(有争议),更明确一点。:-)

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

由于您不希望同一标记类的所有实例共享同一标记名,因此最好将其设置为类变量而不是实例变量。例如

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\u type
)是这样的,如果指定了
tag\u type
,那么实例将设置它的
tag\u type
,但是所有其他实例都将依赖类作为默认值。

您也可以生成一个简化的
elem
类吗?我也无法复制您的确切异常,而是得到
运行时错误:super():\uuuuu class\uuuu未找到单元格
。您是否在某处使用了
make_elem_class
作为静态或类方法?或者,您是否在某处设置了
\uuuu class=elem
?@MartijnPieters当然!我编辑了我的帖子,
\uuuu init\uuu()
方法完成了。在我的代码中没有
\uuuuu class\uuuu=elem
;仅使用发布的
elem
类无法获得异常(此处不需要
make\u html()
方法,它永远不会到达)。您的解决方案两者都能完美工作!它可能会被简化(我不是Python专家,可能没有正确的词汇表),但会在本地范围内搜索我们传递给它的类名(
\uuuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?@vmonteco:查看已链接的
super()
查找一个闭包单元格,当您a)在
块中创建一个方法,并且
b
在该方法中使用名称
super
时,Python编译器会自动提供该闭包单元格。@vmonteco:通常,只有在使用父函数作用域中的名称时,才会创建闭包单元格(如
make_elem_类中的
name
,要能够在
init()
函数中使用,必须创建这样的单元格)。老实说,我不确定这是否不那么神奇。幸运的是,没有HTML标记恰好存在。使用class属性可能是更好的主意
self.tag
然后从
elem.tag
读取,您可以在子类中覆盖它。在传递给
type()的字典中轻松设置
'tag':name
.F