在Python中,向COM对象添加\ugetitem\uuu函数,或者:重写\uuu slots\uu?

2024-09-27 20:18:08 发布

您现在位置:Python中文网/ 问答频道 /正文

目标

我正在使用pywin32和win32com操作第三方应用程序中的COM对象。在

我的一个对象是list,我想在list理解中迭代这些值。在

什么有效

使用某些COM对象,我可以成功地执行以下操作:

>>> [obj.Name for obj in myCom.someList if 'Test' in obj.Name]

正如所料,我得到了一份结果列表:

['Test1', 'Test2', 'Test3']

什么不能

但是,在其他类似的列表对象上,我尝试相同的方法:

^{pr2}$

我所做的一切

因此,我尝试在定义my_iter之后添加函数:

>>> myCom.anotherList.__iter__ = my_iter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\Python27\lib\site-packages\win32com\client\__init__.py", line 473, in __setattr__
    raise AttributeError("'%s' object has no attribute '%s'" % (repr(self), attr))
AttributeError: '<win32com.gen_py.Thingy instance at 0xDEADBEEF>' object has no attribute '__iter__'

我用__getitem__next做了同样的尝试,得到了同样的错误。我做了一些阅读,我认为这不起作用是因为与__slots__有关。。。不确定。在

正在检查生成的Python源代码

在检查了第一个堆栈跟踪中显示的.py之后,我查看了class ISomeList.__iter__的定义,因为这在本文的第一个示例中非常有效。在

from win32com.client import DispatchBaseClass
LCID = 0x0
class ISomeList(DispatchBaseClass):
    def __iter__(self):
        "Return a Python iterator for this object"
        try:
            ob = self._oleobj_.InvokeTypes(-4,LCID,2,(13, 10),())
        except pythoncom.error:
            raise TypeError("This object does not support enumeration")
        return win32com.client.util.Iterator(ob, '{<<<guid>>>}')

并将其与class IAnotherList.__init__进行比较:

class IAnotherList(DispatchBaseClass):
    def __iter__(self):
        "Return a Python iterator for this object"
        try:
            ob = self._oleobj_.InvokeTypes(-4,LCID,3,(13, 10),())
        except pythoncom.error:
            raise TypeError("This object does not support enumeration")
        return win32com.client.util.Iterator(ob, None)

所以,在我看来,赋值给ob失败了,然后我们提出了一个错误。在

我可以修改生成的源代码以添加__iter__方法,但这似乎是一个非常“在我的机器上工作”的解决方案。我能做什么?在


Tags: 对象inpyselfclientobjforobject
1条回答
网友
1楼 · 发布于 2024-09-27 20:18:08

解决方案

我对任何其他方法都很开放,但这是我自己想出的。在

我发现有一个名为GetModuleForProgID的win32com帮助器函数-正如您从名称中所期望的那样,它将使用COM程序ID并返回为包装该对象而生成的pywin32模块。在

代码

对我来说最有效的是:

""" define a method to do my iteration """
def com_generic_iter(self):
    current = 1 """ All the com objects I'm working with are 1-based indeces """
    while current <= self.Count
        yield self.Item(current)
        current += 1

""" I also wanted to support __getitem__ indexing: """
def generic_getitem(self, k):
    return self.Item(k)

""" Then dynamically add the method to the application wrapper when I generate my object """
mod = win32com.client.gencache.GetModuleForProgID("MyProgram.Application")
mod.IAnotherList.__iter__ = com_generic_iter
mod.IAnotherList.__getitem__ = generic_getitem
app = win32com.client.Dispatch("MyProgram.Application")

print [x.Name for x in app.AnotherList]

"""
[<win32com.gen_py.MyProgram.IItem instance at 0x12345678>,
 <win32com.gen_py.MyProgram.IItem instance at 0x87654321>,
 <win32com.gen_py.MyProgram.IDifferentItem instance at 0x99999999>]
"""

print app.AnotherList[1]

"""
<win32com.gen_py.MyProgram.IItem instance at 0x12345678>
"""

编辑:

您还可以使用__iter__和{}添加{},如下所示:

^{pr2}$

来源

我使用win32com documentation查找有关GetModuleForProgID的详细信息。在

相关问题 更多 >

    热门问题