【问题标题】:Pycharm Type-Hinting of Class Fields / Instance Variables类字段/实例变量的 Pycharm 类型提示
【发布时间】:2014-09-01 07:47:53
【问题描述】:

每当我们在 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 有问题。

实现是一个巨大的链表。 Albums 节点包含 Photo 节点,其中包含 Tag 节点

【问题讨论】:

  • Annotations 可能会对您有所帮助
  • 请注意,在 Python 中,将变量保留为小写通常是明智之举。例如,您有一个类Tag 和一个变量Tag,这会混淆情况。 (它甚至混淆了这里的语法荧光笔)。
  • 什么是专辑 1?如果您想创建 Photo 的实例,只需键入 pPtr = Photo() 然后您可以调用 pPtr.name 例如。请更改该变量名称 pPtr
  • Stop writing classes in Python。在 Java 中,您必须创建类,因为没有别的。你说“实现是一个巨大的链表”,每个链表有其他类实例。你不应该在 Python 中使用链表。记住类实例只是字典也很重要。
  • 不幸的是,您遇到了鸭子打字的痛处之一。

标签: python pycharm type-hinting


【解决方案1】:

首先,正如您问题的一位评论者所指出的那样,使用大写变量名会将它们与类/类型混淆。如果您查看您的问题,您会发现它甚至会混淆 Stackoverflow 代码格式化程序。

此外,在相册构造函数中,您使用本地参数屏蔽全局变量“Photo”。这可能会使 PyCharm 感到困惑,尤其是当您执行以下操作时。因此,对于下面的答案 + 测试,我将您的参数重命名为小写照片,以免干扰。

**编辑:**我确实找到了更好的方法。见“正道”。

第一次尝试

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 类型推断。有关其工作原理的详细信息,请参阅here。

下面是它的工作截图:

注意:我不建议这样做,因为它是一种 hack。当我试图找出在 PyCharm 中是否有更好的方法时,我遇到了你的问题。

正确的方式

这样做的正确方法是在构造函数中给 PyCharm 变量的类型。本质上,将类型绑定从上述方法中移到构造函数中,作为文档字符串条目“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

【讨论】:

  • 如果 Photo 类在其他子模块中怎么办?我必须将它导入专辑的模块才能注释?
【解决方案2】:

这是动态类型语言的限制。类型的静态分析仅在某种程度上是可能的。所以不要期望像静态类型语言那样自动完成。

【讨论】:

  • @daniula 它怎么不回答这个问题?这是关于如何获得自动完成功能,我已经指出它不可能达到 OP 所期望的程度。如果 IDE 不能静态推断类型,它显然不能提供基于类型的自动完成。
  • Python 中有类型提示,PyCharm 对此有很好的支持,允许自动补全。
【解决方案3】:

您应该在此处遵循 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')

【讨论】:

    猜你喜欢
    • 2020-02-18
    • 2013-12-26
    • 1970-01-01
    • 2022-11-02
    • 2016-08-05
    • 2015-11-23
    • 2013-09-28
    • 2012-08-30
    • 2016-03-22
    相关资源
    最近更新 更多