比如说:
import numpy as np
class Person:
    name: str
    age: int
    hobbies: np.ndarray
   
person = Person()
person.age = "12" # raise TypeMismatched exception
Github 上面找到几个在 Python3 测试一下然而并不能用。现在开发 debug 中遇到的 10 个 需要呕心沥血 debug 的中有 9 个都是因为类型问题,镶嵌类型尤其难搞。def 虽然有 type hints,但是函数过多时会封装成这样:
class Params:
    param1 = 'hello'
    param2 = '...'
    ...
    param7 = '...'
所以为了保持代码干净,最好还是在 class 里加入类型的检查。大家除了 IDE、眼球 parse 和记忆力还有什么好办法?
|  |      1Tyanboot PRO 类型标注这个只有在 3.6 及以上的版本才支持的. 解决办法就是升级你的 python 到 3.6 | 
|  |      2so1n      2018-07-26 00:32:47 +08:00 via Android  1 有个叫 attrs 的库 | 
|  |      3ligyxy      2018-07-26 01:12:26 +08:00 via Android Data Classes | 
|      4Cbdy      2018-07-26 08:25:22 +08:00 via Android 换有类型的语言 | 
|  |      5araraloren      2018-07-26 08:51:54 +08:00 可选类型的语言是多么明智。。 | 
|      6netfee      2018-07-26 09:40:26 +08:00 via Android  1 class People: def __init_(self, name: str=None, age: int=0) ->None: --- def find_all_people() ->[People]: --- 这样实现类型注释,方便 ide 预检查错误,参考 pep 484 type hint https://www.python.org/dev/peps/pep-0484/ Python 3.5 就提供这种语法支持了。而当前主流 Linux 发行版预置的 Python3 都是 3.5+以上版本了,所以真的可以全面转到 py3 了。到 V3.6 还提供 f-string 语句支持( pep 498 )。 | 
|  |      7zhuangzhuang1988      2018-07-26 09:59:52 +08:00 换语言 | 
|      8xpresslink      2018-07-26 10:05:45 +08:00  1 有个比较 lowbility 但是有效的办法就是,在函数或类最开始 就把要用到所有变量名加上类型前缀或后缀并赋初始值,比如下面这样: def foo(): int_a = 0, a_int=0 , str_b='', b_str='' 过程中严禁同一变量名改换类型使用,这样 IDE 就可以比较好的类型推断了。 不过这样写 python 的话还不如直接用够浪( golang ) | 
|      9karllynn      2018-07-26 11:20:25 +08:00 升级到最新的 Python 或者不用在意类型,用的时候强制转换就行了…比如这个 age,你先 age = int(p.age)不就完了 | 
|      10Philippa OP 当把 object 作为参数时,python3.6 是不能检查 object 的 attr 的类型的。变量名包括类型已经有了,然而变量多层传递后也不会有大的作用。因此: ``` class Person: name: str age: int ``` 以上这种语法是无效的,Python3.6 也根本不支持这种语法,我不知道大家回答这个是因为误解了还是不知道这一点。 但下面这一个可以。 ``` class TypeMismatched(Exception): pass class Person: def __init__(self, name: str, age: int): self.name = name self.age = age def __setattr__(self, name, value): # Invalid for class comparsion if hasattr(self, name) and type(self.__dict__[name]) != type(value): raise TypeMismatched self.__dict__[name] = value person = Person(name='Jane', age=12) print(person.name) print(person.age) person.age = '14' print(person.age) # raise TypeMismatched Exception ``` 因此想了想,用 type hints 作为 class 属性的首次检查,重载__setattr__,加入检查方法,作为以后 mutable 值的检查。上面的 type(variable_a) == type(variavble_b)有缺陷,需要再改进一下,但基本思路就这样了。 | 
|      11Philippa OP 为什么 markdown 不能用…… | 
|      12Philippa OP 可以在 class 里面加入一个参数, 虽然有点不雅观,mutable -> bool 来决定是否 mutable。一样地,在__setattr__里面做检查。 | 
|      13Philippa OP @xpresslink 换语言不是说换就换了,写 numpy 的话 golang 怎么写…… postfix 加类型的做法已经实行很久了,但效果有限,尤其对镶嵌类型的 list 等,numpy 有太多自定义类型,然而 python 本身却不可标注,再加上镶嵌,灾难就发生了 | 
|      14Philippa OP @karllynn 每次都 int(age)这样太丑了,妨碍其他人阅读你的代码,code review 肯定不让过,而且影响性能(虽说不大)。 | 
|  |      15GoLand      2018-07-26 13:03:18 +08:00  1 pydantic 了解一下。还有校验功能。结合 mypy 使用。 | 
|      16Philippa OP @GoLand 谢谢,这个库有些有用的工具可以用来自己封装。因为测试后发现,初始化为 str 后赋予 int 还是不会抛 error。当传入错误的类型,希望程序能够崩溃。 | 
|  |      17linkermlin      2018-11-19 18:10:16 +08:00 不编译检查了又能怎么样呢? 还是 Cython 靠谱。推荐了解下。 |