Pycharm,Python 3 与 Type Hints

前言及环境假设

Pycharm 2017
低版本的 Pycharm 并不支持 Type Hint,因此这里假设是比较新的版本。html

Python 3.5
在如今的 Python 社区,3 愈来愈成为主流,好几个重量级的库/框架都不在对 2 提供支持。而 3.5 是一个比较重要的版本( 若是是新项目,通常都直接 3.5/3.6 ),因此本文使用 3.5 。编程

静态类型很重要
因为我并不是相关专业人士,这里姑且这样称呼吧。因为 Python 是动态语言,因此 Type Hint 与 C++/Java 那样的静态类型并非一回事,仅仅是 IDE 提示使用(都已经选择了动态语言,还要啥锤子,凑合用吧 :))。好在如今大部分人都会使用 IDE 编程(指:编写生产代码 ),因此 Type Hint 啥的,仍是可堪一用的。bash

总之,若是把 Java/C++ 的那种比喻成火箭大炮,那Type Hint 就是打火机。左看右看,用打火机都是要比“钻木取火”要好 :)。框架

可能的需求

对类型的标注,咱们可能有以下几个方面的需求。函数

一是入参。按照参数类型分,又能够分为以下几类:学习

  1. 基本内置类型,如 str,int,list
  2. 基本类型组合产生的复杂类型,如 list[int], dict[str, int]
  3. 用户自定的class,如 Person,Animal
  4. 函数参数,即 callable,好比回调参数:(value: str, index: int) => str

二是出参(返回值)。基本和入参的分类一致,不在赘述。ui

下面咱们来看看,在 2 和 3 中,如何分别实现咱们上面列举的需求。spa

Python 2 的方式:Doc String

Pycharm 对此有比较完备的支持,基本够用,惟一的缺点是繁琐。code

示例以下:htm

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def get_name(self):
        return self._name

    def get_age(self):
        return self._age


class Py2TypehintTester:
    def test1(self, a, b, c):
        """第一种需求 基本很容易知足 :type a: str :param a: :type b: str :param b: :type c: list :param c: :rtype: list :return: """

        return [a, b, c]

    def test2(self, a, b, c):
        """第二种需求 也很容易知足,只不过须要遵循 Pycharm 规定的语法, 它才能正确解析 :type a: list[str] :param a: :type b: list[int] :param b: :type c: dict[str, int] :param c: :rtype: dict[str, str] :return: """

        for item in a:
            item.upper()

    def test3(self, p):
        """第三种需求 也很容易知足. 不过须要对应的 class 在本module 的空间内( 好比, 从别处 import 进来也是能够的) :type p: Person :param p: :return: """

        age = p.get_age()

    def test4(self, callback):
        """第四种需求 会让你容易知足, 须要遵循特定写法 :type callback: (str, int) -> str :param callback: :return: """

        s = 's'
        i = 1

        result = callback(s, i)
        print(result)  # 能正确推导为str
复制代码

这种方式的优势很明显,即: 没啥依赖,只须要遵循规定的写法就行了。

Python 3 的方式:Type Hint

这种方式是官方规定的,与上面一种方式比起来,基本上简洁许多,并且也很符合直觉,可能须要一段时间适应。

示例以下:

import typing  # 需求导入这个库

# 生成复合类型, 这段代码请无视
FloatVector = typing.List[float]
StrList = typing.List[str]
MyT = typing.TypeVar('T')


class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def get_name(self):
        return self._name

    def get_age(self):
        return self._age


class Py3TypehintTester:
    def test1(self, a: str, b: str, c: str) -> list:
        """第一种需求 很简单, 形式比较简洁 :param a: :param b: :param c: :return: """
        return [a, b, c]

    def test2(self, a: typing.List[str], 
                    b: typing.List[str], 
                    c: typing.Dict[str, int]) -> typing.Dict[str, str]:
        """第二种需求 比较简单, 须要先了解 typing 这个库 :param a: :param b: :param c: :return: """

        return {
            'str': 'str1'
        }

    def test3(self, p: Person):
        """第三种需求 比较简单 :param p: :return: """

        print(p.get_age())

    def test4(self, callback: typing.Callable[[str, int], str]):
        """第四种需求 稍复杂, 须要先仔细阅读下代码 不过这种需求基本出现的频率很少, 倒也不影响大局 :param callback: :return: """

        s = 's'
        i = 1
        result = callback(s, i)
        print(result)  # 能推导为str
复制代码

个人作法

if >= 3.5:
    使用第二种,毕竟简洁许多,并且也没啥学习成本,十几分钟的事
    要求也比较高: 对 IDE 版本和 Python 版本均有要求
else:
    使用第一种,能够视做过渡吧,反正兼容性是最好的,哪一个版本的 Pycharm 都能正确提示
复制代码

附录

  • Pycharm type hint 文档:https://www.jetbrains.com/help/pycharm/type-hinting-in-pycharm.html
相关文章
相关标签/搜索