当前位置:   article > 正文

Python函数_print(f1(), f2(), f3()) 修复以上错误

print(f1(), f2(), f3()) 修复以上错误

1.函数的定义

使用def关键字和缩进语法来定义一个函数:

  1. def funcname(args):
  2. <code statement>

2.函数的参数

 

参数类型描述
位置参数
(必须参数)
如果不输入参数名称,则必须按照指定顺序输入参数;若输出参数名称,则可以不按照指定顺序输入参数
默认参数在设置参数时已设定默认值,故输入参数时可忽略,但若要重新配置该参数值,则按照位置参数规则执行
可变参数使用*,则连续输入多个的个体参数,会被自动封装为tuple,但输入类容器结构数据时,在前类容器前加*进行拆包
关键字参数使用**,可以输入任意的key=value键值对形式的参数,会自动封装为dict,但若输入dict为参数,则需要在dict加**进行拆包

 

  1. def func(name,age,weight=65):
  2. print('%s is %s years old and his weight is %s kiligrams'%(name,age,weight))
  1. func('grant',18)
  2. func('lisa',20,50)
  3. func(age=30,name='peter')
  4. func(weight=100,age=60,name='wood')
  5. #以上都能正常输出
  1. def func2(*L):#定义一个可变长的函数
  2. for i in L:
  3. print(i)
  1. func2(1,2,3)
  2. List=[4,5,6]
  3. func2(*List)#在列表前加*拆包
  4. #以上都能正常输出
  1. def func3(**kw):#定义一个关键字式函数
  2. print(kw)
  1. func3(name='grant',age=18)
  2. func3(**{'name':'grant','age':18})#在字典前加**拆包
  3. #以上都能正常输出

3. 作用域

Python中,变量的作用域一共分四种:

 

  • 局部-Local
  • 闭包函数的外层函数-Enclosing
  • 全局-Global
  • 内建-Built-in

Python解释器按照L-E-G-B的原则进行变量查找

 

变量类型描述
不可变:int,str,tuple内层函数仅对变量有查看权,无修改权,除非使用global,nonlocal 进行作用域声明
可变:list,set,dict内层函数可以对变量进行查看和修改

4.匿名函数

使用lambda关键字来创建匿名函数

匿名函数只能是一行的表达式,所以一般只能封装比较简单的逻辑,但好处是因为没有函数名不用担心名称冲突,而且执行完毕既释放内存空间.

lambda x:x**2

5.递归函数

一个函数在内部调用其自身被称为递归函数,所有的递归函数都可以改写为循环.

由于函数调用都是通过栈的方式实现的,而栈的大小是有限的,所有当递归次数过多时,会导致栈溢出,从而抛出错误

RuntimeError: maximum recursion depth exceeded in comparison

使用递归函数的原则:

 

  • 每一次的递归都能使问题规模减小
  • 必须设置递归的退出条件
  1. def recursion(n):
  2. n=n-2
  3. print(n)
  4. if n<1:
  5. print('end')
  6. else:
  7. return recursion(n)
  8. recursion(10)

输出结果:

  1. 8
  2. 6
  3. 4
  4. 2
  5. 0
  6. end

6.yield和return

 

  • return

函数使用return作为结果输出,若不指定输出结果,则默认返回None,同时return None也可以简写为return

函数一旦执行return语句,则整个函数执行结束

在不指定格式的前提下,若用return同时返回多个结果,则会默认把结果封装成一个tuple

  1. def func(x,y,z):
  2. return x,y,z
  3. print(func(1,2,3))
  4. >>>(1,2,3)

 

  • yield     生成器

函数中一旦出现yield,则该函数不在是函数,而是生成器(generator).

  1. def func(num):
  2. for i in range(num):
  3. yield i
  4. t=func(5)#此时t为生成器对象
  5. print(type(t))
  6. #输出结果:
  7. >>><class 'generator'>
  8. >>>

生成器是惰性的,可以用list/tuple/set直接接收生成器函数的全部输出结果,也可以用for循环对生成器函数进行遍历.

  1. t1=func(5)
  2. print(list(t1))
  3. t2=func(4)
  4. print(set(t2))
  5. t3=func(3)
  6. print(tuple(t3))
  7. t4=func(2)
  8. for i in t4:
  9. print (i,end='//')
  10. ------------------------------------
  11. #输出结果:
  12. ------------------------------------
  13. [0, 1, 2, 3, 4]
  14. {0, 1, 2, 3}
  15. (0, 1, 2)
  16. 0//1//

 

生成器需要被一个变量对象接收,如果每次重新去调用生成器函数,每次都会是生成器函数初始化的结果.

  1. def func(num):
  2. for i in range(num):
  3. yield i
  4. print(next(func(3)))
  5. print(next(func(3)))
  6. print(next(func(3)))
  7. --------------------------------------
  8. #输出结果:
  9. >>>0
  10. >>>0
  11. >>>0

生成器好比单行道,只能向前不能后退,直到抛出StopIteration的异常.

  1. t1=func(3)
  2. print(next(t1),end='/')
  3. print(next(t1),end='/')
  4. print(next(t1))
  5. print(next(t1))
  6. ---------------------------------------
  7. #输出结果:
  8. 0/1/2
  9. Traceback (most recent call last):
  10. File "D:/Pycharm/TEST/0410.py", line 14, in <module>
  11. print(next(t1))
  12. StopIteration

yield 实现协程

  1. def consumer():
  2. r1 = '111'
  3. r2 = '222'
  4. while True:
  5. n1 = yield r1
  6. print('n1:',n1)
  7. if n1:
  8. print('None')
  9. print('[CONSUMER] Consuming %s...' % n1)
  10. n2 = yield r2
  11. print('n2:',n2)
  12. r = '200 OK'
  13. def produce(c):
  14. k=c.send(None)
  15. print('k:',k)
  16. n = 0
  17. while n < 5:
  18. n = n + 1
  19. print('[PRODUCER] Producing %s...' % n)
  20. t = c.send(n)
  21. print('t:',t)
  22. print('[PRODUCER] Consumer return: %s' % t)
  23. c.close()
  24. c = consumer()
  25. produce(c)
  26. -------------------------------------------------------------------------------
  27. #执行结果:
  28. k: 111
  29. [PRODUCER] Producing 1...
  30. n1: 1
  31. None
  32. [CONSUMER] Consuming 1...
  33. t: 222
  34. [PRODUCER] Consumer return: 222
  35. [PRODUCER] Producing 2...
  36. n2: 2
  37. t: 111
  38. [PRODUCER] Consumer return: 111
  39. [PRODUCER] Producing 3...
  40. n1: 3
  41. None
  42. [CONSUMER] Consuming 3...
  43. t: 222
  44. [PRODUCER] Consumer return: 222
  45. [PRODUCER] Producing 4...
  46. n2: 4
  47. t: 111
  48. [PRODUCER] Consumer return: 111
  49. [PRODUCER] Producing 5...
  50. n1: 5
  51. None
  52. [CONSUMER] Consuming 5...
  53. t: 222
  54. [PRODUCER] Consumer return: 222

以上为典型的生产者消费者模型

在该模型中, yield的原则为左接收(先),右发生(后),而send是先发送,后接收

第一步,使用send(None)命令激活(只能使用该固定格式),和该命令对应的yield执行右发生

当第二次及以后的send时,yield执行左接收后,执行其他代码,直到遇到下一个yield执行右发送,从而完成一次循环

当yield完成一次循环后,send接收yield的发送值并执行其他代码,直到下一次send

最后,使用close()命令,关闭整个流程

 

yield和return的位置关系

若yield之后还存在return关键词,则return之后携带的内容只会出现在生成器函数抛出异常时的StopIteration中:

  1. def func():
  2. yield 1
  3. yield 2
  4. return 'end'
  5. t=func()
  6. print(next(t))
  7. print(next(t))
  8. print(next(t))
  9. ---------------------------------------
  10. #输出结果:
  11. 1
  12. 2
  13. Traceback (most recent call last):
  14. File "D:/Pycharm/TEST/0410.py", line 11, in <module>
  15. print(next(t))
  16. StopIteration: end

7.闭包函数

闭包函数本质上就是函数内部再嵌套函数,并且内层函数需要调用外出函数的变量,最后内层函数作为结果输出.

闭包函数输出的是一个函数,所以要拿到最终的结果,需要对输出的函数再次进行调用.

闭包函数的使用最需要注意以下两点:

 

  • 内外层函数变量的作用域问题,切记内层函数对外出函数的变量只有查看权,无修改权
  • 由于闭包函数输出的是一个还未被执行的函数,只在在该函数最终执行时才会去查找调用相关变量,所以这个过程中的变量需要时稳定的,若为不稳定的变量则会影响输出结果.
  1. def out():
  2. count=0#此为不可变类型,故内层函数要修改的话需要声明,用[0]代替则不需要声明
  3. def inner():
  4. nonlocal count
  5. count+=1
  6. return count
  7. return inner
  8. t=out()
  9. print(t(),t(),t())
  10. ---------------------------------------
  11. #输出结果:
  12. >>>1 2 3
  1. def out(n):
  2. f=[]
  3. for i in range(1,n):
  4. def inner():
  5. return i*i
  6. f.append(inner)
  7. return f
  8. f1,f2,f3=out(4)
  9. print(f1(),f2(),f3())
  10. ---------------------------------------
  11. #输出结果:
  12. >>>9 9 9 #由于闭包返回的函数在没有在调用时并没有执行,所以在最后执行再去查找变量时,变量i已经是3,所以输出结果都是9,并不是1,4,9!
  1. def out(n):
  2. f=[]
  3. for i in range(1,n):
  4. def inner(x=i):
  5. return x*x
  6. f.append(inner)
  7. return f
  8. f1,f2,f3=out(4)
  9. print(f1(),f2(),f3())
  10. ---------------------------------------
  11. #输出结果:
  12. >>>1 4 9 #由于在内层函数每次都用参数x绑定了变量i,所以最终输出结果为1,4,9

8.装饰器

装饰器类似于闭包,本质上都是用函数是'包装'函数.

  1. def dec(func):
  2. def wrapper(*args,**kwargs):
  3. print('This is a decorator')
  4. func(*args,**kwargs)
  5. return wrapper
  6. def func1():
  7. print('run func1')
  8. func1()
  9. print('=======================================')
  10. #用函数dec修饰func1后
  11. func1=dec(func1)
  12. func1()
  13. ---------------------------------------
  14. #输出结果:
  15. run func1
  16. =======================================
  17. This is a decorator
  18. run func1

为了简洁性和代码的复用性,Python可以采用@语法糖的形式,@dec的语法是等同于func2=dec(func2)

  1. @dec
  2. def func2():
  3. print('func2 is running')
  4. func2()
  5. -----------------------------------------
  6. #输出结果:
  7. This is a decorator
  8. func2 is running

从形式上来说,确实达到了在不改动原代码的前提下,为原函数增加的新的功能,但其实原函数的元信息已经改变

  1. def func2():
  2. print('func2 is running')
  3. print(func2.__name__)
  4. @dec
  5. def func2():
  6. print('func2 is running')
  7. print(func2.__name__)
  8. ---------------------------------------
  9. #输出结果:
  10. func2
  11. wrapper

但Python 用functools模块中的wraps方法解决了这个问题,这才是真正的装饰器

  1. import functools
  2. def dec(func):
  3. @functools.wraps(func)
  4. def wrapper(*args,**kwargs):
  5. print('This is a decorator')
  6. func(*args,**kwargs)
  7. return wrapper
  8. def func2():
  9. print('func2 is running')
  10. print(func2.__name__)
  11. @dec
  12. def func2():
  13. print('func2 is running')
  14. print(func2.__name__)
  15. ---------------------------------------
  16. #输出结果:
  17. func2
  18. func2

以上是不带参数的装饰器,若需要增加参数的话,就得再增加一层包含的层级

  1. import functools
  2. def dec(text):
  3. print(text)
  4. def wrap(func):
  5. @functools.wraps(func)
  6. def wrapper(*args,**kwargs):
  7. print('decorator with parameter')
  8. return func(*args,**kwargs)
  9. return wrapper
  10. return wrap
  11. @dec('parameter')
  12. def func():
  13. print('func is running')
  14. func()
  15. ---------------------------------------
  16. #输出结果:
  17. parameter
  18. decorator with parameter
  19. func is running

装饰器也是可以多层嵌套的:等同于a装饰(b装饰(c装饰func)),既 func=a(b(c(func)))

  1. @a
  2. @b
  3. @c
  4. def func():
  5. pass

在执行函数前打印start,执行函数后打印end的装饰器例子:

  1. import functools
  2. def dec(func):
  3. @functools.wraps(func)
  4. def wrapper(*args,**kwargs):
  5. print('start')
  6. func(*args,**kwargs)
  7. print('end')
  8. return wrapper
  9. @dec
  10. def func():
  11. print('func is running!')
  12. func()
  13. ---------------------------------------
  14. #输出结果:
  15. start
  16. func is running!
  17. end

 

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号