python编程软件_全国青少年软件编程python四级(12.6备考)

函数,参数及参数解构, 返回值,作用域

函数,参数及参数解构

函数

       数学定义: y=f(x),y是x的函数,x是自变量.

   python函数: 完成一定的功能,由若干语句组成的语句块,函数名称,参数列表构成,它是组织代码的最小单位.

    函数的作用:

       结构化变成对代码的最基本的封装,一般按照功能组织一段代码.

       封装的目的为了复用,减少冗余代码.

       代码更加简洁美观,可读易懂.

    函数的分类:

       内建函数: 如max(),reversed()等.

       库函数: 如math.ceil()等.

函数定义,调用

       def语句定义函数.

    语法:

       def 函数名(参数列表):

           函数体(代码块)

           [return 返回值]

       函数名就是标识符,命名要求一样.

       语句块必须缩进,约定4个空格.

       python的函数没有return语句,隐式会返回一个None值.

       定义中的参数列表成为形式参数,只是一种符号表达,简称形参.

       调用:

       函数定义,只是声明了一个函数,它不会被执行,需要调用.

       调用的方式,就是函数名加上小括号,括号内写上参数.

       调用时写的参数是实际参数,是实实在在传入的值,简称实参.

    函数举例:

def add(x, y):    result = x + y    return resultout = add(4, 5)print(out)  # 9

上面只是一个函数的定义,有一个函数add,接收2个参数.

    计算的结果,通过返回值返回.

    调用通过函数名add加2个参数,返回值可使用变量接收.

    定义需要在调用前,也就是说调用时,已经被定义过了,否则抛异常NameError.

    函数是可调用的对象,callable().

函数参数

       参数调用时传入的参数要和定义的个数相匹配(可变参数例外).

    位置参数:

       def f(x,y,z) 调用使用f(1,3,5).

       按照参数定义顺序传入实参.

    关键字参数:

       def f(x,y,z)调用使用f(x=1,y=3,z=5).

       使用形参的名字来出入实参的方式,如果使用了形参名字,那么传参顺序就可以和定义顺序不同.

       传参:

           f(z=None,y=10,x=[1])

           f((1,),z=6,y=4.1)

           f(y=5,z=6,2)

           要求位置参数必须在关键字参数之前传入,位置参数是按位置对应的.

   参数规则: 参数列表参数一般顺序是,普通参数,缺省参数,可变位置参数,keyword-only参数(可带缺省值),可变关键字参数.

def fn(x,y,z=3,*arg,m=4,n,**kwargs):    print(x,y,z,m,n)    print(args)    print(kwargs)

    注:

       代码应该易读易懂,而不是为难别人.

       按照书写习惯定义函数参数.

函数参数默认值

       参数默认值:

       定义时,在形参后跟上一个值.

def add(x=4,y=5):    result = x + y    print(result) add(6,10)add(6,y=7)add(x=5)add()add(y=7)# add(x=5,6) # error.# add(y=8,4) # error.add(x=5,y=6)add(y=5,x=6)   

       注: def add(x=4, y)是错误的.

    作用:

       参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值.

       参数非常多时,并不需要用户每次都输入所有的参数,简化函数调用.

    举例:

       定义一个函数login,参数名称为host,port,username,password.

def login(host='127.0.0.1', port='8080', username='ames', password='ames'):    print('{}:{}@{}/{}'.format(host, port, username, password))login()login('127.0.0.1', 80, 'tom', 'tom')login('127.0.0.1', username='root')login('localhost', port=80, password=1234)login(port=80,password='python', host='www') # 运行结果: 127.0.0.1:8080@ames/ames127.0.0.1:80@tom/tom127.0.0.1:8080@root/ameslocalhost:80@ames/1234www:80@ames/python

可变参数

       一个形参可以匹配任意个参数.

def add(nums):    sum=0    for x in nums:       sum += x      return sumadd([1, 3, 5])9add([2, 4, 6])12 

    位置参数的可变参数: 有多个数,需要累加求和.

def add(*nums):  sum = 0  print(type(nums))  for x in nums:     sum += x     print(sum)add(3, 6, 9)<class 'tuple'>18

    在形参前使用*表示该形参是可变参数,可以接收多个实参.

    收集多个实参为一个tuple.

    关键字参数的可变参数:

def showconfig(**kwargs): for k,v in kwargs.items():   print('{} = {}'.format(k,v)) Ishowconfig(host='127.0.0.1', port=8080, username='ames', password=123456)username = ameshost = 127.0.0.1port = 8080password = 123456 # 运行结果:password = 123456port = 8080username = ameshost = 127.0.0.1

    形参前使用**符号,表示可以接收多个关键字参数.

    收集的实参名称和值组成一个字典.

    可变参数混合使用:

       def showconfig(username,password,**kwargs)

       def showconfig(username,*args,**kwargs)

       def showconfig(username,password,**kwargs,*args)

    总结:

       可变参数分为位置可变参数和关键字可变参数.

       位置可变参数在形参前使用一个星号*.

       关键字可变参数在形参前使用两个星号**.

       位置可变参数和关键字可变参数都可以收集若干个实参,位置可变参数收集形成一个tuple,关键字可变参数收集形成一个dict.

       混合使用参数时,可变参数要放在参数列表的最后,普通参数需要放到参数列表前面,位置可变参数需要放在关键字可变参数之前.

    可变参数举例:

def fn(x,y,*args,**kwargs):   print(x)   print(y)   print(args)   print(kwargs) fn(3,5,7,9,10,a=1,b='ames')35(7, 9, 10){'a': 1, 'b': 'ames'} In [10]: fn(13,15)1315(){} In [11]: fn(23,25,27)2325(27,){}  fn(33,35,a=1,b='ames')3335(){'a': 1, 'b': 'ames'} fn(7,9,y=5,x=3,a=1,b='ames')---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)13-a0c84e79923c> ----> 1 fn(7,9,y=5,x=3,a=1,b='ames') TypeError: fn() got multiple values for argument 'y'  # 错误,7和9分别赋给了x,y,又y=5 x=3,x和y的值重复. In [14]:
def fn(*args, x, y, **kwargs):     print(x)     print(y)     print(args)     print(kwargs) fn(3, 5)---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)-15----> 1 fn(3, 5) TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y' fn(13, 15, 17)---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)-16----> 1 fn(13, 15, 17) TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y' fn(23, 25, a=1, b='ames')---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)-17----> 1 fn(23, 25, a=1, b='ames') TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y' fn(37, 39, y=35, x=33, a=1, b='ames')3335(37, 39){'a': 1, 'b': 'ames'} In [19]:

keyword-only参数

       keyword-only参数 (python3加入). 

        如果在一个星号参数后,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通的参数,而是keyword-only参数.

In [19]: def fn(*args, x):    ...:     print(x)    ...:     print(args)    ...: In [20]: fn(3, 5)---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)20-----> 1 fn(3, 5) TypeError: fn() missing 1 required keyword-only argument: 'x' In [21]: fn(13, 15, 17)---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)21-----> 1 fn(13, 15, 17) TypeError: fn() missing 1 required keyword-only argument: 'x' In [22]: fn(23, 25, x = 27)27(23, 25) In [23]:

    注: 如上错误,args可看做已经截获了所有位置参数,x不使用关键字参数就不可能拿到实参.

        以上函数如果换成def fn(**kwargs,x),会直接报语法错误,可以理解为kwargs会截获所有的关键字,就算写了x=5,x也永远得不到这个值,所以语法错误.

keyword-only参数的另一种形式:

def fn(*,x,y):   print(x,y)   fn(x=5,y=6)5 6 

*号之后,普通形参都变成了必须给出的keyword-only参数.

可变参数和参数默认值

def fn(*args,x=5):   print(x)   print(args) fn()  # 等价于fn(x=5)5()fn(5)5(5,)fn(x=6)6()fn(1,2,3,x=10)10(1, 2, 3)
def fn(y,*args,x=5):   print('x={},y={}'.format(x,y))   print(args)  fn()---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last) in ()----> 1 fn() TypeError: fn() missing 1 required positional argument: 'y' fn(5)x=5,y=5()  fn(x=6)---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last) in ()----> 1 fn(x=6) TypeError: fn() missing 1 required positional argument: 'y' fn(1,2,3,x=10)x=10,y=1(2, 3) fn(y=17,2,3,x=10)  File "", line 1    fn(y=17,2,3,x=10)           ^SyntaxError: positional argument follows keyword argument  fn(17,2,3,x=10)x=10,y=17(2, 3) fn(1,2,y=3,x=10)---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last) in ()----> 1 fn(1,2,y=3,x=10) TypeError: fn() got multiple values for argument 'y' 
def fn(x=5, **kwargs):  print('x={}'.format(x))  print(kwargs) fn()x=5{} fn(5)x=5{} fn(x=6)x=6{} fn(y=3,x=10)x=10{'y': 3} fn(3,y=10)x=3{'y': 10} 

参数解构

       参数解构:

       给函数提供实参时,可在集群类型前使用*或**,把集群类型的解构解开,提取出所有元素作为函数的实参.

       非字典类型使用*解构成位置参数.

       字典类型使用**解构成关键字参数.

       提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配.

def add(x,y):    return x+y    add(*(4,5))9 add(*[4,5])Out[47]: 9 add(*{4,6})10 d = {'x':5, 'y':6} add(**d)11 add(**{'x':5, 'y':6})11def add(*iterable):    result = 0for x in iterable:     result += x    return result add(1,2,3)6 add(*[1,2,3])6 add(*range(10))45    

    练习:

1.编写一个函数,能够接受至少2个参数,返回最小值和最大值.

import random def double_values(*nums):    print(nums)    return max(nums), min(nums)print(*double_values(*[random.randint(10, 20) for _ in range(10)]))  # 两次解构# 运行结果:(18, 16, 16, 12, 13, 13, 14, 20, 18, 16)20 12
  1. 编写一个函数,接受一个参数n,n为正整数,左右两种打印方式.要求数字必须对齐.

def show(n):    tail = ' '.join([str(i) for i in range(n, 0, -1)])    width = len(tail)    for i in range(1, n):        print("{:>{}}".format(" ".join([str(j) for j in range(i, 0, -1)]),width))    print(tail)show(12)
def showtail(n):    tail = ' '.join([str(i) for i in range(n, 0, -1)])    print(tail)    for i in range(len(tail)):        if tail[i] == ' ':            print(' '*i, tail[i+1:])showtail(12)

插入排序

函数返回值,作用域

函数的返回值

       举例:

def showplus(x):    print(x)    return x+1    print(x+1)  # 该行不会执行.print(showplus(5)) # 运行结果:56

    多条return语句:  

def guess(x):    if x > 3:        return '>3'    else:        return '<=3'print(guess(10))-------------------------------------------def showplus(x):    print(x)    return x+1    return x+2  # 该行不会执行.print(showplus(5)) # 运行结果:56
def fn(x):    for i in range(x):        if i > 3:            return i    else:        print('{} is not greater than 3'.format(x))print(fn(5)) # 运行结果: 4print(fn(3)) # 运行结果:3 is not greater than 3None   # 所有函数都有函数值,如果没有return语句,隐式调用return None.

       总结:

       python函数使用return语句返回'返回值'.

       所有函数都有函数值,如果没有return语句,隐式调用return None.

       return语句并不一定是函数的语句块的最后一条语句.

       一个函数可以存在多个return语句,但是只有一条可以被执行.如果没有一条return语句被执行到,隐式调用return None.

       如果有必要,可以显示调用return None,可以简写为return.

       如果函数执行了return语句,函数就会返回,当前被执行的return语句之后的其他语句就不会被执行.

       作用: 结束函数调用和返回值.

    返回多个值:

def showlist():    return [1, 3, 5]print(showlist())  # 运行结果: [1, 3, 5] def showlist():    return 1, 3, 5print(showlist())  # 运行结果: (1, 3, 5)

    注:

       函数不能同时返回多个值.

       return [1,3,5] 即指明返回一个列表,是一个list对象.

       return 1,3,5 看似返回多个值,隐式的被python封装成了一个元组.

def showlist():    return 1,3,5x, y, z = showlist()print(x, y, z)  # 运行结果: 1 3 5

函数嵌套

       函数嵌套:

       在一个函数中定义了另一个函数.

 def outer():   def inner():       print('inner')   print('outer')   inner() outer()outerinner inner()---------------------------------------------------------------------------NameError                                 Traceback (most recent call last)6-----> 1 inner() NameError: name 'inner' is not defined 

    注:

       函数有可见范围,这就是作用域的概念.

       内部函数不能被外部直接使用,会抛异常NameError,如上代码.

def outer():     def inner():         print('inner')         return 'xx'  # return None     print('outer')     inner()     return inner(),'p'print(outer()) # 执行结果outerinnerinner('xx', 'p')  # 两次return的结果组成了一个元组.

作用域

       作用域: 一个标识符的可见范围即标识符的作用域.一般常说的是变量的作用域.

x = 5 def foo():   print(x) foo()5x = 5def foo():   x += 1   # x = x + 1print(x)foo()# 运行报错:UnboundLocalError: local variable 'x' referenced before assignment

    全局作用域:

       在整个程序运行环境中都可见.

    局部作用域:

       在函数,类等内部可见.

       局部变量使用范围不能超过其所在的局部作用域.

In [31]: def fn1():    ...:     x = 1  # 局部作用域,在fn1内.    ...: def fn2():    ...:     print(x)    ...: In [32]: print(x)---------------------------------------------------------------------------NameError                                 Traceback (most recent call last)32-----> 1 print(x) NameError: name 'x' is not defined In [33]:

    嵌套结构:

def outer1():    o = 65    def inner():        print('inner {}'.format(o))        print(chr(o))    print('outer {}'.format(o))    inner() outer1() # 运行结果:outer 65inner 65A def outer2():    o = 65    def inner():        o = 97        print('inner {}'.format(o))        print(chr(o))    print('outer {}'.format(o))    inner() outer2() # 运行结果:outer 65inner 97a 

    从嵌套结构例子看出:

       外层变量作用域在内层作用域可见.

       内层作用域inner中,如果定义了o=97,相当于当前作用域中重新定义了一个新的变量o,但是这个o并没有覆盖外层作用域outer中的o.

x = 5 def foo():      y = x + 1       x += 1     print(x)   foo()---------------------------------------------------------------------------UnboundLocalError                         Traceback (most recent call last)input----> 1 foo() input      1 def foo():---> 2     y = x + 1      3     x += 1      4     print(x)      5 UnboundLocalError: local variable 'x' referenced before assignment def foo():     y = x + 1     # x += 1     print(x)   foo()5x = 5 def foo():   x += 1   return x foo()---------------------------------------------------------------------------UnboundLocalError                         Traceback (most recent call last)input----> 1 foo() input      1 def foo():----> 2     x += 1      3     return x UnboundLocalError: local variable 'x' referenced before assignment In [17]: 注意:x += 1 其实是 x = x + 1相当于在foo内部定义一个局部变量x,那么foo内部所有x都是这个局部变量x了.但是这个x还没完成复制,就被右边拿来做加1操作了,故报错.

    全局变量: global

x = 5  def foo():    global x    x += 1    return xfoo()6 

    使用global关键字的变量,将foo内的x声明为使用外部的全局作用域中定义的x.

    全局作用域中必须有x的定义.

    如果全局作用域中没有x定义:

def foo():   global x    x = 10    x += 1    print(x) foo()11 print(x)11 

    使用global关键字的变量,将foo内的x声明为使用外部的全局作用域中定义的x.

    但是,x = 10赋值即定义,x在内部作用域为一个外部作用域的变量赋值,所以x += 1不会报错.注意这里的x的作用域还是全局的.

    global总结:

      x+=1这种是特殊形式产生的错误的原因,先引用后赋值,而python动态语言是赋值才算定义,才能被引用.解决办法是在这条语句前增加x=0之类的赋值语句,或者使用global告诉内部作用域,去全局作用域查找变量定义.

       内部作用域使用x=5之类的赋值语句会重新定义局部作用域使用的变量x,但是一旦这个作用域中使用的global声明为全局的,那么x=5相当于在为全局作用域的变量x赋值.

    global使用原则:

       外部作用域变量在内部作用域可见,但也不要在这个内部的局部作用域中直接使用,因为函数的目的就是为了封装,尽量与外界隔离.

       如果函数需要使用外部全局变量,使用函数的形参传参解决.

函数值传递和引用传递(包括形式参数和实际参数的区别)

通常情况下,定义函数时都会选择有参数的函数形式,函数参数的作用是传递数据给函数,令其对接收的数据做具体的操作处理。在使用函数时,经常会用到形式参数(简称“形参”)和实际参数(简称“实参”),二者都叫参数,之间的区别是:

· 形式参数:在定义函数时,函数名后面括号中的参数就是形式参数,例如:

#定义函数时,这里的函数参数 obj 就是形式参数

def demo(obj)

    print(obj)

· 

· 实际参数:在调用函数时,函数名后面括号中的参数称为实际参数,也就是函数的调用者给函数的参数。例如:

a = "C语言中文网"

#调用已经定义好的 demo 函数,此时传入的函数参数 a 就是实际参数

demo(a)

· 

实参和形参的区别,就如同剧本选主角,剧本中的角色相当于形参,而演角色的演员就相当于实参。

明白了什么是形参和实参后,再来想一个问题,那就是实参是如何传递给形参的呢?Python 中,根据实际参数的类型不同,函数参数的传递方式可分为 2 种,分别为值传递和引用(地址)传递:

1. 值传递:适用于实参类型为不可变类型(字符串、数字、元组);

2. 引用(地址)传递:适用于实参类型为可变类型(列表,字典);

值传递和引用传递的区别是,函数参数进行值传递后,若形参的值发生改变,不会影响实参的值;而函数参数继续引用传递后,改变形参的值,实参的值也会一同改变。例如,定义一个名为 demo 的函数,分别为传入一个字符串类型的变量(代表值传递)和列表类型的变量(代表引用传递):

def demo(obj) :    obj += obj    print("形参值为:",obj)print("-------值传递-----")a = "C语言中文网"print("a的值为:",a)demo(a)print("实参值为:",a)print("-----引用传递-----")a = [1,2,3]print("a的值为:",a)demo(a)print("实参值为:",a)

运行结果为:

-------值传递-----a的值为:C语言中文网形参值为: C语言中文网C语言中文网实参值为: C语言中文网-----引用传递-----a的值为:[1, 2, 3]形参值为: [1, 2, 3, 1, 2, 3]实参值为: [1, 2, 3, 1, 2, 3]

分析运行结果不难看出,在执行值传递时,改变形式参数的值,实际参数并不会发生改变;而在进行引用传递时,改变形式参数的值,实际参数也会发生同样的改变。

Python匿名函数详解

在编程语言中,函数的应用:1. 代码块重复,这时候必须考虑用到函数,降低程序的冗余度2. 代码块复杂,这时候可以考虑用到函数,降低程序的可读性在Python,有两种函数,一种是def定义,一种是lambda函数#假如要求两个数之和,用普通函数或匿名函数如下:1. def func(x,y):return x+y2. lambda x,y: x+y在编程语言中,C/C++/Java属于过程式编程,而匿名函数(lambda)一般应用于函数式编程中,举个简单例子也许比较好理解,对于一个列表,要求大于3的元素.过程式编程实现: 也就是常规的方法>>> L1 = [1,2,3,4,5]>>> L2 = []>>> for i in L1:if i>3:L2.append(i)>>> L2[4, 5]函数式编程实现: 运用filter,给其一个判断条件即可>>> def func(x): return x>3 #在函数中>>> filter(func,[1,2,3,4,5])[4, 5]如果运用匿名函数,则更加精简,一行就可以了:>>> filter(lambda x:x>3,[1,2,3,4,5])[4, 5]总结: 从中可以看出,lambda一般应用于函数式编程,代码简洁,常和reduce,filter等函数结合使用。格式如下:8f274910340d94e184f6e05029144d06.png解构上面的例子x 为lambda函数的一个参数:分割符x>3 则是返回值,在lambda函数中不能有return,其实:后面就是返回值为什么要用匿名函数?1. 程序一次行使用,所以不需要定义函数名,节省内存中变量定义空间2. 如果想让程序更加简洁时。匿名函数几个规则:1. 一般也就一行表达式,必须有返回值2. 不能有return3. 可以没有参数,可以有一个或多个参数>>> def func(x): x+y>>> func>>> lambda x: x+y at 0x0000000002F48D68>无参匿名函数:------>>> t = lambda : True #分号前无任何参数>>> t()True等价于下面的def定义的函数>>> def func(): return True>>> func()True------>>> s = "this is\na\ttest" #建此字符串按照正常情形输出>>> s'this is\na\ttest'>>> print s.split() #split函数默认分割:空格,换行符,TAB['this', 'is', 'a', 'test']>>> ' '.join(s.split()) #用join函数转一个列表为字符串'this is a test'等价于>>> (lambda s:' '.join(s.split()))("this is\na\ttest")带参数匿名函数>>> lambda x: x**3 #一个参数>>> lambda x,y,z:x+y+z #多个参数>>> lambda x,y=3: x*y #允许参数存在默认值匿名函数调用#直接赋值给一个变量,然后再像一般函数调用------>>> c = lambda x,y,z: x*y*z>>> c(2,3,4)24------>>> c = lambda x,y=2: x+y #使用了默认值>>> c(10) #不输的话,使用默认值212------>>> a = lambda *z:z #*z返回的是一个元祖>>> a('Testing1','Testing2')('Testing1', 'Testing2')------>>> c = lambda **Arg: Arg #arg返回的是一个字典>>> c(){}#直接后面传递实参------>>> (lambda x,y: x if x> y else y)(101,102)102------>>> (lambda x:x**2)(3)9#lambda返回的值,结合map,filter,reduce使用>>> filter(lambda x:x%3==0,[1,2,3,4,5,6])[3, 6]等价于下面的列表推导式>>> l = [x for x in [1,2,3,4,5,6] if x%3==0]>>> l[3, 6]嵌套使用#lambda嵌套到普通函数中,lambda函数本身做为return的值------>>> def increment(n):... return lambda x: x+n...>>> f=increment(4)>>> f(2)6------>>> def say():... title = 'Sir,'... action= lambda x: title + x... return action...>>> act = say()>>> act('Smith!')'Sir,Smith!'大量例子:例01: 字符串联合,有默认值,也可以x=(lambda...)这种格式>>> x = (lambda x="Boo",y="Too",z="Zoo": x+y+z)>>> x("Foo")'FooTooZoo'例02: 和列表联合使用>>> L = [lambda x:x**2,\lambda x:x**3,\lambda x:x**4]>>> for f in L:... print f(2)...4816也可以如下面这样调用>>> print L[0](3)9例03: 和字典结合使用>>> key = 'B'>>> dic = { 'A': lambda: 2*2,\... 'B': lambda: 2*4,\... 'C': lambda: 2*8}>>> dic[key]()8例04: 求最小值>>> lower = lambda x,y: x if x>>> lower('aa','ab')'aa'例05: 和map及list联合使用>>> import sys>>> showall = lambda x:list(map(sys.stdout.write,x))>>> showall(['Jerry\n','Sherry\n','Alice\n'])JerrySherryAlice>>> showall(['Jerry','Sherry','Alice'])JerrySherryAlice等价于下面>>> showall = lambda x: [sys.stdout.write(line) for line in x]>>> showall(('I\t','Love\t','You!'))I Love You![None, None, None]例06: 在Tkinter中定义内联的callback函数import sysfrom Tkinter import Button,mainloopx = Button(text='Press me',command=(lambda:sys.stdout.write('Hello,World\n')))x.pack()x.mainloop()2b23d21bda29c027c9c4270e4a7aeb03.png>>>Hello,World!Hello,World!例07: lambda和map联合使用,>>> out = lambda *x: sys.stdout.write(' '.join(map(str,x)))>>> out('This','is','a','book!\n')This is a book!例08: 判断字符串是否以某个字母开头>>> print (lambda x: x.startswith('B'))('Bob')True----->>> Names = ['Anne', 'Amy', 'Bob', 'David', 'Carrie', 'Barbara', 'Zach']>>> B_Name= filter(lambda x: x.startswith('B'),Names)>>> B_Name['Bob', 'Barbara']例09: lambda和map联合使用:>>> squares = map(lambda x:x**2,range(5))>>> squares[0, 1, 4, 9, 16]例10. lambda和map,filter联合使用:>>> squares = map(lambda x:x**2,range(10))>>> filters = filter(lambda x:x>5 and x<50,squares)>>> filters[9, 16, 25, 36, 49]例11. lambda和sorted联合使用#按death名单里面,按年龄来排序#匿名函数的值返回给key,进来排序>>> death = [ ('James',32),('Alies',20),('Wendy',25)]>>> sorted(death,key=lambda age:age[1]) #按照第二个元素,索引为1排序[('Alies', 20), ('Wendy', 25), ('James', 32)]例12. lambda和reduce联合使用>>> L = [1,2,3,4]>>> sum = reduce(lambda x,y:x+y,L)>>> sum10例13. 求2-50之间的素数#素数:只能被1或被自己整除的数>>> nums = range(2,50)>>> for i in nums:nums = filter(lambda x:x==i or x % i,nums)>>> nums[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]例14. 求两个列表元素的和>>> a = [1,2,3,4]>>> b = [5,6,7,8]>>> map(lambda x,y:x+y, a,b)[6, 8, 10, 12]例15. 求字符串每个单词的长度>>> sentence = "Welcome To Beijing!">>> words = sentence.split()>>> lengths = map(lambda x:len(x),words)>>> lengths[7, 2, 8]写成一行:>>> print map(lambda x:len(x),'Welcome To Beijing!'.split())

一. 递归函数

递归函数就是函数在内部调用自身。

必须有一个明确的递归结束条件,称为递归出口。

注意: 切勿忘记递归出口,避免函数无限调用。

函数调用自身的实现:

其实函数每次被调用时都会创建一个新命名空间,也就是当函数调用“自身”时,实际上运行的是两个不同的函数(也可以说一个函数具有两个不同的命名空间)。

【例】定义阶乘函数

递归实现:

>>> def fact(n):

... if n == 1:

... return 1

... else:

... return n * fact( n-1 )

...

>>>

>>> fact(1)

1

>>> fact(2)

2

>>> fact(4)

24

>>> fact(5)

120

fact(5) 计算过程:

factorial(5) # 第 1 次调用使用 5

5 * factorial(4) # 第 2 次调用使用 4

5 * (4 * factorial(3)) # 第 3 次调用使用 3

5 * (4 * (3 * factorial(2))) # 第 4 次调用使用 2

5 * (4 * (3 * (2 * factorial(1)))) # 第 5 次调用使用 1

5 * (4 * (3 * (2 * 1))) # 从第 5 次调用返回

5 * (4 * (3 * 2)) # 从第 4 次调用返回

5 * (4 * 6) # 从第 3次调用返回

5 * 24 # 从第 2 次调用返回

120 # 从第 1 次调用返回

迭代实现:

>>> def fact(n):

... result = 1

... for i in range(2,n+1):

... result *= i

... return result

...

>>>

>>> fact(1)

1

>>> fact(2)

2

>>> fact(5)

120

递归的优缺点:

优点:

  • 递归使代码看起来更加整洁、优雅

  • 可以用递归将复杂任务分解成更简单的子问题

  • 使用递归比使用一些嵌套迭代更容易

缺点:

  • 递归的逻辑很难调试、跟进

  • 递归调用的代价高昂(效率低),因为占用了大量的内存和时间。

二.  尾递归

使用递归函数需要注意防止栈溢出。在计算机中函数调用是通过栈这种数据结构实现的。每当进入一个函数调用,栈就会加一层栈帧;每当函数返回就会减一层栈帧。由于栈的大小不是无限的,因此递归调用次数过多会导致栈溢出。

解决递归调用栈溢出的方法是通过尾递归优化。

尾递归是指函数返回时调用函数本身,并且 return 语句不能包含表达式。这样,编译器和解释器就可以对尾递归进行优化。使递归本身无论调用多少次都只占用一个栈帧,从而避免栈溢出的情况。

>>> def fact(n):

... return fact_iter(n,1)

...

>>>

>>> def fact_iter(num , result):

... if num == 1:

... return result

... return fact_iter(num-1 , num * result)

...

>>>

>>>

>>> fact(1)

1

>>> fact(2)

2

>>> fact(5)

120

python 递归、递推算法实例(小明爬楼梯)

递推算法递归算法例题:假设-段楼梯共15个台阶,小明-步最多能上3个台阶。编写程序计算小明上:这段楼梯一共有多少种方法。要求给出递推法和递归法两种代码。

递归法

#递归法

defdemo(n):

    d={1:1,2:2,3:4}

    if n in d.keys():

        return d[n]

    else:

        return demo(n-1)+demo(n-2)+demo(n-3)

print(demo(15))

递推法

#递推法

defdemo(n): # n最少为3,否则输出4错误

    a=1

    b=2

    c=4

    for i inrange(n-3):

        c,b,a=a+b+c,c,b

    return c

print(demo(4))

”分治法“

基本思想:

将一个问题分解为多个规模比较小的子问题,这些子问题互相独立并与原问题解决方案相同,递归求解这些子问题,然后将这些子 问题的解合并得到原问题的解。

分治法求解的基本步骤:

1、将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;

2、明确最小子问题,递归最终的结束条件;

3、划分子问题,调用递归方法;

4、合并回溯后的结果

分治经典问题

(1)二分查找

(2)归并排序

(3)快速排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值