Python学习笔记--函数

本文摘自朱雷老师所著《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,items=None):"""向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(limit=20,offset=0,min_followers_count=100,include_profile=True)

虽然关键字参数调用模式很有用,但是系统并没有强制要求。不过,下面这种语法将强制使用,否则会抛出异常错误:

# 注意参数列表中的 * 符号
def query_users(limit,offset,*,min_followers_count,include_profile):"""查询用户...:param min_followers_count: 最小关注者数量:param include_profile: 结果包含用户详细档案"""...

通过在参数列表中插入 * 符号,该符号后的所有参数都变成了仅限关键字参数,如果调用方仍然使用位置参数值,系统会抛出异常错误,正确用法:

query_users(20,0,min_followers_count=100,include_profile=True)

假如函数的参数较多(超过3个),使用关键字参数模式将大大提升代码的可读性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/651266.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决:‘chromedriver’ executable needs to be in PATH

解决:chromedriver’ executable needs to be in PATH 文章目录 解决:chromedriver’ executable needs to be in PATH背景报错问题报错翻译报错位置代码报错原因解决方法方法一:检查python安装路径有没有添加到环境变量里面方法二&#xff1…

谷歌vue插件安装包

链接:https://pan.baidu.com/s/1wTCqn7ttc-rF_wZScfEgPw?pwde7k6 提取码:e7k6 修改D:\谷歌浏览器插件安装包\devtools-main\packages\shell-chrome下manifest.json文件 将里面这四个文件地址改为src下面,因为地址在src下,直接…

Redis面试题34

什么是人工智能?它的应用领域有哪些? 答:人工智能(Artificial Intelligence,AI)是一种模拟、模拟和扩展人类智能的计算机系统。它指的是计算机系统能够模拟和执行人类智能,包括感知、学习、推理…

头歌C语言指针

目录 第1关:用指针法输入12个整数,然后按每行4个数输出 任务描述 第2关:指针变量作为函数参数实现两变量交换值 任务描述

go去除字符串中的\(去除指定字符)

通用化推荐 一键开启舒适: go get -u "github.com/jialanli/lacia/utils" 常用功能一应俱全, 非常实用。 调用:lacia.RemoveX(str, x) 参数2为指定的要去除的字符。 实例: var x \// 去除\fmt.Println(lacia.Rem…

基于Guava布隆过滤器的海量字符串高效去重实践

在Java环境中处理海量字符串去重的问题时,布隆过滤器(BloomFilter)是一种非常高效的数据结构,尽管它有一定的误报率。布隆过滤器适用于那些可以接受一定误报率,并且希望节省空间和时间成本的场景。 布隆过滤器应用 使…

Fastjson代码审计实战

代码审计-漏洞复现 漏洞分析采用的是华夏ERP2.3, 查看pom.xml文件发现fastjson版本1.2.55,该版本存在漏洞,利用DNSlog进行验证。 fastjson涉及反序列化的方法有两种,JSON.parseObject()和JSON.parse(),在代码中直接搜…

maven 依赖配置补充

依赖配置补充 依赖范围 import 管理依赖最基本的办法是继承父工程,但是和 Java 类一样,Maven 也是单继承的。如果不同体系的依赖信息封装在不同 POM 中了,没办法继承多个父工程怎么办?这时就可以使用 import 依赖范围。 典型案…

力扣:116. 填充每个节点的下一个右侧节点指针

广度优先搜索解法: 1.该题的解法主要在于给每层节点的下一个右侧节点来进行赋值,所以我们只要再没遍历到每层最后一个节点时都给之前弹出的节点赋上当前对列中队首的节点就解决了这题。 /* // Definition for a Node. class Node {public int val;publ…

MySQL 联合索引

文章目录 1.简介2.最左匹配3.最左匹配原理4.如何建立联合索引?5.覆盖索引参考文献 1.简介 联合索引指建立在多个列上的索引。 MySQL 可以创建联合索引(即多列上的索引)。一个索引最多可以包含 16 列。 联合索引可以测试包含索引中所有列的查询&#…

关于在Ubuntu20.04(ROS1 noetic)中使用catkin_make编译时发生的与pyhton版本不兼容的问题解决办法

今天在另外一台电脑上操作复现【ROS建模:一起从零手写URDF模型】这个博客时,发生了一些问题,特此记录下来 【ROS建模:一起从零手写URDF模型】链接:https://blog.csdn.net/qq_54900679/article/details/135726348?spm…

JasperReports渲染报表文件时候,读取图片报错:Byte data not found at:xxx.png.\r\n\tat

目录【知识星球】 1.1、错误描述 1.2、解决方案 1.1、错误描述 最近在工作中,使用JasperReports报表比较多一些,有次线上环境里面运行报错,查看报错日志,如下所示: net.sf.jasperreports.engine.JRException: Byte…

Spring Boot 启动错误【Kotlin】

目录 错误详情 错误原因 解决方法一 解决方法二 错误详情 Kotlin:     Module was compiled with an incompatible version of Kotlin.     The binary version of its metadata is 1.7.1, expected version is 1.1.16. 错误原因 编译器或构建工具的版本不匹配所造…

LC201-300

本篇博客是用Go语言编写的详尽简洁代码,这里没有写算法思路,若要看具体思路,请移步力扣官网查看相关高赞题解。本篇博客的特点是代码简洁明了,包含多种写法,适合读者后期复盘巩固,加深理解。这一百题是面试…

(免费领源码)python#Mysql苏州一日游之可视化分析69216-计算机毕业设计项目选题推荐

摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对旅游服务等问题,对旅游服务进行…

docker 构建应用

docker 应用程序开发手册 开发 docker 镜像 Dockerfile 非常容易定义镜像内容由一系列指令和参数构成的脚本文件每一条指令构建一层一个 Dockerfile 文件包含了构建镜像的一套完整指令指令不区分大小写,但是一般建议都是大写从头到尾按顺序执行指令必须以 FROM 指…

Web3.0投票如何做到公平公正且不泄露个人隐私

在当前的数字时代,社交平台举办投票活动已成为了一种普遍现象。然而,随之而来的是一些隐私和安全方面的顾虑,特别是关于个人信息泄露和电话骚扰的问题。期望建立一个既公平公正又能保护个人隐私的投票系统。Web3.0的出现为实现这一目标提供了…

java web mvc-04-Apache Wicket

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …

完美调试android-goldfish(linux kernel) aarch64的方法

环境要求 Mac m1Mac m1 中 虚拟机安装aarch64 ubuntu22.02Mac m1安装OrbStack,并在其中安装 ubuntu20.04(x86_64) 构建文件系统 在虚拟机 aarch64 ubuntu22.02中构建 安装必要的库 sudo apt-get install libncurses5-dev build-essenti…

ARP安全针对欺骗攻击的解决方案

针对欺骗攻击的解决方案 ARP表项固化 使能ARP表项固化功能后,设备在第一次学习到ARP之后,不再允许用户更新此ARP表项或只能更新此ARP表项的部分信息,或者通过发送ARP请求报文的方式进行确认,以防止攻击者伪造ARP报文修改正常用户…