V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
klxq15
V2EX  ›  Python

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

  •  
  •   klxq15 · 2017-04-16 07:28:16 +08:00 via Android · 7086 次点击
    这是一个创建于 2809 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如一个数值输入计算,要先判断它是否全为数字,然后再计算
    61 条回复    2017-04-18 17:04:26 +08:00
    340244120
        1
    340244120  
       2017-04-16 07:38:55 +08:00 via Android
    前端验证 and 后端框架验证(比如 struts 的 form validation)
    eyp82
        2
    eyp82  
       2017-04-16 07:48:25 +08:00   ❤️ 3
    如果理论上概率确实为 0, 那不需要考虑. 但是你确定是 0 吗?
    lcorange
        3
    lcorange  
       2017-04-16 07:48:36 +08:00
    java 不用, python 要用,避免猪队友硬传你个字符串"123"过来搞事情
    lucifer9
        4
    lucifer9  
       2017-04-16 08:01:57 +08:00   ❤️ 3
    概率为 0 的事件未必一定是不可能事件
    wenzichel
        5
    wenzichel  
       2017-04-16 08:07:13 +08:00
    你比如的情况,概率应该不是 0 吧。如果接收的输入情况较少,可以采用白名单的方式,比如只能数字类型才能通过;如果接收的输入情况较多,那么就用黑名单的方式,比如含有特殊字符不能通过
    mozutaba
        6
    mozutaba  
       2017-04-16 08:13:08 +08:00 via Android
    ' or 1 = 1'
    k9982874
        7
    k9982874  
       2017-04-16 08:19:57 +08:00 via iPad
    外部输入数据一概设定为不可信,严防 sb 用户和猪队友
    mcfog
        8
    mcfog  
       2017-04-16 08:30:03 +08:00 via Android
    正是因为概率是 0 ,所以要加断言来标清楚。”这里的输入老子就只处理数字,不爽不要玩“

    改这种风格代码非常爽,一改一跑一堆异常,解决完基本就没问题了
    kongkongyzt
        9
    kongkongyzt  
       2017-04-16 08:42:11 +08:00 via Android   ❤️ 1
    因为有猪队友的存在,所以一定要检验,亲身经历的事实。你永远无法想象你的队友有多蠢和粗心
    0TSH60F7J2rVkg8t
        10
    0TSH60F7J2rVkg8t  
       2017-04-16 08:45:06 +08:00
    概率为 0 的事情按常理说,你想都想不到;你能想到的,概率一定不为 0 。
    geelaw
        11
    geelaw  
       2017-04-16 08:45:58 +08:00   ❤️ 3
    因为计算机处理的内容是离散的,所以概率是 0 等同于不可能,不用处理。甚至小概率情况也不用管,比如硬件故障,这种完全管不了的情况也没法管。

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

    - 用户输入了全角数字字符;
    - 用户输入小数点的时候输入成了句号;
    - 用户不小心在数字中间加了空格;
    - 用户使用了千位分隔符,而你以为大家都不用千位分隔符;
    - 用户使用 , 作为小数分隔符、使用 . 作为千位分隔符;
    - 用户误触键盘其他键但是忘了删掉或者手太快;
    - ……
    gamexg
        12
    gamexg  
       2017-04-16 08:50:02 +08:00 via Android
    python 类的?
    执行次类型转换,但是不需要自己处理异常。
    外部输入的参数有问题直接给他抛异常完事。
    codingadog
        13
    codingadog  
       2017-04-16 08:52:38 +08:00 via iPhone
    概率为 0 的事件不等于不可能事件……
    rogerchen
        14
    rogerchen  
       2017-04-16 09:01:43 +08:00 via Android   ❤️ 1
    要想模块化编程,必须把非法输入挡在函数的入口,多看代码大全
    wiselyv2
        15
    wiselyv2  
       2017-04-16 09:01:44 +08:00
    比如上次亚马逊 s3 服务器 down 掉,很多程序员就没处理这种情况
    codehz
        16
    codehz  
       2017-04-16 09:04:20 +08:00 via Android
    这个题目描述大概是有问题的,不过如果按照概率为 0 来理解的话,就是说假定用户都是专业用户,知道什么是未定义行为,输入内容保证符合要求。。。这种情况下,确实不需要考虑了
    as463419014
        17
    as463419014  
       2017-04-16 09:13:02 +08:00
    建议判断一下
    1.你永远不知道你的队友会如何坑你
    2.你永远不知道产品经理明天会不会改需求
    n6DD1A640
        18
    n6DD1A640  
       2017-04-16 09:16:16 +08:00
    永远不要相信外部的输入
    elfive
        19
    elfive  
       2017-04-16 09:17:47 +08:00
    工作认真对待该处理就处理;自己私下的小玩具就随意了。不过还是养成习惯最好。
    工作上,我一般直接给 return ;
    私下的朋友间的玩具,一般都是:
    print("搞事啊!!");
    exit(1)
    #滑稽
    cy18
        20
    cy18  
       2017-04-16 09:25:05 +08:00 via Android
    理论概率为零就抛异常或者 assert 呗
    unoyx
        21
    unoyx  
       2017-04-16 09:38:36 +08:00
    不是很理解你这个理论上为 0 ……
    放在实际开发中,确实是能想到的错误出现的概率都不见得为 0 。即使是内存 bit 读写会翻转,这种问题放到一些环境下也是需要进行处理的。
    所以实际上开发中的错误一般是依据出现的上下文,可能产生的影响,或者说是各种处理方案的性价比来决定处理方案。
    具体到你的例子,如果这个处理放在用户输入部分。即使你事先准备了各种提醒,那也架不住用户一不小心做了错误的输入。而且这种时候你不做处理那么程序可能会 crash ,用户体验会非常糟糕,那么最好是预先阻止掉各种意外的输入。如果你的处理只是一个内部调用的子函数,而且你已经和调用方约定好了输入只能是数字,那么再出现问题一般就是由调用方进行处理了。
    Cbdy
        22
    Cbdy  
       2017-04-16 09:45:27 +08:00 via Android
    断言就是这个时候用的
    cwlmxwb
        23
    cwlmxwb  
       2017-04-16 10:03:55 +08:00 via iPhone
    @lucifer9 此话怎讲
    infun
        24
    infun  
       2017-04-16 10:06:26 +08:00
    @lcorange 哈哈哈。
    sagaxu
        25
    sagaxu  
       2017-04-16 10:11:17 +08:00 via Android
    用户输入,任何情况下都要检查。 API 调用,契约式编程无需检查,防御式编程要检查。
    vincentqi
        26
    vincentqi  
       2017-04-16 10:21:58 +08:00
    曾经有一个产品经理的用户名是 null
    Phariel
        27
    Phariel  
       2017-04-16 10:23:42 +08:00 via Android
    墨菲定律 有几率会发生的事情一定会出错 并且人类认为零概率的东西通常都有概率发生
    wly19960911
        28
    wly19960911  
       2017-04-16 10:23:56 +08:00 via Android
    就算前端可以帮你挡住,假如有人要发包测试呢,这东西没有 0%的,如果不涉及数据库和业务的话我懒得检测,涉及的话该怎么样就怎么样
    bukip
        29
    bukip  
       2017-04-16 10:49:30 +08:00
    “比如一个数值输入计算,要先判断它是否全为数字”

    这种可能性远远大于 0
    iyaozhen
        30
    iyaozhen  
       2017-04-16 10:54:27 +08:00 via Android
    你举得例子和你的标题不符呀。
    编程法则:不要信任任何用户输入

    但比如说你是强类型语言申明了输入类型或者框架上做了处理,这种业务代码上就不用判断了
    gamexg
        31
    gamexg  
       2017-04-16 11:16:10 +08:00
    我的做法:

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

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

    如果是类似 https://www.v2ex.com/t/355154 里面的 355154 ,理论合法用户不会出现非数字的情况,这种直接同函数调用,直接抛异常。但是别忘了设置整站的 500 页面及错误日志。
    jayzjj000
        32
    jayzjj000  
       2017-04-16 12:32:48 +08:00
    作为开放出去的公用库,只要不是强类型,都建议判断

    另外,另一种思路是如果产生了这种异常分支,不处理这个分支对整个工程的影响,拿正文举例:
    - 如果不处理的结果是输出不满足输入结果需要,那么可以不处理,因为输入结果就是错误的
    - 如果不处理的结果是抛异常或者 Crash ,那么再怎么样都要处理,防止出现“你这个函数写的容错性怎么这么差”的攻击机会
    Khlieb
        33
    Khlieb  
       2017-04-16 12:35:00 +08:00 via Android
    这就需要采取边界检查的机制
    wanttofly
        34
    wanttofly  
       2017-04-16 12:44:10 +08:00
    哎,其实最悲剧的是你写程序考虑了很多低概率事件,设想了很多极端的情况,却发现一个用户都没有操作到那种情况简直想死,哦,因为没人用。哈哈!
    phrack
        35
    phrack  
       2017-04-16 12:46:44 +08:00 via Android
    never trust any input
    anuan
        36
    anuan  
       2017-04-16 13:25:04 +08:00
    先跑起来再说别的
    lc4t
        37
    lc4t  
       2017-04-16 13:26:29 +08:00
    射飞镖的时候射中盘上任意一点概率都是 0 ,因为点 /面=0 ,但是只要射中了概率为 0 的事情就发生了,所以概率为 0 不是不可能发生。

    对于用户的输入,即便用户完全不可能输入一个值,也要防止测试给你一个意外输入。总之原则上就是考虑所有可能。
    viator42
        38
    viator42  
       2017-04-16 13:31:17 +08:00 via Android
    我觉得能做的验证还是尽量做,一方面防那些搞事情的,另一方面减少出一些奇怪的 bug 。墨菲定律不信不行啊
    crist
        39
    crist  
       2017-04-16 13:33:13 +08:00
    为 0 你考虑个卵!
    kaneg
        40
    kaneg  
       2017-04-16 14:16:05 +08:00 via iPhone
    如果真的概率很低,比如 CPU 的逻辑门被宇宙射线改变了电平,是可以不用考虑。可问题你提的用户输入是否数字,这个出错的概率太高了,起码有 2 , 3 成。
    zyEros
        41
    zyEros  
       2017-04-16 14:17:54 +08:00 via iPhone
    这种情况就需要学习一下防御性编程,因为概率为 0 ,除非你可以证明得到
    jason19659
        42
    jason19659  
       2017-04-16 14:48:54 +08:00
    首先要论证是不是真的概率为 0
    bombless
        43
    bombless  
       2017-04-16 14:59:49 +08:00 via Android
    看过一个说法,说过马路总是记得往马路两头看的人才是合格的程序员。起码这个说法还是挺有趣的,哈哈
    klxq15
        44
    klxq15  
    OP
       2017-04-16 15:02:43 +08:00 via Android
    这样啊,看了大家的评论感觉还是加上判断好一些,谢谢大家的回复~
    watcher
        45
    watcher  
       2017-04-16 15:05:27 +08:00
    多写两行 穷不了你 富不了我... 写不出吃亏 写不出上当...
    realpg
        46
    realpg  
       2017-04-16 15:09:45 +08:00
    不相信任何其他途径传过来的数据
    reus
        47
    reus  
       2017-04-16 15:19:26 +08:00
    如果你要这样做,那就别用 python 了,用静态类型语言。
    nicevar
        48
    nicevar  
       2017-04-16 16:14:48 +08:00
    保证程序的健壮性是很有必要的,因为你想不到的情况太多了
    很多年前刚参加工作在一公司,软件发布前经过整个部门的轮番测试觉得已经不错了然后就发出去,结果短短几天用户反馈的 bug 达到 200 多个,当时测试跑过来说这个事我就惊呆了
    loading
        49
    loading  
       2017-04-16 16:47:18 +08:00 via Android
    不要相信提交的任何内容,不是基本原则吗?
    atnopc
        50
    atnopc  
       2017-04-16 16:56:41 +08:00
    之前有个和本地 zf 合作的一个项目
    用户群是中老年人
    你就会发现你认为这个概率为 0 的想法有多么不靠谱了
    AstroProfundis
        51
    AstroProfundis  
       2017-04-16 20:17:30 +08:00
    用户输入不符合预期的数据这种事情概率不应该是接近 1 的吗,楼主怎么会产生概率为 0 的错觉
    blessyou
        52
    blessyou  
       2017-04-16 20:34:54 +08:00 via iPhone
    考虑过服务器挂掉 1988 次,然后突然觉得,哼 怎么可能,不存在的
    si
        53
    si  
       2017-04-16 20:45:58 +08:00
    接近零!=零,即使概率再小他也不为零。不为零就是肯定会发生。为零是肯定不会发生。
    Mutoo
        54
    Mutoo  
       2017-04-16 21:10:47 +08:00
    莫非定律, 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
    lifanxi
        55
    lifanxi  
       2017-04-16 21:50:39 +08:00
    37 楼说得对,概率为 0 并不表示不发生,所以不能一概而论要不要处理“概率为 0 ”的情况,最多只能讨论“不会发生的事件”要不要处理。
    BOYPT
        56
    BOYPT  
       2017-04-16 21:52:30 +08:00
    if(false) { alert("something happeded ... "); }
    ra1983
        57
    ra1983  
       2017-04-16 21:53:55 +08:00 via Android
    @bombless 我看到的说法是过单行道也看两边的程序员,哈哈
    jatesun
        58
    jatesun  
       2017-04-17 08:51:20 +08:00
    当然啦,你要问我考不考虑我说考虑,我就可以明确的告诉你
    pepesii
        59
    pepesii  
       2017-04-17 09:04:30 +08:00 via iPhone
    为啥我想起了人生三大错觉
    kuber
        60
    kuber  
       2017-04-17 13:32:57 +08:00
    曾经碰到一个奇葩的 bug ,一个 button 点 10 次以上程序会崩溃。特别佩服那个测试。
    ryanzyy
        61
    ryanzyy  
       2017-04-18 17:04:26 +08:00
    你的情况需要详细了解你所说的数值输入是什么
    如果来源为 Web Form ,用户用第三方软件生成的文件之类的 那么必定要验证
    如果来源为 自己另一处的代码 可以考虑加一个 验证 然后直接报 Runtime Error (提醒自己用的) 或者也可省略

    你说的理论概率为 0 是不需要写代码做额外处理的
    比如
    do
    uuid = UUID.generate_new_uuid
    end while existing_uuids[uuid]
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1022 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 22:08 · PVG 06:08 · LAX 14:08 · JFK 17:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.