Python基础刻意训练——DAY5
学习内容:
1.主要内容:函数与lambda表达式
前言:
函数作为程序的重要组成部分,连接起了各种复杂的部分:一方面,函数将需要的功能进行封装,避免了变量的命名出现重复的情况,也保证了程序的稳定性,与检查代码的简便性。另一方面,函数避免了重复书写代码,提升效率,方便调用。
而lambda表达式则更加强化函数的简便性,它可以直接书写与调用,不必再去def(定义)函数,也更加方便了变量的命名。
1)函数:
- 创建函数
基本格式
def 函数名(参数):
函数体
(返回值)
注意:创建函数,必须要加上冒号(:)
后面调用函数。
示例:
def square(x):
return x*x
square(15) ###求15的平方
- 形参与实参:
-
形参不影响实参
-
函数是返回‘值’,过程是没有返回值的;python一般没有返回值,只有过程(不写return的时候)
其实(不写return的时候)也在返回值——None;
python动态确定类型,可以返回多个值
示例:
def back():
return 1,2,6,'shj' ##返回(1,2,6,‘shj’)元组
参考链接:https://www.cnblogs.com/kex1n/p/8285351.html
- 函数变量的作用域问题:
1. 局部变量与全局变量
局部变量不影响全局变量,当出现全局变量与局部变量名字一样时。函数内部创建一个名字一样的变量,从而保护全局变量
但是,global关键字实现局部变量升级为全局变量
2. 内嵌函数:
在内部函数的整个作用域都在外部函数作用域之内(fun2都在fun1之内作用,即除了fun2可以在fun1内部被调用以外,就没有可以调用的了)——只能fun1调用fun2
示例:
def fun1():
print("调用了fun1")
def fun2():
print("调用了fun2")
fun2()
fun1()
实验结果如下:
3. 闭包:
如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数被认为是闭包(closure)------则想要调用funy必须先调用funx,funx不允许funy出轨
示例:
def FunX(x):
def FunY(y):
return x*y
return FunY ##返回的是一个函数——这个函数就是闭包,内部函数FunY()对于外部变量进行了引用(x)
i=FunX(2)
type(i) ###显示的是函数类型
i(5) ##此时调用的是内部函数————并且返回2*5=10
2)lambda表达式:
lambda本质上是构建一个函数对象,是一个匿名函数。
基本形式:
lambda [x,y…](相关参数): x*2+1参数的相关表达式
作用:
- 使得代码简洁,省去定义函数的时间与过程;
- 对于某些抽象函数以及相关的一些只使用一两次的函数,省去了起名字的过程;
- 简化代码的可读性,可以不需要再次返回原来的最初的函数定义中进行代码的阅读,可以直接在lambda中一次性的对函数有着详细的了解。
相关示例与代码:
###lambda表达式
g=lambda x :x*x ##定义平方的表达式
g(15) ##求15的平方
###函数方式
def g(x):
returnx*x
g(x) ##相比之下,lambda省去了def 的过程,省去了对于函数名的命名,更加简洁
3)递归:
递归作为一种分治思想,具有很强的巧妙性。但是使用递归的时候,需要明确:某些情况下的递归效果很好——汉诺塔游戏,树结构的定义,谢尔宾斯基三角形,递归自拍照……而在递归面临着空间开销的问题,如果处理问题的数据量很大,此时用递归可能就不是那么合适。因此,一定要合理审判情况。
在Python中,递归的默认深度设置为100层,网络爬虫可以设置递归深度。
import sys
sys.setrecursionlimit(参数)
递归的精髓在于设置递归形式与终止条件,下面举几个例子,来说明情况:
- 1.求阶乘
def fun(n):
if n==1:
return 1
else:
return n*fun(n-1)
n=int(input('请输入一个正整数:'))
result=fun(n)
print('%d的阶乘是:%d'%(n,result))
- 2.斐波那契数列
###递归方式
def fab(n):
if n<1:
print('输入错误!!')
return -1
if n==1 or n==2:
return 1
else:
return fab(n-1)+fab(n-2)
result = fab(20)
if result !=-1:
print('一共有%d对兔子诞生!!!'% result)
###递归方式
def fab(n):
n1=1
n2=1
n3=1
if n<1:
print('运算错误!!')
return -1
while(n-2)>0:
n3=n1+n2
n1=n2
n2=n3
n-=1
return n3
result=fab(20)
if(result!=-1):
print('总共有%d对小兔崽子诞生!!!'%result)
注意:
在实验中可以发现,当数字量增大的时候,循环结构的运行时间明显快于递归结构运行时间,这再一次说明递归由于空间开销较大,一定要根据具体情况慎用递归。
- 3.汉诺塔游戏
# py10_29.汉诺塔游戏的递归实现.py
def hanoi(n,x,y,z):
if n == 1:
print(x,'-->',z)#如果只有一层,直接从x移动到z
else:
hanoi(n-1,x,z,y)#将前n-1个圆盘从x移动到y上
print(x,'-->',z)#将最底下的第64个圆盘从x移动到z上
hanoi(n-1,y,x,z)#将y上的63个圆盘移动到z上
n = int(input('请输入汉诺塔的层数:'))
hanoi(n,'X','Y','Z')
2.今日学到的BIF
- filter(过滤函数,相关的数据)——过滤掉不需要的东西 ——函数也可以使用lambda表达式实现
注意:
在python2 中,filter直接生成过滤后的序列,而在python3中,得到的是filter的类,需要将其实例化。
相关示例与代码:
y=filter(lambda x:x%2==1 ,[1,2,3,4,5,6]) ###过滤掉不属于奇数的数字,留下奇数
list(y) ###实例化filter类型
- map(迭代的函数,可迭代的序列)
映射:(可迭代函数与序列)将序列的每一个元素作为函数的参数进行加工,直到可迭代序列的每一个元素都加工完毕,返回所有加工后的元素得到的新序列。
相关示例与代码:
y=map(lambda x:x*x ,[1,2,3,4,5,6]) ###返回序列中元素的平方数
list(y) ##实例化map类型
注意:在这些操作中可以发现,lambda表达式对于该应用相当便捷,定义与使用同步进行,省去了许多不必要的工作。