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
kayseen
V2EX  ›  Python

一个简单低级的代码逻辑问题

  •  
  •   kayseen · 2022-01-04 16:34:28 +08:00 · 3796 次点击
    这是一个创建于 839 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设存在多个判断条件,以下以修改用户信息为例,哪种代码结构会更清晰而且性能会好一点? 以下 python 伪代码:

    一:

    if 用户存在:
    	if 密码符合规范:
    		if 手机号符合规范:
    			if 邮箱符合规范:
    				do 修改用户信息
    			else:
    				return 邮箱不符合规范
    		else:
    			return 手机号不符合规范
    	else:
    		return 密码不符合规范
    else:
    	return 用户不存在
    

    二:

    if 用户不存在:
    	return 用户不存在
    if 密码不符合规范:
    	return 密码不符合规范
    if 手机号不符合规范:
    	return 手机号不符合规范
    if 邮箱不符合规范:
    	return 邮箱不符合规范
    do 修改用户信息
    
    44 条回复    2022-01-07 18:58:56 +08:00
    xiao109
        1
    xiao109  
       2022-01-04 16:36:09 +08:00
    那肯定是第二种啊,起码不用数空格
    WoWTxT
        2
    WoWTxT  
       2022-01-04 16:37:21 +08:00
    性能不用考虑,清晰肯定第二种
    Vinceeeent
        3
    Vinceeeent  
       2022-01-04 16:37:28 +08:00 via Android
    第一种看着都累啊
    wangtian2020
        4
    wangtian2020  
       2022-01-04 16:38:52 +08:00   ❤️ 1
    第二种

    从代码的“面相”来看,第一种长的像“回调地狱”,第二种就长得像 async 方法了( JavaScript )
    xingshu1990
        5
    xingshu1990  
       2022-01-04 16:45:46 +08:00
    原先在 Python 高级编程里看到过第二种 这种优化:

    Python 下,第二种属于短路原则。

    Python 里的“短路原则”:在条件语句中,如果存在多个条件需要判断时,位置靠前的条件导致整个判断语句为 True ( or 语句)或者为 False ( and 语句),就不再进行后续条件的判断。
    looyer
        6
    looyer  
       2022-01-04 16:50:03 +08:00
    第二种 另外表单输入判断前置 涉及到数据库查询结果的判断后置 只有表单数据都确认规范了 再去请求数据库做进一步判断
    Jooooooooo
        7
    Jooooooooo  
       2022-01-04 16:50:28 +08:00
    第二种清晰.
    66beta
        8
    66beta  
       2022-01-04 16:51:25 +08:00
    第二种是几乎适合所有语言的短路原则
    shyrock
        9
    shyrock  
       2022-01-04 16:54:36 +08:00
    必须是二啊。
    第一种我是没想出来哪种场景有用。
    xingshu1990
        10
    xingshu1990  
       2022-01-04 16:57:55 +08:00
    @shyrock 第一种是无任何编程基础的新人学着写的。
    FutherAll
        11
    FutherAll  
       2022-01-04 16:59:57 +08:00
    提前返回
    ayase252
        12
    ayase252  
       2022-01-04 17:00:13 +08:00
    无疑是第二种,early return

    第一种可读性太差
    Droi
        13
    Droi  
       2022-01-04 17:03:29 +08:00
    可以试试设计模式了。不知道职责链模式能不能解决你的这个问题。
    adoal
        14
    adoal  
       2022-01-04 17:06:30 +08:00
    Monad 了解一下
    EchoDeveloper
        15
    EchoDeveloper  
       2022-01-04 17:12:14 +08:00
    第二种就是卫语句,显然更好. 把不该出现的情况提前返回.
    ianEros
        16
    ianEros  
       2022-01-04 17:17:50 +08:00
    Fail-fast
    qiaobeier
        17
    qiaobeier  
       2022-01-04 17:19:49 +08:00
    肯定第二种啊,连你这种伪代码第二种也是漂亮太多了。
    ccraohng
        18
    ccraohng  
       2022-01-04 17:43:44 +08:00
    if 密码不符合规范:
    return 密码不符合规范
    if 手机号不符合规范:
    return 手机号不符合规范
    if 邮箱不符合规范:
    return 邮箱不符合规范


    都是校验,先走规则校验
    dengji85
        19
    dengji85  
       2022-01-04 17:53:23 +08:00
    @Droi 借楼问一下,这种业务判断多少人会真的去用设计模式,用了会不会增加复杂度
    PiersSoCool
        20
    PiersSoCool  
       2022-01-04 17:56:56 +08:00
    肯定第二种
    night98
        21
    night98  
       2022-01-04 18:38:45 +08:00
    python 没有类似 hibernate valid 的库么,这种基础校验手写太麻烦了把
    daimubai
        22
    daimubai  
       2022-01-04 19:12:55 +08:00
    肯定第二,能 return 就 return ,return 意味着 return 掉的代码不需要去管了可以降低“思维逻辑负担”,尽管逻辑不复杂
    veike
        23
    veike  
       2022-01-04 19:20:16 +08:00 via Android
    第二种,可以查一下"卫语句",就是为了降低 if 嵌套的程序复杂性
    Droi
        24
    Droi  
       2022-01-04 19:39:04 +08:00
    @dengji85 各人项目不会去用,用了反而增加复杂度
    teem
        25
    teem  
       2022-01-04 19:42:17 +08:00
    2 防御式编程
    chnhyg
        26
    chnhyg  
       2022-01-04 19:57:49 +08:00
    以卫语句取代嵌套条件表达式的精髓就是:给某一条分支以特别的重视。如果使用 if-then-else 结构,你对 if 分支和 else 分支的重视是同等的。这样的代码结构传递给阅读者的消息就是:各个分支有同样的重要性。卫语句就不同了,它告诉阅读者:“这种情况不是本函数的核心逻辑所关心的,如果它真发生了,请做一些必要的整理工作,然后退出。”——《重构》
    xiubin
        27
    xiubin  
       2022-01-04 20:13:30 +08:00
    个人可能会这么写,减少 return case ,做统一收口,后面方便加逻辑,比如 log 或者异常监控:

    let result = 0;
    if 用户不存在:
    result = 用户不存在
    if 密码不符合规范:
    result = 密码不符合规范
    if 手机号不符合规范:
    result = 手机号不符合规范
    if 邮箱不符合规范:
    result = 邮箱不符合规范
    log('check result: {result}')
    return result;
    llsquaer
        28
    llsquaer  
       2022-01-04 22:33:40 +08:00
    if 用户存在 or 密码符合规范 or 手机号符合规范 or 邮箱符合规范:
    return '你输入的数据中有一些地方是错的.自己检查'
    NowTime
        29
    NowTime  
       2022-01-04 22:35:28 +08:00   ❤️ 1
    @xiubin 那你这种的话,会不会符合多种条件,但只会返回最后一个提示
    bigxianyu
        30
    bigxianyu  
       2022-01-04 22:52:21 +08:00
    这两者之间的性能差距几乎可以忽略( 不是主要矛盾 ) ,第二种的可读性好多了,所以肯定选第二个
    zwgf
        31
    zwgf  
       2022-01-04 23:00:38 +08:00
    性能当然是第一种,但是这点性能,没必要
    还是第二种看着舒服
    msg7086
        32
    msg7086  
       2022-01-04 23:04:13 +08:00 via Android
    @dengji85 如果库已经有现成的功能的话还是用起来方便。
    比如 Rails 里,写 validation 规则比手写代码方便多了。
    https://guides.rubyonrails.org/active_record_validations.html
    inframe
        33
    inframe  
       2022-01-04 23:26:07 +08:00
    Django DRF 框架里用 validator 可以对每个字段设置规则进行校验,就不用单独写逻辑
    pcbl
        34
    pcbl  
       2022-01-04 23:49:48 +08:00
    @xiubin 不直接 return 的话,应该用 elif 吧。这些条件是只要满足一个就退出判断的
    yolee599
        35
    yolee599  
       2022-01-05 09:29:31 +08:00
    用第二种,有错误及时返回,不要再做其他判断了,做了也没用
    meiyoumingzi6
        36
    meiyoumingzi6  
       2022-01-05 09:34:42 +08:00 via iPhone
    写第一种怕不是要被同事打死
    bfdh
        37
    bfdh  
       2022-01-05 10:33:20 +08:00   ❤️ 1
    说个题外话,想起以前去一些单位办事,工作人员的答复
    第一次去:身份证没带,办不了
    第二次去:户口本没带,办不了
    第三次去:证件照没带,办不了
    xiubin
        38
    xiubin  
       2022-01-05 11:26:28 +08:00
    @NowTime #29
    @pcbl #34

    enen 我是直接复制了,应该是 if - else if
    sadfQED2
        39
    sadfQED2  
       2022-01-05 15:30:19 +08:00
    @xiubin #27
    sadfQED2
        40
    sadfQED2  
       2022-01-05 15:31:59 +08:00
    @xiubin #27

    let result = "";
    if 用户不存在:
    result += 用户不存在\n
    if 密码不符合规范:
    result += 密码不符合规范\n
    if 手机号不符合规范:
    result += 手机号不符合规范\n
    if 邮箱不符合规范:
    result += 邮箱不符合规范\n
    log('check result: {result}')
    return result;

    我一般都是这样写,不然多种条件部分和,日志打印不全,排除问题的时候日志反而误导人
    ariera
        41
    ariera  
       2022-01-05 16:47:47 +08:00
    性能不用考虑,清晰肯定第二种
    akira
        42
    akira  
       2022-01-05 17:19:17 +08:00
    性能应该也是 第二种
    veike
        43
    veike  
       2022-01-05 19:36:25 +08:00 via Android
    @bfdh 不冲突,一次性返回全部需要信息即可,和第二种写法类似
    generated
        44
    generated  
       2022-01-07 18:58:56 +08:00
    @night98 当然是有的噻,多的很, 比如 https://pydantic-docs.helpmanual.io/
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1080 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 19:05 · PVG 03:05 · LAX 12:05 · JFK 15:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.