我在“datetime”的例子中停止它,在lxml的一个真实例子中重写
(这可能很奇怪,因为英语在谷歌翻译中被翻译是我的声明,我很抱歉。)
我认为我喜欢lxml非常好的表现,但来源难以阅读
如果您正在积极使用XML,我经常也可以修改python代码
时间已经过去了,因为很难理解,因为很难理解
我花时间调试和修复
例如,我认为通常在搜索时如下:深层XML层次结构。
elem = lxml.etree.parse ("xxx/xxx/sample.xml").getroot()
elem.xpath("//depth3/text()")[0]
elem.find("./depth1/depth2/depth3").get("attr1").text
我想使用如下。
(使用此代码只是我。)
elem.depth3.text (Ex.1)
OR
elem.depth1.depth2.depth3.text (Ex.2)
我尝试过类继承是第一个实现这个。
您已经通过参考“在lxml中使用自定义元素类”进行了一些自定义
我使用__getattr__
来搜索XML元素。
from lxml import etree
class CustomElement (etree.ElementBase):
def __ getattr__ (self, k):
ret = self.xpath ("/ /" + k)
setattr(self, k, ret)
return getattr(self, k)
成功的例子(例1)
但是(Ex.2)的示例变为属性错误__getattr__
在返回etree._Element depth1的实例中不存在。
虽然不是(补充)实用,但我在第一个问题中使用了一个例子,在“易于理解”的第一个问题中增加了“毫秒”。
有人认为这是一种使用ctypes模块向lxml的Element类添加函数的方法。
import ctypes
import lxml.etree
class PyObject_HEAD(ctypes.Structure):
_fields_ = [
('HEAD', ctypes.c_ubyte * (object.__basicsize__ -
ctypes.sizeof(ctypes.c_void_p))),
('ob_type', ctypes.c_void_p)
]
def __getattr__(self, k):
ret = self.xpath("//" + k)
setattr(self, k, ret)
return getattr(self, k)
_get_dict = ctypes.pythonapi._PyObject_GetDictPtr
_get_dict.restype = ctypes.POINTER(ctypes.py_object)
_get_dict.argtypes = [ctypes.py_object]
EE = _get_dict(lxml.etree._Element).contents.value
EE["__getattr__"] = __getattr__
elem = lxml.etree.parse("xxx/xxx/sample.xml").getroot()
elem.xpath("//depth3")[0]
=>返回_Element对象
from ispect import getsource
print getsource(elem.__getattr__)
=> def __getattr__
(self,k):
=> ret = self.xpath(“//”+ k)
=> setattr(self,k,ret)
=> return getattr(self,k)
添加了来源..
elem.depth3
=> AttributeError ..没有属性'depth3'
我不知道是否或应该如何使用“PyObject_GetAttr”来写
请告诉我。
最好的问候
====================上一个问题============================ =======
我正在尝试增强ctypes。
添加功能通常顺利。
但是,如果添加特殊方法并且为什么?
import ctypes as c
class PyObject_HEAD(c.Structure):
_fields_ = [
('HEAD', c.c_ubyte * (object.__basicsize__ -
c.sizeof(c.c_void_p))),
('ob_type', c.c_void_p)
]
pgd = c.pythonapi._PyObject_GetDictPtr
pgd.restype = c.POINTER(c.py_object)
pgd.argtypes = [c.py_object]
import datetime
def millisecond(td):
return (td.microsecond / 1000)
d = pgd(datetime.datetime)[0]
d["millisecond"] = millisecond
now = datetime.datetime.now()
print now.millisecond(), now.microsecond
这会打印155 155958
,确定!
def __getattr__(self, k):
return self, k
d["__getattr__"] = __getattr__
now = datetime.datetime
print now.hoge
这不起作用,为什么?
Traceback (most recent call last):
File "xxxtmp.py", line 31, in <module>
print now.hoge
AttributeError: type object 'datetime.datetime' has no attribute 'hoge'
答案 0 :(得分:0)
我认为你不能以这种方式覆盖__getattr__
。基本上,您正在攻击对象的__dict__
以包含新方法。如果你打电话给now.millisecond
,原来的“属性getter”会被调用,查看dict,然后返回你的新方法。我不确定这个属性getter所在的位置(可能在C代码中),但它不能在它查找的字典中 - 所以你不能用这种方式覆盖它。
您可能会尝试__getattribute__
,但我不知道这是否有效。请注意,正确实施起来要困难得多(参见https://stackoverflow.com/a/3278104/143091)。
话虽如此,以这种方式破解内置组件可能不是一个好主意。许多python标准库代码可能依赖于您更改的行为,并且您的代码可能难以理解。对于那些了解python并试图理解你的代码的人来说,这也让人感到困惑。
我希望你没有这个讨厌的伎俩。我仅使用它来支持旧版本的python或库中不可用的功能,例如:
if not hasattr(wnck.Screen, "get_workspaces"):
def get_workspaces(screen):
return [screen.get_workspace(i) for i in range(screen.get_workspace_count())]
_get_dict(wnck.Screen)[0]['get_workspaces'] = get_workspaces
这样,我可以主要开发库的现代版本,但如果只缺少一个或两个函数,仍然支持古代版本,而不必更改我的代码。
答案 1 :(得分:0)
PyObject_GetAttr
(Objects / object.c)使用类型的tp_getattro
插槽,如果未定义前者,则使用tp_getattr
。它不会在类型的MRO中查找__getattribute__
。
对于自定义__getattr__
,您需要继承datetime
。您的堆类型将使用slot_tp_getattr_hook
(Objects / typeobject.c)作为其tp_getattro
。此函数将通过调用_PyType_Lookup
(Objects / typeobject.c)在类型的MRO中查找__getattribute__
和__getattr__
。
根据您的更新,请参阅"using custom Element classes in lxml"。对于多个结果,我已经攻击了一个__getattr__
钩子,它使用了索引的后缀表示法。否则默认为索引0。不可否认,我没有多想,但如果你总是使用索引,就可以避免与现有名字的冲突。
from lxml import etree
def make_parser(element):
lookup = etree.ElementDefaultClassLookup(element=element)
parser = etree.XMLParser()
parser.setElementClassLookup(lookup)
return parser
class CustomElement(etree.ElementBase):
def __getattr__(self, attr):
try:
name, index = attr.rsplit('_', 1)
index = int(index)
except ValueError:
name = attr
index = 0
return self.xpath(name)[index]
parser = make_parser(CustomElement)
例如:
>>> spam = etree.fromstring(r'''
... <spam>
... <foo>
... <bar>eggs00</bar>
... <bar>eggs01</bar>
... </foo>
... <foo>
... <bar>eggs10</bar>
... <bar>eggs11</bar>
... </foo>
... </spam>
... ''', parser)
>>> spam.foo_0.bar_0.text
'eggs00'
>>> spam.foo_0.bar_1.text
'eggs01'
>>> spam.foo_1.bar_0.text
'eggs10'
>>> spam.foo_1.bar_1.text
'eggs11'