V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
jpmorn
V2EX  ›  问与答

文无第一,武无第二,大城小胖说的 python 这段代码怎么优化

  •  1
     
  •   jpmorn · 2016-01-28 10:35:45 +08:00 · 4005 次点击
    这是一个创建于 3217 天前的主题,其中的信息可能已经有所发展或是发生改变。


    我今天白天说得就是这个... 所以, 年轻人千万别轻易的拜大神。那些满口软件工程、重构、敏捷开发、 OOP 、 TDD 、高质量、可复用……的人啊,写起代码来说不定有多魔幻呢…


    /@老赵:无论如何也应该把 cmd 提取出来,然后每个 if 分支执行后就跳过,现在先不论代码漂不漂亮,每个 if 条件都判断一遍是几个意思,至少也 elif 一下呢? //@欧长坤:[doge]谁能讨论点儿正经的 这玩意儿到底应该怎么写?

    //@GeniusVczh:我仔细地看了一眼这个代码,发现很有规律啊,正确的做法是写个独立程序 parse 这个文件,然后 codegen 出这一段函数来,除此以外没有任何更好的办法。

    .
    轮子哥说的这个是啥,有没有库之类的
    27 条回复    2016-01-28 15:45:29 +08:00
    ming2281
        1
    ming2281  
       2016-01-28 10:49:54 +08:00 via Android
    黑点是啥,没有看懂
    jpmorn
        2
    jpmorn  
    OP
       2016-01-28 10:54:57 +08:00
    @ming2281 没搞懂,抱着学习的态度来的,他们说能优化,那就优化的方法呢
    function007
        3
    function007  
       2016-01-28 11:05:11 +08:00
    不知道 python 里有没有 switch ,找到之后可以 break 出去的
    话说照首字母分个类,第一步判断首字母的话,说不定能省不少工作量?
    awanabe
        4
    awanabe  
       2016-01-28 11:06:21 +08:00
    py2 是没有 switch 的...只有 if 了..所以其实没啥大问题
    wuchizhitu1988
        5
    wuchizhitu1988  
       2016-01-28 11:09:44 +08:00
    为了黑而黑
    zztczcx
        6
    zztczcx  
       2016-01-28 11:14:15 +08:00
    反射,一行代码 解决 那么多 if
    hei1000
        7
    hei1000  
       2016-01-28 11:16:05 +08:00
    虽然不是太懂 Python ,但是每次检测都执行一遍 dataItem.get("cmd")是几个意思?
    SpicyCat
        8
    SpicyCat  
       2016-01-28 11:16:26 +08:00
    能不能发个 gist
    另外,像这种一长串 if 语句到底有什么坏处?除了看起来不高大上以外?
    jatsz
        9
    jatsz  
       2016-01-28 11:17:10 +08:00
    觉得代码也没有太难看,业务复杂度,你用代码也解决不了。
    非要说让代码变好看一点,而然实际上用户不大,那就是讲 else 的部分改成表驱动,方法的 dispatch 改成查表。
    MarioLuisGarcia
        10
    MarioLuisGarcia  
       2016-01-28 11:21:44 +08:00
    吹毛求疵讲两点:
    banricho
        11
    banricho  
       2016-01-28 11:25:35 +08:00 via Android
    如果是 JS 的话

    缓存 cmd
    obj[key]代替多个 if ( py 好像管这叫字典?)

    感觉差别不大。。
    MarioLuisGarcia
        12
    MarioLuisGarcia  
       2016-01-28 11:27:13 +08:00
    1. 这个代码里在最后的 else 分支里有多少次 if ,就会调用多少次 dataItem.get("cmd")
    除了性能消耗外,还有潜在隐患。
    我认为作者在这块现在 else 分支下的第一行使用 cmd_result = dataItem.get("cmd"), 之后再用 cmd_result 和字符串比较是更好的

    2. 文中的比较都是相等性比较,且比较的对象字符串都不同,所以只会有一个满足条件。所以在这儿除了第一个 if 外,之后的都应该改成 elif 。这样在 elif 的某一个条件满足后,后面的 elif 语句就会停止执行了。全部使用 if 的话,每一次都要判断所有的 if 语句。
    aisk
        13
    aisk  
       2016-01-28 11:27:36 +08:00
    如果单纯因为性能考虑的话,一般都是用一个 dict 保存 key 和响应处理的函数,这样就不需要执行这么多次判断了。

    不过从可读性上讲,这坨代码根本就不该写成这样。
    mulog
        14
    mulog  
       2016-01-28 11:27:52 +08:00
    别这样 说不定人家代码行数计入 KPI
    EPr2hh6LADQWqRVH
        15
    EPr2hh6LADQWqRVH  
       2016-01-28 11:28:43 +08:00
    这哥不会用 Dict 么
    canesten
        16
    canesten  
       2016-01-28 11:49:04 +08:00 via Android
    喜感十足
    yimity
        17
    yimity  
       2016-01-28 12:21:20 +08:00
    我也觉得 Dict 可以。我其实不会 Python
    jpmorn
        18
    jpmorn  
    OP
       2016-01-28 12:30:27 +08:00
    看起来需要来个实际点的例子学学啊
    thinker3
        19
    thinker3  
       2016-01-28 12:45:48 +08:00
    这跟 url route 很类似
    neilwong
        20
    neilwong  
       2016-01-28 13:29:59 +08:00 via iPhone
    昨天和大城小胖因为这个微博讨论到凌晨三点…
    caomaocao
        21
    caomaocao  
       2016-01-28 13:39:23 +08:00
    要用 dict 来表示 switch 呀~ python 里
    sherlocktheplant
        22
    sherlocktheplant  
       2016-01-28 13:40:25 +08:00
    直接设计类的时候 cmd 和函数名一一对应就好了啊 参数用** kwargs 传就好了
    icedx
        23
    icedx  
       2016-01-28 14:05:50 +08:00 via Android
    有低级错误 另外不要轻易用 duct 代替 swirch
    icedx
        24
    icedx  
       2016-01-28 14:05:59 +08:00 via Android
    Switch
    felinx
        25
    felinx  
       2016-01-28 14:19:16 +08:00
    根据 cmd 的字符和名字规则用 getattr 自动获取函数名,代码可以简练的多。且看命名习惯,这不是一个熟练的 Python 工程师写的,一点不 Pythonic 。
    gamexg
        26
    gamexg  
       2016-01-28 14:36:32 +08:00 via Android
    data 这个变量名被多次重复使用没人提吗?之后修改逻辑时很有可能掉坑里。

    其他的看起来都是小问题。

    反射搞不定,参数不一致。
    hepochen
        27
    hepochen  
       2016-01-28 15:45:29 +08:00   ❤️ 1
    像这种规则性非常明确的,也不需要用到额外的 dict 来建立映射。

    替换这进百行的重复代码,基本思路大抵如此:
    handler = getattr(self, data_item.get('cmd', '')+'_handler', None)
    if handler:
    handler(*[data_item.get(key) for key in inspect.getargspec(handler).args])


    写出脏代码并不可耻,为脏代码辩解的倒真算是可耻的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5427 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 09:22 · PVG 17:22 · LAX 01:22 · JFK 04:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.