简体   繁体   中英

Pycharm Type-Hinting of Class Fields / Instance Variables

Whenever we need a new object in Java, we declare the type and the name choose to give it a initial value or not. In Python we can't do this, because we don't declare types.

How can I get around this because if the types are not declared; I am not getting any code completion hints. Like the fields of a particular object or any methods we can call on the object...

 class Album:
    def __init__(self, name, Photo, next):
        self.name = name
        self.Photo = None
        self.next = next

    def __str__(self):
        return "Album name is: " + self.name


class Photo:
    def __init__(self, name, caption, Tag, next):
        self.name = name
        self.caption = caption
        self.Tag = Tag
        self.next = next

    def __str__(self):
        return "Photo name is: " + self.name + " with caption: " + self.caption


class Tag:
    def __init__(self, type, info, next):
        self.name = type
        self.info = info
        self.next = next

    def __str__(self):
        return "Photo name is: " + self.name


def addPhoto(toEdit, photoName, caption):

   if isinstance(toEdit, Album):    
        if toEdit.Photo is None:
            toEdit.Photo = Photo(photoName, caption, None, None)    
        else:

            tempPhoto = toEdit.Photo
            prev = None
            isFound = False 
            while tempPhoto != None:

                if tempPhoto.name.lower() == photoName.lower():
                    isFound = True
                    break

                prev = tempPhoto
                tempPhoto = tempPhoto.next

            if isFound == False:
                prev.next = Photo(photoName, caption, None, None)

            else:
                print("Photo " + photoName + " already exists in " + toEdit.name)


def deletePhoto(toEdit, photoName): 
    if isinstance(toEdit, Album):
        if photoName in toEdit.Photo.name:
            if toEdit.Photo.next is not None:
                toEdit.Photo = toEdit.Photo.next
                return True

            else:
                toEdit.Photo = None
                return True
        else:
            Photo = toEdit.Photo.next
            Photo_prev = None

            while Photo is not None:
                if Photo.name in photoName:
                    prev.next = Photo.next

                prev = Photo
                Photo = Photo.next

        print("Removed photo: " + photoName + " from " + toEdit.name)

pPtr = album1.Photo  
while (pPtr != None):
    print(pPtr)
    pPtr = pPtr.next

So whenever I try to do pPtr = album1.Photo and then try to access any fields of that pPtr object I get no suggestions in PyCharm. I need to know whether I am doing this wrong or if PyCharm is at fault.

The implementation is one giant linkedlists. Albums nodes contain Photo nodes which contain Tag nodes

First off, as one of the commenters on your question pointed out, using upper_case variable names confuses them with Classes/Types. If you look at your question, you'll see it even confused the Stackoverflow code-formatter.

Additionally, in your Album constructor, you are masking the global variable "Photo" with a local parameter. That might confuse PyCharm, especially when you do the following. So for my answer + test below, I renamed your parameter to a lower-case photo so that it doesn't interfere.

**Edit: ** I did find a better way. See "The Right Way".

First Attempt

class Album:
    def __init__(self, name, photo, next):
        self.name = name
        self.photo = self.get_photo(photo)
        self.next = next

    def get_photo(self, photo):
        """
        @rtype: Photo
        """
        return photo

    def __str__(self):
        return "Album name is: " + self.name

The way it works is it uses the PyCharm type-inference. See here for details on how it works.

And below a screenshot of it working:

答案工作的形象

Note: I do not recommmend doing this, as it is a hack. I came across your question as I'm attempting to find out if there is a better way of doing this in PyCharm.

The Right Way

The right way of doing this is to give PyCharm the type of the variables in the constructor. Essentially, moving the type-binding from the method as above, and into the constructor as part of the docstring entry "type".

class Album:
    def __init__(self, name, photo, next):
        """
        @type name: str
        @type photo: Photo
        @type next: str
        """
        self.name = name
        self.photo = photo
        self.next = next

    def __str__(self):
        return "Album name is: " + self.name


class Photo:
    def __init__(self, name, caption, Tag, next):
        self.name = name
        self.caption = caption
        self.Tag = Tag
        self.next = next

photo1 = Photo("name.txt", "caption", "tag", "next")

album1 = Album("TestAlbum", photo1, "next")

album1.photo.#code completion working here

It is a limitation of dynamically typed languages. Static analysis of types is only possible to some degree. So don't expect as much autocompletion as in statically typed languages.

You should follow the intellij procedure here:

https://www.jetbrains.com/help/pycharm/type-hinting-in-product.html

Example:

class SomeClass(object):
    __logger = None  # type: Logger

 def __init__(self):
     self.__logger = logging.getLogger('root')

def some_method:
    self.__logger.info('hint completion is working here :P')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM