【问题标题】:Add __getitem__ function to COM object in Python, OR: Overriding __slots__?在 Python 中将 __getitem__ 函数添加到 COM 对象,或者:覆盖 __slots__?
【发布时间】:2016-01-10 02:52:28
【问题描述】:

目标

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

我的一个对象是一个列表,我想迭代列表推导中的值。

什么有效

使用一些 COM 对象,我能够成功地执行以下操作:

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

而且,正如预期的那样,我得到了一个结果列表:

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

什么不...

但是,在其他类似的列表对象上,我尝试了同样的事情:

>>> [obj.Name for obj in myCom.anotherList]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\Python27\lib\site-packages\win32com\gen_py\<class_string>.py", line 6575, in __iter__
    raise TypeError("This object does not support enumeration")
TypeError: This object does not support enumeration

我尝试过的

所以我在定义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__ 方法,但这似乎是一个非常“适用于我的机器”的解决方案。我能做什么?

【问题讨论】:

    标签: python python-2.7 com pywin32


    【解决方案1】:

    解决方案

    我对任何替代方法都持开放态度,但这是我自己想出的。

    我发现有一个名为 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____getitem__setattr

    mod = win32com.client.gencache.GetModuleForProgID("MyProgram.Application")
    IAnotherList = mod.IAnotherList
    setattr(IAnotherList, '__getitem__', generic_getitem)   
    setattr(IAnotherList, '__iter__', com_generic_iter)
    

    来源

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-20
      • 2020-07-02
      • 2015-06-25
      • 2020-12-28
      • 2021-06-04
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      相关资源
      最近更新 更多