zoukankan      html  css  js  c++  java
  • 代码重构之路 --- 一些编程规范和 python idiom make your code more pythonic

    蓝色的 mandelbrot

    1. 重构代码(《重构》的python实现):

    常量和临时变量

    • 提取常量
    • 加入解释性变量
    • 分解临时变量(单一原则)
    • 去除临时变量
    • 移除控制标记(直接return 或 break)

    函数

    • 拆分
    • 去除(去除简单的)
    • 合并多个函数,使用参数
    • 函数不应有副作用,单一职责原则,一个函数不应做两件事,函数粒度尽量小

    表达式

    • 过多的条件逻辑, 难以理解正常的执行路径. 在python中的特征是, 缩进太深(尽早return 改为平行的 if)
    • 合并条件表达式(对于返回结果相同的条件)
    • 分解复杂条件表达式(分别从if,else中提炼出独立函数)
    • 合并重复的代码片段(if 和 else都有的代码,放到外面去)

    参数及返回值

    • 提取对象(如果参数/返回值是一组相关的数值, 且总是一起出现, 可以考虑提取成一个对象)
    • 减少参数(中间不需要的步骤)
    def get_width_height():
        ....
    
        return width, height
    
    def get_area(width, height):
        return width, height
    # to
    class Rectangle(object):
        def __init__(self, width, height):
            self.width = width
            self.height = height
    
        def area(self):
            return self.width * self.height
    
    def get_shape():
        ....
        return Rectangle(height, width)
    

    • 搬移,函数/字段
    • 拆分类
    • 去除类 (类做的事不多,不再独立存在)

    模式

    • 慎用,只用熟悉的,只用符合业务场景的
    • 装饰器

    参考:http://www.wklken.me/posts/2017/06/17/refactoring-07.html#yuan-ze

    2. pycharm重构快捷键

    序号 快捷键 功能
    1 F5 复制文件
    2 F6 移动文件
    3 SHIFT F6 重命名
    4 ALT delete 安全删除
    5 CTRL F6 改变函数形参
    6 CTRL ALT M 将代码提取为函数
    7 CTRL ALT V 将代码提取为变量
    8 CTRL ALT C 将代码提取为常数
    9 CTRL ALT F 将代码提取为字段
    10 CTRL ALT P 将代码提取为参数

    3. python idiom, pythonic

    每当你在代码库中看到以下的模式可以参照以下的建议进行重构,让代码变得更加的pythonic,可读性更好,更容易维护。
    参考:Python重构代码的一些模式 http://mpwang.github.io/2017/08/26/python-refactor-patterns/

    enumerate

    需要使用列表的下标时,不要使用C风格的下标遍历

    lst = ['a', 'b', 'c']
    # DON'T
    i = 0
    for i in lst:
        print i, '-->', lst[i]
        i += 1
    # OR
    for i in range(len(lst)):
        print(i, '-->', lst[i])
    # DO
    for idx, item in enumerate(lst):
        print(idx, '-->', item)
    
    

    zip/izip

    同时遍历两个列表时,不要使用C风格的下标遍历

    lst1 = ['a', 'b', 'c']
    lst2 = [1, 2, 3]
    # DON'T
    for i in range(len(lst1)):
        print(lst1[i])
        print(lst2[i])
    # DO
    for lst1_item, lst2_item in zip(lst1, lst2):
        print(lst1_item)
        print(lst2_item)
    # BETTER
    # 不需要在内存中生成包含lst, lst2的第三个列表
    from itertools import izip
    for lst1_item, lst2_item in izip(lst1, lst2):
        print(lst1_item)
        print(lst2_item)
    
    

    unpacking tuple

    x, y = y, x
    foo, bar, _ = words # 使用 _ 如果你不需要这个值
    

    Dict.setdefault/defaultdict

    处理字典中key不存在时的默认值

    # group words by frequency
    words = [(1, 'apple'), (2, 'banana'), (1, 'cat')]
    frequency = {}
    # DON'T
    for freq, word in words:
        if freq not in frequency:
            frequency[freq] = []
        frequency[freq].append(word)
    # DO
    for freq, word in words:
        frequency.setdefault(freq, []).append(word)
    # BETTER
    from collections import defaultdict
    frequency = defaultdict(list)
    for freq, word in words:
        frequency[freq].append(word)
    # 在工作中要经常处理字典为空或键值不存在的情形,用get和setdefault代替dict_name['key']
    

    setdefault vs get
    setdefault()的使用,类似get方法,如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值
    不同点:1.setdefault会把不存在的item保存到原来的dict,2.setdefault比get快10percent

    person_dict = {}
    person_dict['liqi'] = 'LiQi'
    person_dict.setdefault('liqi', 'Liqi')  # 'LiQi'
    person_dict.setdefault('Kim', 'kim')  # 'kim'
    person_dict
    person_dict.get('Dim', 'D')  # 'D'
    person_dict  # {'liqi': 'LiQi', 'Kim': 'kim'}
    
    

    Dict.iteritems

    遍历字典

    words = {'apple': 1, 'banana': 2, 'cat': 3}
    # OK
    for word in words:
        print word, '-->', words[word] # 需要计算word的hash值
    # GOOD
    for word, freq in words.items():
        print word, '-->', freq
    # BETTER
    # 不需要在内存中生存包含words所有元素的中间结果
    for word, freq in words.iteritems():
        print word, '-->', freq
    
    

    for...else

    break and nobreak

    # DO
    for word in words:
        if condition(word):
            # 处理存在符合condition的元素的情况
            print 'Found'
            break
    else:
        # 处理没有符合condition元素的情况
        print 'Not found'
    

    try...except...else

    分开异常处理与正常情况

    # GOOD
    try:
        result = json.loads(get_external_json())
        do_something_with(result)
    except Exception as e:
        handle_error(e)
    # BETTER
    try:
        # 异常可能抛出点
        result = json.loads(get_external_json())
    except Exception as e:
        # 异常处理
        handle_error(e)
    else:
        # 正常情况
        do_something_with(result)
    
    

    https://medium.com/the-andela-way/idiomatic-python-coding-the-smart-way-cc560fa5f1d6

    1. chained comparison operators

    # bad
    if x <= y and y <= z:
      # do something
    # good
    if x <= y <= z:
      # do something
    

    2. indentation(if else )

    3. use the falsy & truthy concepts

    For example an empty list/sequences [], empty dictionaries {} None, False, Zero for numeric types, are considered “falsy”. On the other hand, almost everything else is considered “truthy”.

    # bad
    x = True
    y = 0
    if x == True:
      # do something
    elif x == False:
      # do something else
    if y == 0:
      # do something
    ls = [2, 5]
    if len(ls) > 0:
      # do something
    # good
    (x, y) = (True, 0)
    # x is truthy
    if x:
      # do something
    else:
      # do something else
    # y is falsy
    if not y:
      # do something
    ls = [2, 5]
    if ls:
      # do something
    

    4. ternary operator replacement

    # bad
    a = True
    value = 0
    if a:
      value = 1
    print(value)
    # good
    a = True
    value = 1 if a else 0
    print(value)
    
    

    5. use the 'in' keyword

    # bad
    city = 'Nairobi'
    found = False
    if city == 'Nairobi' or city == 'Kampala' or city == 'Lagos':
      found = True
    # good
    city = 'Nairobi'
    found = city in {'Nairobi', 'Kampala', 'Lagos'}
    

    6. Use ‘return’ to evaluate expressions, in addition to return values

    # bad
    def check_equal(x, y):
      result = False
    
      if x == Y:
        result = True
      return result
    # good
    def check_equal(x, y):
      return x == y
    

    7. multiple assignment

    # good
    x = y = z = 'foo'
    

    8. formatting strings

    def user_info(user):
      return 'Name: {user.name} Age: {user.age}'.format(user=user)
    
    

    9. list comprehension(set, dict)

    ls = [element for element in range(10) if not(element % 2)]
    emails = {user.name: user.email for user in users if user.email}
    

    10. sets

    ls1 = [1, 2, 3, 4, 5]
    ls2 = [4, 5, 6, 7, 8]
    elements_in_both = list( set(ls1) & set(ls2) )
    print(elements_in_both)
    
    

    11. dont't repeat yourself(dry)

    # bad
    if user:
      print('------------------------------')
      print(user)
      print('------------------------------')
    # good
    if user:
      print('{0}
    {1}
    {0}'.format('-'*30, user))
    
    
  • 相关阅读:
    mac 10.15.7 修改PATH
    oc 属性类型一般用法
    ubuntu解压zip文件名乱码
    telnet 退出
    docker 根据容器创建镜像
    mac android adb device 没有显示设备
    Yii2 查看所有的别名 alias
    Yii2 App Advanced 添加 .gitignore
    ubuntu 18.04 搜狗突然就提示乱码
    An error occured while deploying the file. This probably means that the app contains ARM native code and your Genymotion device cannot run ARM instructions. You should either build your native code to
  • 原文地址:https://www.cnblogs.com/bruspawn/p/9236379.html
Copyright © 2011-2022 走看看