(董付国)Python 学习笔记---Python函数设计与使用(2)

5.3.2 关键参数

  • 关键参数主要指实参,即调用函数时的参数传递方式
  • 通过关键参数,实参顺序可以和形参顺序不一致,但不影响传递结果,避免了用户需要牢记位置参数顺序的麻烦。
>>> def demo(a,b,c = 5):
...     print(a,b,c)
...
>>> demo(3,7)
3 7 5
>>> demo(a = 7,b = 3,c = 6)
7 3 6
>>> demo(c = 8,a = 9,b = 0)
9 0 8

5.3.3 可变长度参数

  • 可变长度参数主要有两种形式:
    1.*parameter用来接受多个实参并将其放在一个元组
在这里插入代码片
>>> def demo(*p):
...     print(p)
...
>>> demo(1,2,3)
(1, 2, 3)
>>> demo(1,2)
(1, 2)

2.**parameter用来接受关键参数并存放到字典中

>>> def demo(**p):
...     for item in p.items():
...             print(item)
...
>>> demo(x=1,y=2,c=3)
('x', 1)
('y', 2)
('c', 3)
  • 几种不同类型的参数可以混合使用,但是不建议这样做
>>> def func(a,b,c=4,*aa,**bb):
...     print(a,b,c)
...     print(aa)
...     print(bb)
...
>>> func(1,2,3,4,5,6,7,8,9,xx='1',yy='2',zz=3)
1 2 3
(4, 5, 6, 7, 8, 9)
{'xx': '1', 'yy': '2', 'zz': 3}

5.3.4 参数传递的序列解包

  • 传递参数时,可以通过在实参序列前加一个星号将其解包,然后传递给多个单变量形参。
>>> def demo(a,b,c):
...     print(a+b+c)
...
>>> demo(1,2,3)
6
>>> seq = [1,2,3]
>>> demo(seq)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: demo() missing 2 required positional arguments: 'b' and 'c'
>>> demo(*seq)			#实参序列前加‘*’
6
>>> tup = (1,2,3)
>>> demo(tup)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: demo() missing 2 required positional arguments: 'b' and 'c'
>>> demo(*tup)			#实参序列前加‘*’
6
>>> dic = {1:'a',2:'b',3:'c'}
>>> demo(*dic)			#实参序列前加‘*’
6
>>> set = {1,2,3}
>>> demo(*set)			#实参序列前加‘*’
6
>>> demo(*dic.values())
abc
  • 注意:调用函数时如果对实参使用一个星号*进行序列解包,这么这些解包后的实参将会被当作普通位置参数对待,并且会在关键参数和使用两个星号**进行序列解包的参数之前进行处理。
>>> def demo(a,b,c):
...     print(a,b,c)
...
>>> demo(*(1,2,3))              #调用,序列解包
1 2 3
>>> demo(1,*(2,3))              #位置参数和序列解包同时使用
1 2 3
>>> demo(1,*(2),3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: demo() argument after * must be an iterable, not int
>>> demo(1,*(2,),3)
1 2 3
>>> demo(a=1,*(2,3))            #序列解包相当于位置参数,优先处理
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: demo() got multiple values for argument 'a'
>>> demo(b=1,*(2,3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: demo() got multiple values for argument 'b'
>>> demo(c=1,*(2,3))
2 3 1
>>> demo(**{'a':1,'b':2},*(3,)) #序列解包不能在关键参数解包之后
  File "<stdin>", line 1
SyntaxError: iterable argument unpacking follows keyword argument unpacking
>>> demo(*(3,),**{'a':1,'b':2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: demo() got multiple values for argument 'a'
>>> demo(*(3,),**{'b':1,'c':2})
3 1 2

5.4 return语句

  • return语句用来从一个函数中返回一个值,同时结束函数。
  • 如果函数没有return语句,或者有return语句但是没有执行到,或者只有return而没有返回值,Python将认为该函数以return None结束。
  • 在调用函数或对象方法时,一定要注意有没有返回值,这决定了该函数或方法的用法。

5.5 变量作用域

  • 变量起作用的代码范围成为变量的作用域,不同作用域内变量名可以相同,互不影响。
  • 一个变量在函数外部定义和在函数内部定义,作用域是不同的。
  • 在函数内部定义的普通变量只在函数内部起作用,称为局部变量。当函数执行结束后,局部变量自动删除,不再可以使用。
  • 局部变量的引用比全局变量速度快,应优先考虑使用。

也可以这么理解:

  • 在函数内如果只引用某个变量的值而没有为其赋新值,该变量为(隐式)全局变量;
  • 如果在函数内任意位置有为变量赋新值的操作,该变量即被认为是(隐式的)局部变量,除非在函数内显示地用关键字global进行声明。
>>> def demo():
...     global x
...     x = 3
...     y = 4
...     print(x,y)
...
>>> x = 5
>>> demo()
3 4
>>> x
3
>>> y                   #因为在函数外部,函数已经结束了,栈帧已经回收了
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
  • 注意:在某个作用域内只要有为变量赋值的操作,该变量在这个作用域内就是局部变量,除非使用global进行了声明。
>>> x = 3
>>> def f():
...     print(x)                #本意是先输出全局变量X的值,但是不允许这样做
...     x = 5                   #有赋值操作,因此在整个作用域内x都是局部变量
...     print(x)
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment
  • 如果局部变量与全局变量具有相同的名字,那么该局部变量会在自己的作用域内隐藏同名的全局变量。
>>> def demo():
...     x = 3           #创建了局部变量,并自动隐藏了同名的全局变量
...
>>> x = 5
>>> x
5
>>> demo()				#函数执行,不影响外面全局变量的值
>>> x
5
  • 如果需要在同一个程序的不同模块之间共享全局变量的话,可以编写一个专门的模块来实现这一目的。
  • 除了局部变量和全局变量,Python还支持使用nonlocal关键字定义的一种介于二者之间的变量。关键字nonlocal声明的变量会引用距离最近的非全局作用域的变量,要求声明的变量已经存在,关键字nonlocal不会创建新变量
def scope_test():
    def do_local():
        spam = "我是局部变量"
    def do_nonlocal():
        nonlocal spam                               #这是要求spam必须是已存在的变量
        spam = "我不是局部变量,也不是全局变量"        
    def do_global():
        global spam                                 #如果全局作用域内没有spam,就自动新建一个
        spam = "我是全局变量"

    spam = "原来的值"
    do_local()
    print("局部变量赋值后:",spam)
    do_nonlocal()
    print("nonlocal赋值后:",spam)
    do_global()
    print("全局变量赋值后:",spam)

scope_test()
print("全局变量:",spam)

运行结果:

局部变量赋值后: 原来的值
nonlocal赋值后: 我不是局部变量,也不是全局变量
全局变量赋值后: 我不是局部变量,也不是全局变量
全局变量: 我是全局变量

5.6 lambda表达式

  • lambda表达式可以用来声明匿名函数,也就是没有函数名字的临时使用小函数,尤其适合需要一个函数作为另一个函数参数的场合。
  • lambda表达式只可以包含一个表达式,该表达式的计算结果可以看作是函数的返回值,不允许包含其他复杂的语句,但在表达式中可以调用其他函数。
>>> f = lambda x,y,z:x+y+z              #可以给lambda表达式起名字
>>> f(1,2,3)
6
>>> g = lambda x,y=2,z=3:x+y+z          #参数默认值
>>> g(1)
6
>>> g(2,z=4,y=5)                        #关键参数
11
>>> L = [(lambda x:x**2),(lambda x:x**3),(lambda x:x**4)]
>>> print(L[0](2),L[1](2),L[2](2))
4 8 16
>>> D = {'f1':(lambda:2+3),'f2':(lambda:2*3),'f3':(lambda:2**3)}
>>> print(D['f1'](),D['f2'](),D['f3']())
5 6 8
>>> L = [1,2,3,4,5]
>>> print(list(map(lambda x:x+10,L)))           #模拟向量运算
[11, 12, 13, 14, 15]
>>> L
[1, 2, 3, 4, 5]
>>> def demo(n):
...     return n*n
...
>>> demo(5)
25
>>> a_List = [1,2,3,4,5]
>>> list(map(lambda x:demo(x),a_List))          #在lambda表达式中调用函数
[1, 4, 9, 16, 25]
>>> data = list(range(20))                      #创建列表
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> import random
>>> random.shuffle(data)                        #打乱顺序
>>> data
[16, 10, 5, 15, 13, 4, 8, 12, 0, 6, 19, 7, 1, 2, 18, 3, 14, 11, 17, 9]
>>> data.sort(key=lambda x:x)                   #和不指定规则效果一样
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data.sort(key=lambda x:len(str(x)))         #按转换成字符串以后的长度排序
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data.sort(key=lambda x: len(str(x)),reverse=True)           #降序排序
>>> data
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
posted @ 2019-08-31 12:02  旅人_Eric  阅读(347)  评论(0编辑  收藏  举报