How to typehint object attributes?

Lets say I have a class:
class A(object):
    pass
prettyPrint();
Auto-completing an instance of A doesn't give me any attributes (of course).

If I add an attribute to the instance, I will get proper completion:

a = A()
a.foo = "bar"
a.foo # Now foo completes properly, with string specific methods
prettyPrint();
However, since I know all objects of A will have an attribute "foo" of type str, I would like to get completion on "foo" all times (i.e when typing the a.foo = "bar" line.

So, I add foo to the class body:
class A(object):
    foo = None

a = A()
a.foo = "bar" # Now I get completion here, yay!
a.foo # But now, foo is not recognized as a string any more :(
prettyPrint();

I have tried adding a docstring to A:
class A(object):
    """
    :ivar foo: str
    """
    foo = None
prettyPrint();
But still nothing. I have tried with both epydoc and reST in all kinds of forms, but no luck.

How do I do this?
3 comments
"foo" in your example is a class attribute, not an instance attribute, so it should be annotated as :cvar rather than :ivar.
0
Well, my point is that foo will be an instance attribute, so that's what I want to document.

But, as I wrote, I have tried all kinds type hinting, including "attr", "type", "ivar". Nothing works.

Not even if it really was a class attribute:
class A(object):
    """
    :cvar foo: str
    """
    foo = None

A.foo.  # Completing here doesn't work
prettyPrint();
So, the question remains, how do I document instance attributes? I want to be able to tell PyCharm that the instance variable foo, in class A, is of type str.

The only thing that works is:
class A(object):
    def __init__(self, foo=None):
        """
        :type foo: str
        """
        self.foo = foo

A().foo.  # This works
prettyPrint();
But, that quickly gets tiresome since it requires many lines of boilerplate and typing each variable four times. Also, it interferes with the real __init__ method. I'd like my type hinting to be done in comments, not in code.

I would like to be able to do something like this:
class A(object):
    """
    :type foo: str
    """
prettyPrint();
2
I want to chime in on this discussion, because I feel that Markus is correct about this behavior. I came here for a slightly different use case, where the library provider wants to offer a mix-in class (e.g. not standalone, and will not have its own constructor):

class AMixIn(object):
    """
    :ivar foo: str
    :cvar bar: unicode
    """
    bar = None
    def a_method(self):
        self.foo = 'hello'

class OtherClass(AMixIn, OtherSuperclass):
    def another_method(self):
        print('My Foo is %s, bar is %s' % (self.foo, self.bar))
prettyPrint();

In PyCharm (as of my build 880d3c92 this morning) it ignores the type hinting in both :ivar and :cvar, which makes me think either this behavior is broken, or there is some subtlety to their use. They are also rendered in an ugly manner when one uses View > Quick Documentation.

In my experience, the only way to achieve the desired behavior is to either use :type foo: str in the pydoc or to use the #: :type: str directly above the class field.

As an added bonus, the self.foo = expression is marked as a warning, citing "Instance attribute defined outside of __init__"

I came here not necessarily to pile on a "me, too" but to see if this is, in fact, a regression and I should file a YouTrack for it?
1

Please sign in to leave a comment.