gpt4 book ai didi

python - 使用 __slots__ 子类化一个类

转载 作者:太空宇宙 更新时间:2023-11-03 12:33:55 25 4
gpt4 key购买 nike

我正在尝试子类化 Scrapy 的 XPathSelector 并打补丁以支持 CSS3 选择器。

XPathSelector 定义如下:

class XPathSelector(object_ref):
__slots__ = ['doc', 'xmlNode', 'expr', '__weakref__']

def __init__(self, response=None, text=None, node=None, parent=None, expr=None):
if parent is not None:
self.doc = parent.doc
...

我将 XPathSelector 子类化并覆盖 __init__:

class CSSSelector(XPathSelector):
def __init__(self, *args, **kwargs):
translator = kwargs.get('translator', 'html').lower()

if 'translator' in kwargs:
del kwargs['translator']

super(XPathSelector, self).__init__(*args, **kwargs)

当我尝试使用 CSSSelector 时,我得到了 AttributeErrordocxmlNode 错误>表达式。将这些插槽手动添加到 CSSSelector 中也无济于事。

使用 __slot__ 子类化类的正确方法是什么?


我的完整代码在这里:

"""
Extends `XPathSelector` to allow CSS3 selectors via the `cssselect` library.
"""

from cssselect import HTMLTranslator, GenericTranslator
from scrapy.selector import XPathSelector, XPathSelectorList

__all__ = ['CSSSelector', 'CSSSelectorList']

class CSSSelector(XPathSelector):
__slots__ = ['doc', 'xmlNode', 'expr', 'translator']

def __init__(self, *args, **kwargs):
translator = kwargs.get('translator', 'html').lower()

if 'translator' in kwargs:
del kwargs['translator']

super(CSSSelector, self).__init__(*args, **kwargs)

if translator == 'html':
self.translator = HTMLTranslator()
elif translator == 'xhtml':
self.translator = HTMLTranslator(xhtml=True)
elif translator == 'xml':
self.translator = GenericTranslator()
else:
raise ValueError("Invalid translator: %s. Valid translators are 'html' (default), 'xhtml' and 'xml'." % translator)

def _select_xpath(self, xpath):
if hasattr(self.xmlNode, 'xpathEval'):
self.doc.xpathContext.setContextNode(self.xmlNode)
xpath = unicode_to_str(xpath, 'utf-8')

try:
xpath_result = self.doc.xpathContext.xpathEval(xpath)
except libxml2.xpathError:
raise ValueError("Invalid XPath: %s" % xpath)

if hasattr(xpath_result, '__iter__'):
return CSSSelectorList([self.__class__(node=node, parent=self, expr=xpath) for node in xpath_result])
else:
return CSSSelectorList([self.__class__(node=xpath_result, parent=self, expr=xpath)])
else:
return CSSSelectorList([])

def select(self, selector):
xpath = self.translator.css_to_xpath(selector)

return self._select_xpath(xpath)

def attribute(self, name):
return self._select_xpath('self::@' + name)

def text(self):
return self._select_xpath('self::text()')

class CSSSelectorList(XPathSelectorList):
def attribute(self, name):
return [x.attribute(name) for x in self]

def text(self, name):
return [x.text() for x in self]

我可以很好地初始化类:

>>> css_selector = CSSSelector(response)

但我到处都是 AttributeError:

>>> css_selector.select('title')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-150-d21b0f17d4cc> in <module>()
----> 1 css_selector.select('title')

<ipython-input-147-c855c7eaf9fa> in select(self, selector)
57
58
---> 59 return self._select_xpath(xpath)
60
61

<ipython-input-147-c855c7eaf9fa> in _select_xpath(self, xpath)
34
35 def _select_xpath(self, xpath):
---> 36 if hasattr(self.xmlNode, 'xpathEval'):
37 self.doc.xpathContext.setContextNode(self.xmlNode)
38 xpath = unicode_to_str(xpath, 'utf-8')

AttributeError: xmlNode

最佳答案

使用 __slots__ 没有错。问题是您没有从子类中调用 XPathSelector__init__

super(XPathSelector, self) 应该是super(CSSSelector, self):

class CSSSelector(XPathSelector):
def __init__(self, *args, **kwargs):
# ...
super(CSSSelector, self).__init__(*args, **kwargs)

在 Python 中看到一个关于 super 的好话题:Understanding Python super() with __init__() methods .

更新。

就其值(value)而言,如果您使用 __slots__ 扩展一个类,通常您也应该在子类中添加 __slots__,至少是一个空子类。否则,无论如何都会创建每个实例的字典,从而使基类的 __slots__ 变得毫无用处。来自 Python Reference :

The action of a __slots__ declaration is limited to the class where it is defined. As a result, subclasses will have a __dict__ unless they also define __slots__ (which must only contain names of any additional slots).

关于python - 使用 __slots__ 子类化一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14187571/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com