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

Python 的 if 如果判断语句过于冗长,有书写技巧不?

  •  
  •   pppguest3962 · 2022-01-20 17:54:09 +08:00 · 4080 次点击
    这是一个创建于 1045 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如:

    if (a or b) and (c.get('d') == 1 or e.get('f') == 1) and (not g or not h) and (type(i) == list or type(j) == list):  
    

    如果 a,b,c,d...j (而且还不止)的正式变量名,均在 8 个字符以上,这种条件判断阅读和书写上一行都超屏了, if 如果下面嵌套 if ,也不好看,if 就不能逐个子条件折一下行么?

    24 条回复    2022-01-27 14:15:48 +08:00
    pppguest3962
        1
    pppguest3962  
    OP
       2022-01-20 17:55:39 +08:00
    如果 if 嵌套,那么真正的执行内容缩进到那一节,也超屏了
    lasuar
        2
    lasuar  
       2022-01-20 17:57:28 +08:00
    ```
    and_set1 = (a or b) and (c.get('d') == 1 or e.get('f') == 1)
    and_set2 = (not g or not h) and (type(i) == list or type(j) == list)

    if and_set1 and and_set2:
    ```
    pppguest3962
        3
    pppguest3962  
    OP
       2022-01-20 17:58:43 +08:00
    @lasuar 妙,多弄几个新变量。
    Pilippa
        4
    Pilippa  
       2022-01-20 17:59:37 +08:00
    长度不是问题,
    条件应该可读清晰才是重要的
    以下纯粹举例

    is_qualified = a or b
    is_allowed = c.get('d') == 1 or e.get('f') == 1
    is_valid_type = isinstance(i, list) or isinstance(j, list)

    if is_qualified and is_allowed and is_valid_type:
    # do something here...
    pppguest3962
        5
    pppguest3962  
    OP
       2022-01-20 18:00:08 +08:00
    还能多几行码量增加了工作量,妙
    shawnbluce
        6
    shawnbluce  
       2022-01-20 18:01:58 +08:00
    @pppguest3962 #3 不过这种写法要注意一个问题。如果写成原来那种很长一串的话,不论是 and 还是 or 都有可能提前遇到判定短路从而跳过后面的条件,例如 a or b or c or d or e 的情况下如果 a 直接就 True 了那么后面的判断就不需要了,性能上要比多弄几个变量更好一些
    shawnbluce
        7
    shawnbluce  
       2022-01-20 18:02:38 +08:00
    @shawnbluce #6 不是说前面这种写法就不好,只是单纯提出一种看法
    cclin
        8
    cclin  
       2022-01-20 18:04:23 +08:00 via Android   ❤️ 1
    if (
    (a or b)
    and (c.get("d") == 1 or e.get("f") == 1)
    and (not g or not h)
    and (type(i) == list or type(j) == list)
    ):
    pass

    使用 black 格式化一下就好
    gadfly3173
        9
    gadfly3173  
       2022-01-20 18:04:33 +08:00
    不如把判断结果抽成几个变量,这也太长了
    ClericPy
        10
    ClericPy  
       2022-01-20 18:15:57 +08:00
    忘了哪本书提到过, if 里面逻辑太复杂, 把相关逻辑抽取成一个完整逻辑的函数, 保证可读性. 当然如果计算非常简单提取成变量也没问题, 函数是为了逻辑短路避免无用计算
    imycc
        11
    imycc  
       2022-01-20 18:17:12 +08:00
    折行呗,大概长这样,也不用什么括号

    ```
    if cond_a \
    and cond_b \
    and cond_c:
    pass
    ```
    imycc
        12
    imycc  
       2022-01-20 18:18:36 +08:00
    缩进被删了有点麻。if 折行之后下一行是两个缩进的距离,为了 if 里面一个缩进的语句区分开来
    rwecho
        13
    rwecho  
       2022-01-20 18:19:42 +08:00 via Android
    pep8 会给加换行的
    imn1
        14
    imn1  
       2022-01-20 18:41:44 +08:00   ❤️ 2
    conditions =[
    (a or b),
    (c.get('d') == 1 or e.get('f') == 1),
    (not g or not h),
    (type(i) == list or type(j) == list)
    ]
    if all(conditions):

    all 和 any 是支持短路的

    或者
    写成闭包函数(也无需传参),每行短路判断 --> if not xxx: return False
    chevalier
        15
    chevalier  
       2022-01-20 18:47:13 +08:00   ❤️ 2
    这种 if 很显然,你的程序设计有问题,逻辑划分和封装得不合理

    这一个 if 的圈复杂度已经是 13 ,先不说队友得死多少脑细胞才能看明白和维护,光你的单测得写多少用例才能覆盖?
    lasuar
        16
    lasuar  
       2022-01-20 18:47:42 +08:00
    @imn1 这种更妙!
    cmdOptionKana
        17
    cmdOptionKana  
       2022-01-20 18:56:10 +08:00
    @chevalier 确实,这么复杂的 if 语句,逻辑没划分清楚的可能性极大。
    karloku
        18
    karloku  
       2022-01-20 19:47:56 +08:00
    如果优化不了条件的话, 可以设计成能提前进行 return/continue/break 的执行方式

    当然最好是想办法优化一下判断条件, 这么长的判断式可读性很差
    ilylx2008
        19
    ilylx2008  
       2022-01-20 19:56:02 +08:00
    Python: 时间花在排版上
    msg7086
        20
    msg7086  
       2022-01-20 20:20:29 +08:00
    @shawnbluce #6
    是不是可以把变量改写成 lambda 延迟执行,这样就支持短路了吧。
    GuangXiN
        21
    GuangXiN  
       2022-01-20 20:23:52 +08:00
    把长 if 表达式提取成函数
    deplivesb
        22
    deplivesb  
       2022-01-21 11:43:01 +08:00
    如果 if 条件太长,为什么不抽取成一个功能完备的函数,这样既可以解决 if 太长,还可以有概率复用
    panghu618
        23
    panghu618  
       2022-01-24 18:21:42 +08:00
    变函数
    colatea
        24
    colatea  
       2022-01-27 14:15:48 +08:00
    正常写,写完就格式化文档,反正以后也不看
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2574 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 05:27 · PVG 13:27 · LAX 21:27 · JFK 00:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.