Python学习日记3

Python 学习日记3

——函数和Lambda表达式

3.1 函数

函数是代码复用的重要手段,使程序更加简洁。
定义函数要明白以下几点

  1. 函数需要动态变化的数据,即为函数定义的参数;
  2. 函数需要传出调用函数后得到的数据,这些数据应被定义为返回值。
  3. 函数具体实现的过程,即函数主体。

3.1.1 定义和调用函数

定义函数的语法格式:

def 函数名(参数列表):
    ...
    函数主体
    ...
    [return[返回值]]

  • 函数名只要是一个合法的标识符即可
  • 形参列表:参数之间以逗号隔开
  • retuen语句可以显式的返回一个值,这个值可以是有具体值的变量也可以是一个表达式。

示例代码:

def my_fun(x,y):
    z=x if x>y else y
    return z
result=my_fun(8,15)
print('result:',result)  #输出结果:15
有多个返回值时

如果程序需要多个返回值,则既可以把多个值包装成列表之后返回,也可以直接返回多个值。如果Python函数直接返回多个值,Python会自动将多个返回值封装成元组。

3.1.2 递归函数

函数不仅可以调用其他函数也可以调用函数自身,即为函数递归。函数递归包含了一种隐式的循环,它会重复执行某段代码,但是这种重复执行无需循环控制。经典的例子有求斐波那契数列、求阶乘和求幂等。
递归一定要向已知方向进行:在某个时刻函数的返回值是确定的,即不再调用它自身,否则递归就成了无穷递归,类似死循环。

示例:斐波那契数列

def fibonacci(i):
    if i<=2 and i>0:
        return 1
    else:
        return (fibonacci(i-2)+fibonacci(i-1))


for j in range(1,11):
    print(fibonacci(j),end='  ')  #打印斐波那契数列前十位数字
1  1  2  3  5  8  13  21  34  55 

3.2 函数的参数

3.2.1 关键字参数、位置参数

Python函数的参数名不是无意义的,其允许在调用函数时通过名字来传入参数值。
按照参数位置传入的为位置参数,它是按位置顺序传入的;如果根据参数名来传入参数,则位置顺序就无关紧要。

def Data(width,height):
    return(2*(width*height))
print(Data(4,5)) #根据位置顺序传入参数
print(Data(height=5,width=4)) # 根据关键字传入参数,可调换位置

但是,要求在调用函数时关键字参数关键字参数必须位于位置参数之后。

3.2.2 参数收集与逆向参数收集

  1. 参数收集

很多语言都允许定义个数可变的参数,这样可以在嗲用函数时传入任意多个参数。
Python也一样,其方法实在形参前面添加一个星号 ‘*’,与序列在封包时一样,表示该参数可以接收多个参数值,这些值被当成元组传入。
Python还可以收集关键字参数,会将这些参数收集成字典,此时需要在参数前面添加两个星号。

  1. 逆向参数收集

逆向收集参数即值在程序已有列表、元组等对象的前提下,把他们的元素拆开之后传给函数的参数。
方法也一样,在需要传入的列表元组参数之前添加一个星号,在字典参数之前添加两个星号。

扫描二维码关注公众号,回复: 9108785 查看本文章

3.2.3 参数的传递机制

Python中函数的参数传递机制都是‘值传递’。所谓值传递,就是将实际参数值的副本(复制品)传入函数,而参数本身不会受到任何影响。

  • 不管什么类型的参数,在函数中对函数直接使用“=”符号赋值是没有用的,直接使用等号赋值并不能改变参数。
  • 如果要让函数修改某些数据,则可以通过把这些数据包装成列表、字典等可修改对象,然后把列表、字典等可变对象作为参数传入函数,在函数中通过列表、字典的方法修改他们。

3.2.4 变量作用域

  • 局部变量
  • 全局变量
    Python提供了如下三个工具函数来获取指定范围内的“变量字典”:
  • globals() :返回全局范围内所有变量组成的“变量字典”;
  • locals(): 返回当前局部范围内所有变量组成的“变量字典”;
  • vars(object): 获取在指定对象范围内所有变量组成的“变量字典”,如不传入参数,其跟globals()作用一致。

全局变量默认在所有函数内都可以被访问,但是在函数中定义了与全局变量同名的变量,此时就会发生局部变量遮蔽(hide)全局变量的情形。

name='James'
def NBA():
    print(name)
    name='Durant'
test()
print(name)

#报错:
C:\Users\WD\PycharmProjects:
UnboundLocalError: local variable 'name' referenced before assignment

解决方法:

  1. 通过globals()函数访问name全局变量
  2. 在函数中声明全局变量

3.3 函数的高级内容

函数本身也作为一个对象,既可以用于赋值,也可以用作其他函数的参数,还可以作为其他函数的返回值。

1.使用函数变量
Python的函数也是一种值,所有的函数都时function对象,可以把函数本身赋值给变量,赋值之后程序也可以通过调用变量来调用函数。

2.使用函数作为函数形参

3.使用函数作为返回值

def get_math_fun(type):
    def square(n):
        return n*n   #计算平方的局部函数
    def cube(n):
        return n*n*n   #计算立方的局部函数
    def factorial(n):  #计算阶乘的局部函数
        result=1
        for i in range(2,n+1):
            result*=i
        return  result
    if type=='square':
        return square
    if type=='cube':
        return cube
    else:
        return factorial    #函数作为返回值

math_fn=get_math_fun('cube')
print(math_fn(5)

3.4 局部函数与lambd表达式

在上一段代码中我们引入了三个局部函数来分别计算,但是局部函数的作用域默认仅停留在其封闭函数之内,因而其作用及其有限——仅仅在程序的if语句中作为返回值使用,一旦离开函数体就失去了意义。

既然局部函数名没有太大意义,那么就考虑使用lambda表达式来简化局部函数的写法,如下:

def get_math_fun(type):
    if type=='square':
        return lambda n: n*n
    if type=='cube':
        return lambda n: n*n*n
    else:
        return lambda n: n*(n+1)/2
math_fn=get_math_fun('cube')
print(math_fn(5))

明显简化了很多很多。

lambd表达式的语法格式如下:

lambda[参数列表]:表达式

实际上,lambda表达式的本质就是匿名的、单行函数体的函数。虽然lambda表达式只能创建简单的函数对象,知识和函数体为单行的情形,但他依然有如下两个用途:

  • 对于单行函数,使用lambda表达式省去定义函数的过程,让代码更加简洁。
  • 对于不需要多次复用的函数,使用lambda表达式可以在用完之后立即释放,提高了性能。
发布了4 篇原创文章 · 获赞 0 · 访问量 250

猜你喜欢

转载自blog.csdn.net/weixin_44204830/article/details/104252492