python 疯狂讲义(函数和lambda表达式)

为函数提供文档

>>> def max_my(x,y):
...     '''
...     aaa
...     '''
...     return x,y
... 
>>> help(max_my)

Help on function max_my in module __main__:

max_my(x, y)
    aaa
(END)

多个返回值:

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

递归函数:

递归是非常有用的,例如程序希望遍历某个路径下的所有文件,但这个路径下的文件夹的深度是未 知的,那么就可以使 用递归来实现这个需求。系统可定义一个函数,该函数接收一个文件路径作为参数,该函数可遍历出当前路径下的所有文件和文件路径一一-在该函数的函数体中再次调用函数自身来 处 理该路径 下的所有文件路径。递归一定要向己知方向进行。

函数的参数:

注:Python 要求将带默认值的参数定义在形参列表的最后 。

按照形参位置传入的参数被称为位置参数。如果使用位置参数的方式来传入参数值,则必须严格按照走义函数时指定的顺序来传入参数值:如果根据参数名来传入参数值,则无须遵守定义形参的顺序,这种方式被称为关键字参数。需要说明的是,如果希望在调用函数时混合使用关键字参数和位置参数,则关键字参数必须位于位置参数之后 。 换句话说,在关键字参数之后的只能是关键字参数 。由于 Python 要求在调用函数时关键字参数必须位于位置参数的后面,因此在定义函数时指定了默认值的参数(关键字参数)必须在没有默认值的参数之后 。

参数收集(个数可变的参数):

Python 允许在形参前面添加一个星号(*),这样就意味着该参数可接收多个参数值,多个参数值被当成元组传入。

>>> def test(a,*books):
...     print(books)
...     for b in books:
...         print(b)
...     print(a)
... 
>>> test(5,"qqq","www")
('qqq', 'www')
qqq
www
5
>>> 

由上面看,参数收集的本质就是 一个元组 ,Python 会将传给 books 参数的多个值收集成一 个元组 。

Python 允许个数可变的形参可以处于形参列表的任意位置(不要求是形参列表的最后一个参数〉,但 Python 要求一个函数最多只能带一个支持“普通”参数收集的形参。函数的第 一 个参数是个可变的形参,由于该参数可接收个数不等 的 参数值,因此如果需要给后面的参数传入参数值,则必须使用关键字参数(以参数名传参) ; 否 则 ,程序会把所传入的多个值都当成是传给 参数收集的形参。

Python 还可以收集关键宇参数,此时 Python 会将这种关键宇参数收集成字典。为了让 Python能收集关键字参数,需要在参数前面添加两个星号。在这种情况下,一个函数可同时包含一个支持“普通”参数收集的参数和 一个支持关键字参数收集的参数。

>>> def test(x,y,z=3,*books,**scores):
...     print(x,y,z)
...     print(books)
...     print(scores)
... 
>>> test(1,2,3,"111","222",语文=89,数学=94)
1 2 3
('111', '222')
{'语文': 89, '数学': 94}

逆向参数收集:指的是在程序己 有 列表、元组、 宇典等对象 的前提下,把它们的元素“ 拆开”后传给函数的参数

>>> def test(name,message):
...     print("user:",name)
...     print("message:",message)
... 
>>> my_list = ["111","222"]
>>> test(*my_list)
user: 111
message: 222

为了让程序将 my_list 列表 的两个元素传给 test() 函数,程序在传入 的 my_list 参数之前添加 了一个 星号。

实际上,即使是支持收集的参数,如果程序需要将 一个元组传给该参数,那么同样需要使用逆向收集:

>>> def foo(name,*nums):
...     print("name参数",name)
...     print("name参数",nums)
... 
>>> my_tuple = (1,2,3)
#使用逆向收集将 my_tuple包含的多个元素传给 nums 参数, nums 再将 my_tuple的多个元素收集成元组 。
>>> foo('fkit',*my_tuple)
name参数 fkit
name参数 (1, 2, 3)

#将元组传给参数nums,再将nums收集成元组,因此 有两个括号
>>> foo('fkit',my_tuple)
name参数 fkit
name参数 ((1, 2, 3),)

字典也支持逆向收集,字典将会以关键字参数的形式传入。

>>> def bar(book,price,desc):
...     print(book,"这本书的价格是:",price)
...     print('描述信息',desc)
... 
>>> my_dict = {'price':89,'book':"疯狂python",'desc':"aaaa"}
>>> bar(**my_dict)
疯狂python 这本书的价格是: 89
描述信息 aaaa

函数的参数传递机制:

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

注意:向函数swap()中传递字典dw:这种参数传递方式是不 折不扣的值传递方式(只是传的是引用/地址) , 系统一样复制了 dw 的 副本传入swap ()函数 。 但由于 dw 只是 一个引用 变量 ,因此系统复制的 是 dw 变量 ,并未 复 制字 典 本身。当程序在 swap ()函 数 中操作 dw 参数 时 ,由于 dw 只是 一 个引用变量,放实际操作的还是字典对象。此时,不管是操作主程序中的 dw 变量,还是操作 swap() 函数里的 dw 参数,其实操作的都是它们共同引用的字典对象,它 们 用的是同 一 个字典对象。因 此, 当在 swap() 函数中交换 dw 参数所 引 用字典对象的 a 、 b 两个元素的值后,可以看到在主程序中 dw 变量所引用字典对象的 a 、 b两个元素的值也被交换了。

 

通过上面介绍可以得出如下两个结论:
不管什么 类型的参数,在 Python 函 数中对参数直接使用“ =” 符号赋值是没用 的 ,直接使用“=”符号赋值并不能改变参数。
如果需要让函数修改某些数据 ,则可以通过把这些数据包装成列表、字典等可变对象,然后把列表、宇典等可变对象作为参数传入函数,在函数 中 通过列 表 、 字典的方法修改它们,这样才能改变这些数据。

 

变量作用域:

局部变量。在函数中定义的变量,包括参数,都被称为局部变量。

全局变量。在函数外面、全局范围内定义的变量 , 被称为全局变量。

每个函数在执行时,系统都会为该函数分配一块“ |临时内存空间”,所有的局部变量都被保存在这块临时内存空间内。当函数执行完成后,这块内存空间就被释放了,这些局部变量也就失效了,因此离开函数之后就不能再访问局部变量了。从这个角度来看 , 不管是局部范围还是全局范围,这些变革和它们的值就像一个“看不见”的字典 , 其中变量名就是字典的 key ,变量值就是字典的 value 。

globals() : 该函数返回全局范围内所有变量组成的“变量字典” 。
locals():该函数返回当前局部范围内所有变量组成的“变量字 典” 。
vars(object):获取在指定对象范围内所有变量组成的“变量字典”。如 果不传入object参数, vars()和loacals()的作用完全相同。

globals()和 locals()看似完全不同,但它们实际上也是有联系的, 关于这 两个函数的区别和联系大致有以下两点 。
locals()总是获取当前局部范围内所有变量组成的“变量字典”,因此,如果在全局范围内(在函数之 外 )调用 l ocals()函数,同样会获取全局范围内所有变量组成的“变量宇典;而globals()无论在哪里执行, 总是获取全局范围内所有变量 组成的“变量字典。
一般来说,使用 locals()和 globals()获取的“变量字典”只应该被访问,不应该被修改 。但实际上,不管是使用 globals()还是使用 locals() 获取的全局范围内的“变量字典’ , 都可以被修改,而这种修改会真正改变全局变量本身:但通过 locals()获取的局部范围内的“变量字典”,即使对它修改也不会影响局部变量。

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

>>> name = "Charlie"
>>> def test():
...     print(name)
...     name ="孙悟空"
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
UnboundLocalError: local variable 'name' referenced before assignment

Python 语法规定 : 在函数内部对不存在的变量赋值 时, 默认就是重新定义新的局部变量。因此这行代码相当于重新定义了 name 局部变量,这样 name 全局变 量就被遮蔽了,所以会报错。通过两种方式来修改上:

(1)访问被遮蔽的全局变量

如果程序希望在print(name)代码依然能访问 name 全局变量,且在print(name)代码之后可重新定义 name局部变量-----也就是在函数中可以访问被遮蔽的全局变量, 此时可通过 globals () 函数来实现,如下:

>>> def test():
...     print(globals()['name'])
...     name ="孙悟空"
... 
>>> test()
Charlie
>>> print(name)
Charlie
>>> 

(2)在函数中声明全局变量

为了避免在函数中对全局变量赋值(不是重新定义局部变量),可使用 global 语句来声明全局变量。增加了“ global name”声明之后,程序会把 name 变量当成全局变量,这意味着 test()函数后面对 name 赋值的语句只是对全局变量赋值,而不是重新定义局部变量。如下:

>>> def test():
...     global name
...     print(name)
...     name = "孙悟空"
... 
>>> test()
Charlie
>>> print(name)
孙悟空

 

局部函数:

函数都是在全局范围内定义的,它们都是全局函数,Python 还支持在函数体内定义函数 , 这种被放在函数体内定义的函数称为局部函数。

局部函数内的变量 也会遮蔽它所在函数内的局部变量,如下:

>>> def foo():
...     name = 'Charlie'
...     def bar():
...         print(name)
...         name = '孙悟空'
...     bar()
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

该错误是由局部变量遮蔽局部变量导致的,为了声明 bar()函数中的“ name=’孙悟空”’ 赋值语句不是定义新的局部变量,只是访问它所在
foo ()函数内的 name 局部变 量 , Python 提供了 nonlocal 关键字,通过 nonlocal 语句即可声明访问赋值语句只是访问该函数所在函数内的局部变量。

 

nonlocal 和前面介绍的 global 功能大致相似,区别只是 global 用于声明访问全局变量,而 nonlocal 用于声明访问当前函数所在函数内的局部变量。

 

局部函数与 lambda 表达式:

如果说函数是命名的、方便复用的代码块,那么 lambda表达式则 是功能更灵活 的代码块,局部函数的函数名没有太大的意义,那么就考虑使用 lambda 表达式来简化局部函数的写法。

>>> c = lambda n: n*n
>>> c(3)
9

Python 要求 lambda 表达式只能是单行表达式。

lambda 表达式的语法格式如下:
lambda [parameter_list ] : 表达式

几个要点:lambda 表达式必须使用 lambda 关键字定义 。在 lambda 关键字之后、冒号左边的是参数列表,可以没有参数,也可以有多个参数 。 如果有多个参数, 则 需要用逗号隔开,冒号右边是该 lambda 表达式的返回值

lambda 表达式的本质就是匿名的、单行函数体的函数。可以写成函数形式,比如 lambda x,y : x+y 可以携程def add(x, y): return x+y

总体来说,函数比 lambda 表达式的适应性更强, lambda 表达式只能创建简单的函数对象,但 lambda 表达式依然有如下两个用途 。(1)对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁。(2)对于不需要多次复用的函数 , 使用 lambda 表达式可以在用完之后立即释放,提高了性能 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Lambda表达式Python中的一种匿名函数,它可以在一行代码中定义一个函数Lambda表达式通常用于简单的函数,它们可以作为参数传递给其他函数或作为返回值返回。 Lambda表达式的语法如下: lambda 参数列表: 表达式 其中,参数列表是用逗号分隔的形式参数,表达式是函数的返回值。 例如,下面的代码定义了一个简单的Lambda函数: f = lambda x: x * x 这个函数接受一个参数x,并返回x的平方。我们可以像调用普通函数一样调用它: print(f(5)) # 输出25 Lambda表达式还可以用于定义匿名函数,例如: g = lambda x, y: x + y 这个函数接受两个参数x和y,并返回它们的和。我们可以像调用普通函数一样调用它: print(g(2, 3)) # 输出5 总之,Lambda表达式Python中一种非常方便的函数定义方式,它可以让我们更加简洁地编写代码。 ### 回答2: Lambda表达式Python函数中的一种简洁方式,它可以定义在一行内的匿名函数。Lambda使用关键字“lambda”来表示,后面跟随一个或多个参数,分隔符为逗号,然后是冒号和一个表达式。返回值是该表达式的结果。 Lambda表达式的基本语法如下: lambda arguments: expression 其中arguments参数可以是0个、1个或多个参数,expression表达式是lambda函数的返回值。 Lambda表达式的使用场景比较广泛,通常用于函数式编程、过滤器(filter)、映射器(map)、排序器(sort)等操作中。 例如,我们可以使用lambda表达式来定义一个简单的函数: x = lambda a : a + 10 print(x(10)) # 输出结果为20 上述例子中,lambda表达式定义了一个参数“a”,表达式为“a+10”,即函数返回值为传入参数a加上10。 当需要对一个列表中的元素进行操作时,我们可以使用map函数结合lambda表达式来实现: lst = [1, 3, 5, 7] result_lst = list(map(lambda x:x*2, lst)) print(result_lst) # 输出结果为[2, 6, 10, 14] 上述例子中,lambda表达式定义了一个参数“x”,表达式为“x*2”,即将列表中的每个元素乘以2。map函数将该lambda表达式应用于lst中的每个元素,返回一个新的列表。 Lambda表达式比较适用于简单的函数定义和一些简单的操作,但对于较为复杂的任务或需要频繁使用的代码,建议还是使用函数进行定义。 ### 回答3: Python是一种广泛使用的编程语言,而函数Python编程的重要部分。在Python中,函数是一个特殊的代码块,可以接受一些输入(参数),并在执行一些操作后返回输出。其中,lambda表达式是定义函数的一种不同方式。 lambda表达式也被称为匿名函数,因为它们可以定义一个没有名称的函数。与普通函数不同,lambda函数只能包含一个表达式,而不是一条语句块。语法如下: lambda 参数: 表达式 下面是一个简单的例子: add = lambda x, y: x + y print(add(2, 3)) # 输出5 在这个例子中,lambda函数的定义是add = lambda x, y: x + y,其中参数是x和y,表达式是x + y。定义后,我们可以像使用普通函数一样使用它。 lambda函数有许多用途。其中之一是作为其他函数的参数,例如在sort()函数中进行排序。例如,我们可以使用lambda函数按照列表中每个元素的第二个元素进行排序。实现方式如下: a = [(1, 2), (4, 1), (9, 10), (13, -3)] a.sort(key=lambda x: x[1]) # 按每个元组的第二个元素进行排序 print(a) 输出结果为:[(13, -3), (4, 1), (1, 2), (9, 10)] 总之,Lambda表达式Python语言中一个十分有用的特性,它允许我们创建匿名函数,使代码变得更加简洁和易读。在实际编程中,可以将其用于诸如函数参数传递、过滤器、排序等许多编程任务中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值