Pycharm类字段/实例变量的类型提示

6 投票
3 回答
3633 浏览
提问于 2025-04-18 12:51

在Java中,每当我们需要创建一个新对象时,我们会先声明这个对象的类型和名字,然后可以选择给它一个初始值或者不给。而在Python中,我们不能这样做,因为我们不需要声明类型。

我该如何解决这个问题呢?因为如果不声明类型,我就得不到任何代码补全的提示。比如说,某个对象的字段或者我们可以在这个对象上调用的方法……

 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

所以每当我尝试执行 pPtr = album1.Photo,然后想访问这个 pPtr 对象的任何字段时,我在PyCharm中都得不到任何建议。我需要知道我是不是做错了,还是PyCharm本身有问题。

这个实现是一个巨大的链表。相册节点包含照片节点,而照片节点又包含标签节点。

3 个回答

0

你应该按照这里的 IntelliJ 操作步骤来做:

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

举个例子:

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')
0

这是动态类型语言的一个限制。对类型的静态分析只能做到一定程度。所以不要指望能像静态类型语言那样有很多自动补全的功能。

6

首先,有人评论过你的问题,提到使用大写的变量名会让人把它们和类或类型搞混。如果你看看你的问题,就会发现连Stackoverflow的代码格式化工具都被搞糊涂了。

另外,在你的Album构造函数里,你用一个局部参数覆盖了全局变量“Photo”。这可能会让PyCharm感到困惑,尤其是当你接下来做某些操作时。所以在我下面的回答和测试中,我把你的参数改成了小写的photo,这样就不会互相干扰了。

**编辑:** 我找到了一种更好的方法。请看“正确的方法”。

第一次尝试

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

这个方法是利用了PyCharm的类型推断功能。想了解具体怎么操作,可以查看这里

下面是它工作时的截图:

答案工作时的图片

注意:我不推荐这样做,因为这是一种变通的方法。我看到你的问题是因为我在尝试找出在PyCharm中有没有更好的做法。

正确的方法

正确的做法是给PyCharm提供构造函数中变量的类型。也就是说,把类型绑定从方法中移到构造函数里,作为文档字符串中的“类型”部分。

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

撰写回答