刻意练习:Python基础 -- Task05. 函数与Lambda表达式
背景
我们准备利用17天时间,将 “Python基础的刻意练习” 分为如下任务:
- Task01:变量、运算符与数据类型(1day)
- Task02:条件与循环(1day)
- Task03:列表与元组(2day)
- Task04:字符串与序列(1day)
- Task05:函数与Lambda表达式(2day)
- Task06:字典与集合(1day)
- Task07:文件与文件系统(2day)
- Task08:异常处理(1day)
- Task09:else 与 with 语句(1day)
- Task10:类与对象(2day)
- Task11:魔法方法(2day)
- Task12:模块(1day)
这是我的第五次打卡内容。我学习 Python 的思路是,先去熟悉 Python 的整体语法框架与自己熟悉的编程语言进行知识点的连接,后面遇到问题再来慢慢补充,慢慢形成自己的知识结构。
Python 基础语法
还记得 Python 里面“万物皆对象”么?Python 把函数也当成对象,可以从另一个函数中返回出来而去构建高阶函数,比如
- 参数是函数
- 返回值是函数
今天我们就一起来学习 Python 的函数。
1. 函数
函数的定义
- 函数以
def
关键词开头,后接函数名和圆括号()。 - 函数执行的代码以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回
None
。
def functionname(parameters):"函数_文档字符串"function_suitereturn [expression]
函数的调用
Sample01:
def printme(str):print(str)printme("我要调用用户自定义函数!") # 我要调用用户自定义函数!
printme("再次调用同一函数") # 再次调用同一函数
temp = printme('hello') # hello
print(temp) # None
Sample02:
def add(a, b):print(a + b)add(1, 2) # 3
add([1, 2, 3], [4, 5, 6]) # [1, 2, 3, 4, 5, 6]
函数文档
def MyFirstFunction(name):"函数定义过程中name是形参"# 因为Ta只是一个形式,表示占据一个参数位置print('传递进来的{0}叫做实参,因为Ta是具体的参数值!'.format(name))MyFirstFunction('老马的程序人生')
# 传递进来的老马的程序人生叫做实参,因为Ta是具体的参数值!print(MyFirstFunction.__doc__)
# 函数定义过程中name是形参help(MyFirstFunction)
# Help on function MyFirstFunction in module __main__:
# MyFirstFunction(name)
# 函数定义过程中name是形参
函数参数
Python 的函数具有非常灵活多样的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。从简到繁的参数形态如下:
- 位置参数 (positional argument)
- 默认参数 (default argument)
- 可变参数 (variable argument)
- 关键字参数 (keyword argument)
- 命名关键字参数 (name keyword argument)
- 参数组合
1. 位置参数
def functionname(arg1):"函数_文档字符串"function_suitereturn [expression]
arg1
- 位置参数 ,这些参数在调用函数 (call function) 时位置要固定。
2. 默认参数
def functionname(arg1, arg2=v):"函数_文档字符串"function_suitereturn [expression]
arg2 = v
- 默认参数 = 默认值,调用函数时,默认参数的值如果没有传入,则被认为是默认值。- 默认参数一定要放在位置参数 后面,不然程序会报错。
def printinfo(name, age=8):print('Name:{0},Age:{1}'.format(name, age))printinfo('小马') # Name:小马,Age:8
printinfo('小马', 10) # Name:小马,Age:10
- Python 允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
def printinfo(name, age):print('Name:{0},Age:{1}'.format(name, age))printinfo(age=8, name='小马') # Name:小马,Age:8
3. 可变参数
顾名思义,可变参数就是传入的参数个数是可变的,可以是 0, 1, 2 到任意个,是不定长的参数。
def functionname(arg1, arg2=v, *args):"函数_文档字符串"function_suitereturn [expression]
*args
- 可变参数,可以是从零个到任意个,自动组装成元组。- 加了星号(*)的变量名会存放所有未命名的变量参数。
def printinfo(arg1, *args):print(arg1)for var in args:print(var)printinfo(10) # 10
printinfo(70, 60, 50)# 70
# 60
# 50
4. 关键字参数
def functionname(arg1, arg2=v, *args, **kw):"函数_文档字符串"function_suitereturn [expression]
**kw
- 关键字参数,可以是从零个到任意个,自动组装成字典。
def printinfo(arg1, *args, **kwargs):print(arg1)print(args)print(kwargs)printinfo(70, 60, 50)
# 70
# (60, 50)
# {}
printinfo(70, 60, 50, a=1, b=2)
# 70
# (60, 50)
# {'a': 1, 'b': 2}
「可变参数」和「关键字参数」的同异总结如下:
- 可变参数允许传入零个到任意个参数,它们在函数调用时自动组装为一个元组 (tuple)。
- 关键字参数允许传入零个到任意个参数,它们在函数内部自动组装为一个字典 (dict)。
5. 命名关键字参数
def functionname(arg1, arg2=v, *args, *, nkw, **kw):"函数_文档字符串"function_suitereturn [expression]
*, nkw
- 命名关键字参数,用户想要输入的关键字参数,定义方式是在nkw 前面加个分隔符 *。- 如果要限制关键字参数的名字,就可以用「命名关键字参数」
- 使用命名关键字参数时,要特别注意不能缺少参数名。
def printinfo(arg1, *, nkw, **kwargs):print(arg1)print(nkw)print(kwargs)printinfo(70, nkw=10, a=1, b=2)
# 70
# 10
# {'a': 1, 'b': 2}printinfo(70, 10, a=1, b=2)
# TypeError: printinfo() takes 1 positional argument but 2 were given
- 没有写参数名
nwk
,因此 10 被当成「位置参数」,而原函数只有 1 个位置函数,现在调用了 2 个,因此程序会报错。
6. 参数组合
在 Python 中定义函数,可以用位置参数、默认参数、可变参数、命名关键字参数和关键字参数,这 5 种参数中的 4 个都可以一起使用,但是注意,参数定义的顺序必须是:
- 位置参数、默认参数、可变参数和关键字参数。
- 位置参数、默认参数、命名关键字参数和关键字参数。
要注意定义可变参数和关键字参数的语法:
*args
是可变参数,args
接收的是一个tuple
**kw
是关键字参数,kw
接收的是一个dict
命名关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。定义命名关键字参数不要忘了写分隔符 *
,否则定义的是位置参数。
警告:虽然可以组合多达 5 种参数,但不要同时使用太多的组合,否则函数很难懂。
函数的返回值
Sample01:
def add(a, b):return a + bprint(add(1, 2)) # 3
print(add([1, 2, 3], [4, 5, 6])) # [1, 2, 3, 4, 5, 6]
Sample02:
def back():return [1, '小马的程序人生', 3.14]print(back()) # [1, '小马的程序人生', 3.14]
Sample03:
def back():return 1, '小马的程序人生', 3.14print(back()) # (1, '小马的程序人生', 3.14)
Sample04:
def printme(str):print(str)temp = printme('hello') # hello
print(temp) # None
print(type(temp)) # <class 'NoneType'>
变量作用域
- Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
- 定义在函数内部的变量拥有局部作用域,该变量称为局部变量。
- 定义在函数外部的变量拥有全局作用域,该变量称为全局变量。
- 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
def discounts(price, rate):final_price = price * ratereturn final_priceold_price = float(input('请输入原价:')) # 98
rate = float(input('请输入折扣率:')) # 0.9
new_price = discounts(old_price, rate)
print('打折后价格是:%.2f' % new_price) # 88.20
- 当内部作用域想修改外部作用域的变量时,就要用到
global
和nonlocal
关键字了。
num = 1def fun1():global num # 需要使用 global 关键字声明print(num) # 1num = 123print(num) # 123fun1()
print(num) # 123
内嵌函数
def outer():print('outer函数在这被调用')def inner():print('inner函数在这被调用')inner() # 该函数只能在outer函数内部被调用outer()
# outer函数在这被调用
# inner函数在这被调用
闭包
- 是函数式编程的一个重要的语法结构,是一种特殊的内嵌函数。
- 如果在一个内部函数里对外层非全局作用域的变量进行引用,那么内部函数就被认为是闭包。
- 通过闭包可以访问外层非全局作用域的变量,这个作用域称为 闭包作用域。
def funX(x):def funY(y):return x * yreturn funYi = funX(8)
print(type(i)) # <class 'function'>
print(i(5)) # 40
- 闭包的返回值通常是函数。
def make_counter(init):counter = [init]def inc(): counter[0] += 1def dec(): counter[0] -= 1def get(): return counter[0]def reset(): counter[0] = initreturn inc, dec, get, resetinc, dec, get, reset = make_counter(0)
inc()
inc()
inc()
print(get()) # 3
dec()
print(get()) # 2
reset()
print(get()) # 0
- 如果要修改闭包作用域中的变量则需要
nonlocal
关键字
def outer():num = 10def inner():nonlocal num # nonlocal关键字声明num = 100print(num)inner()print(num)outer()# 100
# 100
递归
- 如果一个函数在内部调用自身本身,这个函数就是递归函数。
Sample01:n! = 1 x 2 x 3 x ... x n
循环:
n = 5
for k in range(1, 5):n = n * k
print(n) # 120
递归:
def factorial(n):if n == 1:return 1return n * fact(n - 1)print(factorial(5)) # 120
Samp02:斐波那契数列 f(n)=f(n-1)+f(n-2), f(0)=0 f(1)=1
循环:
i = 0
j = 1
lst = list([i, j])
for k in range(2, 11):k = i + jlst.append(k)i = jj = k
print(lst)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
递归:
def recur_fibo(n):if n <= 1:return nreturn recur_fibo(n - 1) + recur_fibo(n - 2)lst = list()
for k in range(11):lst.append(recur_fibo(k))
print(lst)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
- 设置递归的层数,Python默认递归层数为 100
import syssys.setrecursionlimit(1000)
补充:
技术图文:如何实现汉诺塔问题?
2. Lambda 表达式
在 Python 里有两种函数:
- 用
def
关键词的正规函数 - 用
lambda
关键词的匿名函数
匿名函数 (anonymous function)
- 所谓匿名,即不再使用
def
语句定义一个函数。 - python 使用
lambda
来创建匿名函数。 lambda
只是一个表达式,函数体比def
简单很多。lambda
函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。lambda
函数没有所谓的函数名 (function_header),这也是它为什么叫匿名函数。
lambda argument_list: expression
lambda
- 定义匿名函数的关键词。argument_list
- 函数参数,它们可以是位置参数、默认参数、关键字参数,和正规函数里的参数类型一样。:
- 冒号,在函数参数和表达式中间要加个冒号。expression
- 函数表达式,输入函数参数,输出一些值。
sumary = lambda arg1, arg2: arg1 + arg2
print(sumary(10, 20)) # 30func = lambda *args: sum(args)
print(func(1, 2, 3, 4, 5)) # 15
匿名函数 VS 正规函数
lbd_sqr = lambda x: x ** 2
print(lbd_sqr)# <function <lambda> at 0x000000BABB6AC1E0>def sqr(x):return x ** 2print(sqr)
# <function sqr at 0x000000BABD3A4400>print(sqr(9)) # 81
print(lbd_sqr(9)) # 81
- 误用情况:如果用
lambda
函数只是为了赋值给一个变量,用def
的正规函数。 lbd_sqr
的返回值是以<lambda>
标识的函数,而sqr
的返回时是以sqr
为标识的函数,明显后者一看就知道该函数是「计算平方」用的。
Lambda 表达式的应用
高阶函数 (high-order function) 在函数化编程 (functional programming) 很常见,主要有两种形式:
- 参数是函数 (filter, map)
- 返回值是函数 (closure)
下面,看看 map
, filter
的语法:
filter(function, iterable)
过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用list()
来转换。
odd = lambda x: x % 2 == 1
templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(templist)) # [1, 3, 5, 7, 9]
map(function, iterable, ...)
根据提供的函数对指定序列做映射。
m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(list(m1)) # [1, 4, 9, 16, 25]
m2 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
print(list(m2)) # [3, 7, 11, 15, 19]
除了 Python 这些内置函数,我们也可以自己定义高阶函数,如下:
def apply_to_list(fun, some_list):return fun(some_list)
下面代码分别求出列表中所有元素的和、个数和均值。
lst = [1, 2, 3, 4, 5]
print(apply_to_list(sum, lst))
# 15
print(apply_to_list(len, lst))
# 5
print(apply_to_list(lambda x: sum(x) / len(x), lst))
# 3.0
总结
好了,到此为止有关于函数和 Lambda 表达式部分就介绍完了,大家要根据上面的例子多多体会,只有刻意练习才能掌握一门技术,没有捷径的,加油啊!See You!
参考文献:
- https://www.runoob.com/python3/python3-tutorial.html
- https://www.bilibili.com/video/av4050443
- https://mp.weixin.qq.com/s/gKhXS8JVU8dZBHJF7sIFsw
相关图文:
- 资料分享:数学建模资料分享 – 图论部分
- 资料分享:数学建模资料分享 – 神经网络部分
- 如何利用 C# 实现 K 最邻近算法?
- 如何利用 C# 实现 K-D Tree 结构?
- 如何利用 C# + KDTree 实现 K 最邻近算法?
- 如何利用 C# 对神经网络模型进行抽象?
- 如何利用 C# 实现神经网络的感知器模型?
- 如何利用 C# 实现 Delta 学习规则?
- 如何利用 C# 实现 误差反向传播 学习规则?
- 如何利用 C# 爬取带 Token 验证的网站数据?
- 如何利用 C# 向 Access 数据库插入大量数据?
- 如何利用 C# + Python 破解猫眼电影的反爬虫机制?
相关文章:
PHP 实现无限分类
最近打算做一个blog,通常每篇文章都有属于自己的分类。下面就记录下我在写blog时实现无限分类的过程。php框架用的是laravel,根据注释也能轻松改成你习惯的框架。 数据表设计 CREATE TABLE article_category (id int(10) unsigned NOT NULL AUTO_INCREMENT,pid int(…

软件测试培训怎么学?有没有发展前景?
软件测试是最近几年广受大家关注的一个编程技术,软件测试的出现也是因软件的存在而存在的,目前很多人都想知道软件测试培训怎么学?有没有发展前景?我们来看看下面的详细介绍。 软件测试需要学测试环境(网络环境,windows环境等)、数据库管理…

LeetCode实战:最长有效括号
题目英文 Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring. Example 1: Input: "(()" Output: 2 Explanation: The longest valid parentheses substring is "(…

Android选项卡置底的方法
发现很多Android应用的选项卡 都是显示在页面底部的,网上有资料:通过反射获取TabWidget中的私有变量,改变其值。今天反编译了腾讯微薄,发现实现这个很简单, 只需将布局文件中<TabWidget />标签加个android:layout_gravity&…

【iCore4 双核心板_ARM】例程十七:USB_MSC实验——读/写U盘(大容量存储器)
实验方法: 1、将跳线冒跳至USB_UART,通过Micro USB 线将iCore4 USB-UART接口与电脑相连。 2、打开PUTTY软件。 3、通过读U盘转接线将U盘(或者读卡器)与iCore4 USB-OTG接口相连。大容量存储器为FAT32格式。 实验现象: 核心代码&…

软件测试技术篇:UI自动化到底是难是易?
UI自动化技术,是我们测试工程师绕不开的一个话题,只要提起它来,基本所有测试工程师都能给你说道说道。 有些人认为它很难,有些人认为它很简单。认为它很难的人会告诉你,UI自动化非常不稳定,太难了ÿ…

获取DataRow某列的值的封装
public class DataHelper{const string DEFSTR "";/// <summary>/// 根据一个类型,获取其默认值,数字默认是为0,字符串默认值为一个空字符串/// </summary>/// <typeparam name"T"></typeparam>…

LeetCode实战:逆波兰表达式求值
题目英文 Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are , -, *, /. Each operand may be an integer or another expression. Note: Division between two integers should truncate toward zero.The given RPN expre…

Python函数式编程-map/reduce
1.map map()传入的第一个参数是f,即函数对象本身。 map()函数接收两个参数,一个是函数,一个是Interable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。 >>> def f(x): ... re…

Java程序员到什么级别可以去BAT上班?
学习java技术,很多人都想要进入到IT行业,如果跳槽到BAT大厂上班,那更是非常好的,近几年学习java技术的人越来越多,那么Java程序员到什么级别可以去BAT上班?来看看下面的详细介绍。 Java程序员到什么级别可以去BAT上班…

Android开发之SharedPreferences的封装
对于大部分初学者来说,如果想利用SharedPreferences进行数据存储的话大部分人(包括本人)应该会这样: 存储: SharedPreferences sharedPreferences getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE); Editor editor …

LeetCode实战:设计循环双端队列
题目英文 Design your implementation of the circular double-ended queue (deque). Your implementation should support following operations: MyCircularDeque(k): Constructor, set the size of the deque to be k.insertFront(): Adds an item at the front of Deque…

ItemsControl 解析
先上个示例 <ItemsControl Margin"10" ItemsSource"{Binding}" Name"itemsControl"> <ItemsControl.Template><ControlTemplate TargetType"{x:Type ItemsControl}"><Border CornerRadius"5">&l…

【Web前端培训基础知识】ES5及ES6this详解
今天,我们学习一下JavaScript中的this。我们从什么是this,ES5及ES6中this的几种情况进行学习。让this变的so easy,我们这里说的都是非严格模式下。 什么是this this表示当前行为执行的主体,在javaScript中this不是函数独有的,但是…

LeetCode实战:滑动窗口最大值
题目英文 Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sli…

Partial Class部分类
Partial Class ,部分类 或者分布类。顾名思义,就是将一个类分成多个部分。比如说:一个类中有3个方法,在VS 2005将该类中3个方法分别存放在3个不同的.cs文件中。这样做的好处:1、一个大型的项目类可以同时分成不同的区块…

表格中td限宽溢出以省略号代替
table.ms-listviewtable {table-layout:fixed;width: 100%; } table.ms-listviewtable td[role"gridcell"]{white-space:nowrap;text-overflow:ellipsis;-moz-text-overflow: ellipsis;overflow:hidden; } 转载于:https://www.cnblogs.com/JaneBlog/p/7490445.html

【UI设计培训基础知识】设计中的点线面-线
UI设计所要学习的知识有很多,想要在后期的工作中稳稳当当,基础知识一定要扎实,下面就是小编为大家整理的一份关于UI设计培训基础知识的相关内容,主要讲的是设计中的点线面-线,来看看下面的详细资料吧。 点的移动形成一…

场面话大全,绝对受用一生
◆ 父母生日祝酒辞 尊敬的各位领导、各们长辈、各们亲朋好友:大家好! 在这喜庆的日子里,我们高兴地迎来了敬爱的父亲(母亲)XX岁的生日。今天,我们欢聚一堂,举行父亲(母亲)…

LeetCode实战:爬楼梯
题目英文 You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? Note: Given n will be a positive integer. Example 1: Input: 2 Output: 2 Exp…

Visual Studio Remote Debugger(for 2005/2008) .net远程调试转
我采用虚机的方式模拟了局域网环境,以下是我操作的步骤(client代表客户端,server代表调试机): 建立ASP.NET项目(client):简单写了点Code 代码 1 protectedvoidPage_Load(objectsender, EventArgs e)2 {3 in…

UI设计师必备技能,看看你都学会了吗?
想要成为一名合格的UI设计师,是要有这几项必备技能的,学会这些必备技能,那么后期的工作会进行的相当顺利,下面小编就为大家详细的介绍一下UI设计师必备技能都有哪些? UI设计师必备技能,看看你都学会了吗? 1、设计软件…

CSS中关于清除浮动的问题
1.采用:after的方法清除浮动 优点:避免在html里插入多余的标签 详情:http://www.positioniseverything.net/easyclearing.html 整理成一个通用的.clearfix .clearfix:after {content:".";display:block;height:0;clear:both;visibility:hidden…

LeetCode实战:x 的平方根
题目英文 Implement int sqrt(int x). Compute and return the square root of x, where x is guaranteed to be a non-negative integer. Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned. …
Vue中组件数据的传递
Vue中组件的作用域是隔离的,父组件中的数值子组件看不到!也就是说,用angular作比喻,组件的scope天生是scope:()的!如果父组件需要往子组件中传数据,此时应该使用标签属性: <div id"app&…

学习Python往哪个方向发展好
Python近几年在IT行业的发展前景是非常可观的,尤其是在人工智能领域这一块,吸引了很多人的关注,但不仅仅是人工智能领域,Python在很多其他地方也是非常有发展前景的,那么具体学习Python往那个方向发展好呢?来看看下面…

开发人员绩效考核中有效bug数的统计
我们都知道,开发人员的考核中,bug这块占了一定的比重,那么我们在统计每个开发人员的bug数时,显然要做到有效,不能把缺陷管理系统上的bug不经过处理,就直接进行统计. 如何统计有效bug数呢? 我们从bug的属性上进行控制,分析如下: bug问题来源: 需求问题架构问题设计问题编码问题…

LeetCode实战:反转字符串
题目英文 Write a function that reverses a string. The input string is given as an array of characters char[]. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. You may assume al…

HTML5 监听当前位置
2019独角兽企业重金招聘Python工程师标准>>> <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>监听当前位置</title><meta name"viewport" content"widthdevice-width, initial-scale1,…

Python培训教程之Python基础知识点梳理
Python语言是入门IT行业比较快速且简单的一门编程语言,学习Python语言不仅有着非常大的发展空间,还可以有一个非常好的工作,下面小编就来给大家分享一篇Python培训教程之Python基础知识点梳理。 Python培训教程之Python基础知识点梳理&#x…