Python编程中,写程序时需要考虑理论上概率为零的意外情况吗?

比如一个数值输入计算,要先判断它是否全为数字,然后再计算
Python编程中,写程序时需要考虑理论上概率为零的意外情况吗?

62 回复

前端验证 and 后端框架验证(比如 struts 的 form validation)


当然要考虑。理论上概率为零的意外情况,在实际编程中往往是导致程序崩溃或产生不可预测行为的根源。比如,从理论上讲,一个均匀分布的随机数生成器恰好生成0.5的概率是零,但如果你写 if x == 0.5:,这个分支在理论上是有可能被触发的,因为浮点数精度问题,x 可能非常接近但不等于0.5,导致逻辑错误。

更常见的例子是处理外部输入或系统资源。理论上,你打开一个文件,它应该存在,但用户可能删了它;分配内存应该成功,但系统可能耗尽了内存。这些情况在“理想”的理论模型里概率为零,但在现实世界里天天发生。

所以,防御性编程是关键。对于可能失败的操作,使用 try-except 来捕获异常;对于可能为 None 的值,在使用前先判断;对于浮点数比较,使用容差而不是直接相等。别指望理论概率,要处理实际可能发生的一切。

总结:必须考虑,这是健壮代码的基础。

如果理论上概率确实为 0, 那不需要考虑. 但是你确定是 0 吗?

java 不用, python 要用,避免猪队友硬传你个字符串"123"过来搞事情

概率为 0 的事件未必一定是不可能事件

你比如的情况,概率应该不是 0 吧。如果接收的输入情况较少,可以采用白名单的方式,比如只能数字类型才能通过;如果接收的输入情况较多,那么就用黑名单的方式,比如含有特殊字符不能通过

’ or 1 = 1’

外部输入数据一概设定为不可信,严防 sb 用户和猪队友

正是因为概率是 0 ,所以要加断言来标清楚。”这里的输入老子就只处理数字,不爽不要玩“

改这种风格代码非常爽,一改一跑一堆异常,解决完基本就没问题了

因为有猪队友的存在,所以一定要检验,亲身经历的事实。你永远无法想象你的队友有多蠢和粗心

概率为 0 的事情按常理说,你想都想不到;你能想到的,概率一定不为 0 。

因为计算机处理的内容是离散的,所以概率是 0 等同于不可能,不用处理。甚至小概率情况也不用管,比如硬件故障,这种完全管不了的情况也没法管。

但是期待用户输入的东西,用户输入乱七八糟的内容还是很有可能的,譬如:

- 用户输入了全角数字字符;
- 用户输入小数点的时候输入成了句号;
- 用户不小心在数字中间加了空格;
- 用户使用了千位分隔符,而你以为大家都不用千位分隔符;
- 用户使用 , 作为小数分隔符、使用 . 作为千位分隔符;
- 用户误触键盘其他键但是忘了删掉或者手太快;
- ……

python 类的?
执行次类型转换,但是不需要自己处理异常。
外部输入的参数有问题直接给他抛异常完事。

概率为 0 的事件不等于不可能事件……

要想模块化编程,必须把非法输入挡在函数的入口,多看代码大全

比如上次亚马逊 s3 服务器 down 掉,很多程序员就没处理这种情况

这个题目描述大概是有问题的,不过如果按照概率为 0 来理解的话,就是说假定用户都是专业用户,知道什么是未定义行为,输入内容保证符合要求。。。这种情况下,确实不需要考虑了

建议判断一下
1.你永远不知道你的队友会如何坑你
2.你永远不知道产品经理明天会不会改需求

永远不要相信外部的输入

工作认真对待该处理就处理;自己私下的小玩具就随意了。不过还是养成习惯最好。
工作上,我一般直接给 return ;
私下的朋友间的玩具,一般都是:
print(“搞事啊!!”);
exit(1)
#滑稽

理论概率为零就抛异常或者 assert 呗

不是很理解你这个理论上为 0 ……
放在实际开发中,确实是能想到的错误出现的概率都不见得为 0 。即使是内存 bit 读写会翻转,这种问题放到一些环境下也是需要进行处理的。
所以实际上开发中的错误一般是依据出现的上下文,可能产生的影响,或者说是各种处理方案的性价比来决定处理方案。
具体到你的例子,如果这个处理放在用户输入部分。即使你事先准备了各种提醒,那也架不住用户一不小心做了错误的输入。而且这种时候你不做处理那么程序可能会 crash ,用户体验会非常糟糕,那么最好是预先阻止掉各种意外的输入。如果你的处理只是一个内部调用的子函数,而且你已经和调用方约定好了输入只能是数字,那么再出现问题一般就是由调用方进行处理了。

断言就是这个时候用的

此话怎讲

哈哈哈。

用户输入,任何情况下都要检查。 API 调用,契约式编程无需检查,防御式编程要检查。

曾经有一个产品经理的用户名是 null

墨菲定律 有几率会发生的事情一定会出错 并且人类认为零概率的东西通常都有概率发生

就算前端可以帮你挡住,假如有人要发包测试呢,这东西没有 0%的,如果不涉及数据库和业务的话我懒得检测,涉及的话该怎么样就怎么样

“比如一个数值输入计算,要先判断它是否全为数字”

这种可能性远远大于 0

你举得例子和你的标题不符呀。
编程法则:不要信任任何用户输入

但比如说你是强类型语言申明了输入类型或者框架上做了处理,这种业务代码上就不用判断了

我的做法:

用户输入类的,需要检查并给出友好提示。

如果是其他函数调用提供的参数,那么做一次强制转换,失败了不管,异常直接抛出去,由调用方处理。

如果是类似 https://www.v2ex.com/t/355154 里面的 355154 ,理论合法用户不会出现非数字的情况,这种直接同函数调用,直接抛异常。但是别忘了设置整站的 500 页面及错误日志。

作为开放出去的公用库,只要不是强类型,都建议判断

另外,另一种思路是如果产生了这种异常分支,不处理这个分支对整个工程的影响,拿正文举例:
- 如果不处理的结果是输出不满足输入结果需要,那么可以不处理,因为输入结果就是错误的
- 如果不处理的结果是抛异常或者 Crash ,那么再怎么样都要处理,防止出现“你这个函数写的容错性怎么这么差”的攻击机会

这就需要采取边界检查的机制

哎,其实最悲剧的是你写程序考虑了很多低概率事件,设想了很多极端的情况,却发现一个用户都没有操作到那种情况简直想死,哦,因为没人用。哈哈!

never trust any input

先跑起来再说别的

射飞镖的时候射中盘上任意一点概率都是 0 ,因为点 /面=0 ,但是只要射中了概率为 0 的事情就发生了,所以概率为 0 不是不可能发生。

对于用户的输入,即便用户完全不可能输入一个值,也要防止测试给你一个意外输入。总之原则上就是考虑所有可能。

我觉得能做的验证还是尽量做,一方面防那些搞事情的,另一方面减少出一些奇怪的 bug 。墨菲定律不信不行啊

为 0 你考虑个卵!

如果真的概率很低,比如 CPU 的逻辑门被宇宙射线改变了电平,是可以不用考虑。可问题你提的用户输入是否数字,这个出错的概率太高了,起码有 2 , 3 成。

这种情况就需要学习一下防御性编程,因为概率为 0 ,除非你可以证明得到

首先要论证是不是真的概率为 0

看过一个说法,说过马路总是记得往马路两头看的人才是合格的程序员。起码这个说法还是挺有趣的,哈哈

这样啊,看了大家的评论感觉还是加上判断好一些,谢谢大家的回复~

多写两行 穷不了你 富不了我… 写不出吃亏 写不出上当…

不相信任何其他途径传过来的数据

如果你要这样做,那就别用 python 了,用静态类型语言。

保证程序的健壮性是很有必要的,因为你想不到的情况太多了
很多年前刚参加工作在一公司,软件发布前经过整个部门的轮番测试觉得已经不错了然后就发出去,结果短短几天用户反馈的 bug 达到 200 多个,当时测试跑过来说这个事我就惊呆了

不要相信提交的任何内容,不是基本原则吗?

之前有个和本地 zf 合作的一个项目
用户群是中老年人
你就会发现你认为这个概率为 0 的想法有多么不靠谱了

用户输入不符合预期的数据这种事情概率不应该是接近 1 的吗,楼主怎么会产生概率为 0 的错觉

考虑过服务器挂掉 1988 次,然后突然觉得,哼 怎么可能,不存在的

接近零!=零,即使概率再小他也不为零。不为零就是肯定会发生。为零是肯定不会发生。

莫非定律, Anything that can go wrong, will go wrong.
https://zh.wikipedia.org/wiki/%E6%91%A9%E8%8F%B2%E5%AE%9A%E7%90%86

37 楼说得对,概率为 0 并不表示不发生,所以不能一概而论要不要处理“概率为 0 ”的情况,最多只能讨论“不会发生的事件”要不要处理。

if(false) { alert("something happeded … "); }

我看到的说法是过单行道也看两边的程序员,哈哈

当然啦,你要问我考不考虑我说考虑,我就可以明确的告诉你

为啥我想起了人生三大错觉

曾经碰到一个奇葩的 bug ,一个 button 点 10 次以上程序会崩溃。特别佩服那个测试。

你的情况需要详细了解你所说的数值输入是什么
如果来源为 Web Form ,用户用第三方软件生成的文件之类的 那么必定要验证
如果来源为 自己另一处的代码 可以考虑加一个 验证 然后直接报 Runtime Error (提醒自己用的) 或者也可省略

你说的理论概率为 0 是不需要写代码做额外处理的
比如
do
uuid = UUID.generate_new_uuid
end while existing_uuids[uuid]

回到顶部