网站备案地址不是我的地址怎么办,wordpress 如何采集,广告设计专业前景,手机网站源码教程本文摘自朱雷老师所著《Python工匠》一书内容#xff0c;作为笔记予以记录。
学习本章内容#xff0c;我印象最深的是“虽然函数可以消除重复代码#xff0c;但绝不能只把它看成一种复用代码的工具#xff0c;函数最重要的价值其实是创建抽象#xff0c;而提供复用价值甚…本文摘自朱雷老师所著《Python工匠》一书内容作为笔记予以记录。
学习本章内容我印象最深的是“虽然函数可以消除重复代码但绝不能只把它看成一种复用代码的工具函数最重要的价值其实是创建抽象而提供复用价值甚至可以算是抽象所带来的一种副作用。”
要写出好的函数秘诀就在于设计好的抽象且不要写太复杂的函数导致抽象不精确每个函数只应该包含一层抽象。
一、本章学习的知识要点
1函数参数与返回相关的基础知识
不要使用可变类型作为参数默认值用None来代替使用标记对象可以严格区分函数调用时是否提供了某个参数定义仅限关键字参数可以强制要求调用方提供参数名提升可读性函数应该拥有稳定的返回类型不要返回多种类型适合返回None的情况——操作类函数、查询类函数便是意料之中的缺失值在执行失败时相比返回None,抛出异常更为合适如果提前返回结果可以提升可读性就提前返回不必追求“单一出口”
2代码可维护性技巧
不要编写太长的函数但长度并没有标准65行算是一个危险信号圈复杂度是评估函数复杂程度的常用指标圈复杂度超过10的函数需要重构抽象与分层思想可以帮我们更好地构建与管理复杂的系统同一个函数内的代码应该处在同一抽象级别
3函数与状态
没有副作用的无状态纯函数易于理解容易维护但大多数时候“状态”不可避免避免使用全局变量给函数增加状态当函数状态较简单时可以使用闭包技巧当函数需要较为复杂的状态管理时建议定义类来管理状态
4语言机制对函数的影响
functools.partial()可以用来快速构建偏函数functools.lrc_cache()可以用来给函数添加缓存比起map和filter列表推导式的可读性更强更应该使用lambda函数只是一种语法糖你可以使用operator模块等方式来替代它Python语言里的递归限制较多可能的话请尽量使用循环替代
二、常用技巧
1、别将可变类型作为函数的参数默认值
在编写函数时经常需要为参数设置默认值。这些默认值可以是任何类型比如字符串、数值、列表等等。而当它是可变类型时怪事儿就发生了。看下面这个函数
def append_value(value,items[]):向items列表中追加内容并返回该列表items.append(value)return items
多次调用上面这个函数就会发现函数的行为和预想的会不一样 append_value(apple) [apple] append_value(1223) [apple, 1223] append_value(9999) [apple, 1223, 9999]
可以看到第二次及后续多次调用后的结果看传入函数的参数items的值不再是函数定义的空列表[ ]而是变成了上一次执行后的值。
之所以出现这个问题是因为Python函数的参数默认值只会在函数定义阶段被创建一次之后不论再调用多少次函数内拿到的默认值都是同一个对象。
深入点通过查看函数对象的保留属性_ _defaults_ _(列表类型可以看到这个值的变化 append_value(apple) # 第一次调用 [apple] append_value.__defaults__[0] # 调用函数后items的缺省值[apple] [apple] append_value(999) [apple, 999] append_value.__defaults__[0] # 再次调用函数后items的缺省值[apple, 999] [apple, 999] append_value(中国) [apple, 999, 中国] append_value.__defaults__[0] [apple, 999, 中国] append_value.__defaults__[0].clear() # 清空缺省值items的缺省值[] append_value.__defaults__[0] [] append_value(huawei) # 清空缺省值再次执行函数缺省值[huawei] [huawei]
为了规避这样问题使用None来替代可变类型默认值是比较常见的做法
def append_value(value,itemsNone):向items列表中追加内容并返回该列表if items is None:items []items.append(value)return items
如上修改后假如调用函数没有提供items参数函数每次都会创建一个新的空列表不会在出现之前的问题。
2、定义仅限关键字参数
Python里的函数不光支持通过有序位置参数positional argument调用还能指定参数名通过关键字参数keyword argument的方式调用。比如下面这个用户查询函数
def query_users(limit,offset,min_followers_count,include_profile):查询用户...:param min_followers_count: 最小关注者数量:param include_profile: 结果包含用户详细档案...
# 使用位置参数参数太多时间长了就容易忘记参数的意义
query_users(20,0,100,True)
# 使用关键字参数可以不严格按照函数定义参数的位置来传递
query_users(limit20,offset0,min_followers_count100,include_profileTrue)
虽然关键字参数调用模式很有用但是系统并没有强制要求。不过下面这种语法将强制使用否则会抛出异常错误
# 注意参数列表中的 * 符号
def query_users(limit,offset,*,min_followers_count,include_profile):查询用户...:param min_followers_count: 最小关注者数量:param include_profile: 结果包含用户详细档案...
通过在参数列表中插入 * 符号该符号后的所有参数都变成了仅限关键字参数如果调用方仍然使用位置参数值系统会抛出异常错误正确用法
query_users(20,0,min_followers_count100,include_profileTrue)
假如函数的参数较多超过3个使用关键字参数模式将大大提升代码的可读性。