Python中如何避免在每个函数开始时使用assert isinstance进行类型检查?
写的是一个简单的物理仿真计算程序。这算好习惯还是坏习惯? 养成这个习惯是因为有一次被 numpy 的 1x1 数组坑了好久……
Python中如何避免在每个函数开始时使用assert isinstance进行类型检查?
用 python 3.7
用 assert 做类型检查不是个好主意,因为生产环境用 python -O 运行时断言会被禁用。Python 有更好的方式:
1. 类型注解 + 静态检查
from typing import List
def process_items(items: List[str]) -> int:
return len(items) # 让 mypy/pyright 在开发时检查类型
2. 使用 isinstance 但更优雅
from functools import wraps
from typing import get_type_hints
def validate_types(func):
@wraps(func)
def wrapper(*args, **kwargs):
hints = get_type_hints(func)
# 检查参数类型匹配
return func(*args, **kwargs)
return wrapper
@validate_types
def example(name: str, count: int) -> str:
return name * count
3. 第三方库
pydantic: 数据验证和设置管理typeguard: 运行时类型检查装饰器beartype: 快速的运行时类型检查
4. 契约式设计
from icontract import require
@require(lambda x: isinstance(x, str))
def process_string(x):
return x.upper()
建议:优先用类型注解配合静态检查,真有运行时需求再用装饰器或第三方库。
typing 不行吗?
typing 只是起提示作用,类型检查并不是强制的
3.5 之后,可以用 type hint,然后在运行前,用 mypy 检查一遍
没办法,动态类型就是这样,动态类型是把双刃剑。
我一般用 python 写比较大一点的项目,会加上简单类型说明和比较详细的 docstring。
之前只是耳闻。刚才看了一下你发的链接,感觉这个手段入侵性有点强,后面顶不住了再考虑吧……
正常操作, 动态语言都这样. 现在又在加 typing 啊什么的, 我 TM 都写类型了,我为什么不用静态语言, 而且这个 typing 还不能保证编译安全, 鸡肋一个
动态语言就是这样的呀,不要用静态的思路去考量动态语言。用动态语言的意义不就是先把应用做出来,把结果跑出来吗。要性能和安全的时候再用 Java,C++就好了。
这样会很慢啊…输入输出要按契约编程,写在 docstring 里就可以了
确实如此,特别是复杂一点的类型还要写一坨代码,唯一有点用的地方是对 IDE 解析友好,代码提示更清晰准确。如果真的非常追求静态类型检查,真的不必用这种方法,换一种语言更好,比如 C#。
#12 动态语言的代码提示基本为 0, 写代码 10 分钟, 查手册看参数和返回值半小时
没事,我写 ruby 也是这样。
来用 F#吧
爽歪歪。
题主问题的本质在于: 对于一个语言的心理定位和现实使用情况不符合.
对于我来说, Python 是 better bash, 只要能写脚本就 OJBK 了, 我不关心:
1. GIL
2. Python3.X, 我现在还在用 Python2.6(CentOS6 自带的)
3. 静态类型
因为这些东西 bash 也没有, 我用 bash 写脚本也不会享受到这些优点.
仿真计算我不懂, 但是在 Python 之前一定有其他软件可以做, 题主应该更关注于 Python 带给了你什么优势, 而不是它和 xxx 语言相比有什么劣势.
脚本语言的命, 别操着静态工程语言的心.
用了 typing 之后 pycharm 的自动补全还是挺爽的,如果库作者相应的 doc string 里写明了参数类型和返回值也能进行类似的参数推导
#17 给你返回一个 map, tuple 你怎么做自动补全, 怎么知道返回值中到底有什么? Python 的问题是脚本语言的灵活性给程序员带来了偷懒的机会, 返回 map 最简单, 但是后续的维护太难做.
#9 你 Java 干嘛加 var 类型推导呢 好好地手写不就行了
如果做科学计算,还是 fall fast 比较好,我觉得可以
map 是最难受的,找不到一个办法能标注自己到底有哪些 key,看了 typing 的文档里也没有…
#19 你说的是 Java 10 Local Variable Type Inference, 随手 google 了一下
https://developer.oracle.com/java/jdk-10-local-variable-type-inference
Clearly, defining types for fields and method signatures enforces a contract that needs to be respected and this helps with maintenance as well as understanding. However, declaring types for intermediate expressions may feel less useful and cumbersome.
这篇文章我没看完, 但是看到这里你大概知道了 java 的 var 关键词是用来干嘛的了吧.
其次, 一个语言支持的特性要全都用上吗? 我不这么认为, 我的变量都是后期 refactor 出来的, IDE 自动提取, 至于说 IDE 帮我生成的是 var 还是具体类型, 我是一点都关心
#21 我之前写个脚本都快被搞崩溃了, 更别说大项目中使用 map 了, Java 好一点, 大家都会定义一个类, 也不是强制要求,但是大部分编码规范是这样的
随着各类程序设计工具的完善,动态语言引以为傲的简洁与动态性的优势渐渐消失,甚至在大多数时候成为鸡肋。容易注意到,现在流行的新语言都拥有静态类型系统,而早年流行的动态语言,也渐渐加上了静态类型的帽子(或方言),以便分析工具进行静态分析,把错误消除在编程阶段
动态类型语言只能写小东西
大一点查问题查死你
借用王垠的一句话:“竟然还有五头的人”
无
我觉得是你结构设计问题
openstack 那么大项目都没这么搞
一般的克通用的函数检查接口用装饰器就完了
定位不清晰啊,老铁,Python 的定位就是 灵活 脚本,把它该干好的事情 干好就行了
老想着用一门语言 解决所有问题 ,不是傻就是蠢
31 楼老哥说的对
mypy 这种检查一遍项目
需要良好的命名习惯和 docstring
写脚本迅速解决问题 跟 工程化应用 场景完全不一样
以后不这么搞了。这次这样搞是因为以前学 Python 时把一个很复杂的基础方程组写在 Python 里面了,懒得改……


