0

Here is the code, it basically uses a win32com instance and gets the attribute and sets the attribute. More methods will be added to this class later.

import win32com.client

class WORD(object):

    def __init__(self):
        self.word = win32com.client.Dispatch("Word.Application")

    def __getattr__(self, val):
        try:
            print(1)            
            attr = getattr(self.word, val)
        except:
            print(2)
            attr = super().__getattr__(val)
        return attr

    def __setattr__(self, attr, val):
        try:
            print(3)
            setattr(self.word, attr, val)
        except:
            print(4)
            super().__setattr__(attr, val)    


app = WORD()

It outputs 2 for 635 times and a 4 at the end. Why? Thank you.

2
2
2
2
2
2
2
2
2
2
.
.
.
2
2
2
2
2
2
2
2
2
4
martineau
  • 119,623
  • 25
  • 170
  • 301
User
  • 3
  • 1

1 Answers1

1

Let's follow what happens here:

    def __init__(self):
        self.word = win32com.client.Dispatch("Word.Application")

self.word = ... executes setattr(self, ...) which tries to do getattr(self.word, ...), which leads to getattr(self, 'word'), which tries to do getattr(self.word, 'word'), which ends up in a recursive loop. Once Python's recursion limit is reached, a RecursionError is thrown. Your try...except blocks ignore this exception and eventually end the cycle by calling the corresponding methods on super().

A simple way to work around this and get the functionality that I am guessing you're after, is to change the initialiser as follows:

    def __init__(self):
        super().__setattr__('word', win32com.client.Dispatch("Word.Application"))

This bypasses your custom __setattr__ implementation for the property word so that this property is available inside those methods, avoiding recursion.

Seb
  • 4,422
  • 14
  • 23