Pycharm,Python 3 与 Type Hints

前言及环境假设

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

Python 3.5
在现在的 Python 社区,3 越来越成为主流,好几个重量级的库/框架都不在对 2 提供支持。而 3.5 是一个比较重要的版本( 如果是新项目,一般都直接 3.5/3.6 ),所以本文使用 3.5 。

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

总之,如果把 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

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

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

Python 2 的方式:Doc String

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

示例如下:

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值