Are there any tricks I can employ to get IDEs to offer code completion for dynamically generated class attributes? For instance
class A:
def __init__(self):
setattr(self, "a", 5)
This code will set the class attribute of A
called a
to the value of 5
. But IDEs do not know about a
and therefore you do not get code completion for it. I've read that the __dir__
method can be hooked, but the suggestion made in that answer has not worked for me. Does anybody have any ideas?
I believe you will find the answer here. In short, Pycharm currently does not (and probably in the observable future will not) support dynamic attributes. That's because it analyzes code statically, and can't "see" what attributes a class might have. On the other hand, when you run your code in (say) iPython, once an instance of such class is created, the editor can get the attributes of the specific instance that resides in the memory, and thus show them in autocomplete. In such cases __dir__
helps. I assume that would be the case also with other IDEs.
So if you really need the autocompletion feature, you may want to try using Jupyter notebook. Still, you will have to instantiate your variable prior to getting autocomplete.
Another possible solution is to exploit that IDE supports .pyi
files (Python interface file stub). You can add to your code a little snippet that instantiate the class with dynamic attributes, and writes down a class interface file (.pyi
). Then IDE will use it for autocompletion. Obviously, this solution will have a "one run delay", but as in PyCharm you can switch to such file just by clicking on the asterisk near the class name, you can manually update it when having massive changes.
For this, I had to use Union type to get all the possible autocomplete options. It takes some extra time to write it, but when my program is huge, it is worth it.
from typing import Union
class dynamic1(object):
def __init__(self):
self.b = 5
self.c = 0
class dynamic2(dynamic1):
def __init__(self):
self.e = 10
self.d = 11
class dynamic3:
def __init__(self):
self.f = 12
def func(li):
return li[1]
def func() -> Union[dynamic1, dynamic2, dynamic3]:
a = [dynamic1(), dynamic2(), dynamic3()]
b = func(a)
return b
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With