赞
踩
1.函数的定义
使用def关键字和缩进语法来定义一个函数:
- def funcname(args):
- <code statement>
2.函数的参数
参数类型 | 描述 |
位置参数 (必须参数) | 如果不输入参数名称,则必须按照指定顺序输入参数;若输出参数名称,则可以不按照指定顺序输入参数 |
默认参数 | 在设置参数时已设定默认值,故输入参数时可忽略,但若要重新配置该参数值,则按照位置参数规则执行 |
可变参数 | 使用*,则连续输入多个的个体参数,会被自动封装为tuple,但输入类容器结构数据时,在前类容器前加*进行拆包 |
关键字参数 | 使用**,可以输入任意的key=value键值对形式的参数,会自动封装为dict,但若输入dict为参数,则需要在dict加**进行拆包 |
- def func(name,age,weight=65):
- print('%s is %s years old and his weight is %s kiligrams'%(name,age,weight))
- func('grant',18)
- func('lisa',20,50)
- func(age=30,name='peter')
- func(weight=100,age=60,name='wood')
- #以上都能正常输出
- def func2(*L):#定义一个可变长的函数
- for i in L:
- print(i)
- func2(1,2,3)
- List=[4,5,6]
- func2(*List)#在列表前加*拆包
- #以上都能正常输出
- def func3(**kw):#定义一个关键字式函数
- print(kw)
- func3(name='grant',age=18)
- func3(**{'name':'grant','age':18})#在字典前加**拆包
- #以上都能正常输出
3. 作用域
Python中,变量的作用域一共分四种:
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
使用递归函数的原则:
- def recursion(n):
- n=n-2
- print(n)
- if n<1:
- print('end')
- else:
- return recursion(n)
-
- recursion(10)
输出结果:
- 8
- 6
- 4
- 2
- 0
- end
6.yield和return
函数使用return作为结果输出,若不指定输出结果,则默认返回None,同时return None也可以简写为return
函数一旦执行return语句,则整个函数执行结束
在不指定格式的前提下,若用return同时返回多个结果,则会默认把结果封装成一个tuple
- def func(x,y,z):
- return x,y,z
- print(func(1,2,3))
- >>>(1,2,3)
-
函数中一旦出现yield,则该函数不在是函数,而是生成器(generator).
- def func(num):
- for i in range(num):
- yield i
- t=func(5)#此时t为生成器对象
- print(type(t))
- #输出结果:
- >>><class 'generator'>
- >>>
生成器是惰性的,可以用list/tuple/set直接接收生成器函数的全部输出结果,也可以用for循环对生成器函数进行遍历.
- t1=func(5)
- print(list(t1))
- t2=func(4)
- print(set(t2))
- t3=func(3)
- print(tuple(t3))
- t4=func(2)
- for i in t4:
- print (i,end='//')
- ------------------------------------
- #输出结果:
- ------------------------------------
- [0, 1, 2, 3, 4]
- {0, 1, 2, 3}
- (0, 1, 2)
- 0//1//
生成器需要被一个变量对象接收,如果每次重新去调用生成器函数,每次都会是生成器函数初始化的结果.
- def func(num):
- for i in range(num):
- yield i
-
- print(next(func(3)))
- print(next(func(3)))
- print(next(func(3)))
- --------------------------------------
- #输出结果:
- >>>0
- >>>0
- >>>0
生成器好比单行道,只能向前不能后退,直到抛出StopIteration的异常.
- t1=func(3)
- print(next(t1),end='/')
- print(next(t1),end='/')
- print(next(t1))
- print(next(t1))
- ---------------------------------------
- #输出结果:
- 0/1/2
- Traceback (most recent call last):
- File "D:/Pycharm/TEST/0410.py", line 14, in <module>
- print(next(t1))
- StopIteration
yield 实现协程
- def consumer():
- r1 = '111'
- r2 = '222'
- while True:
- n1 = yield r1
- print('n1:',n1)
- if n1:
- print('None')
- print('[CONSUMER] Consuming %s...' % n1)
- n2 = yield r2
- print('n2:',n2)
- r = '200 OK'
-
- def produce(c):
- k=c.send(None)
- print('k:',k)
- n = 0
- while n < 5:
- n = n + 1
- print('[PRODUCER] Producing %s...' % n)
- t = c.send(n)
- print('t:',t)
- print('[PRODUCER] Consumer return: %s' % t)
- c.close()
-
- c = consumer()
- produce(c)
- -------------------------------------------------------------------------------
- #执行结果:
- k: 111
- [PRODUCER] Producing 1...
- n1: 1
- None
- [CONSUMER] Consuming 1...
- t: 222
- [PRODUCER] Consumer return: 222
- [PRODUCER] Producing 2...
- n2: 2
- t: 111
- [PRODUCER] Consumer return: 111
- [PRODUCER] Producing 3...
- n1: 3
- None
- [CONSUMER] Consuming 3...
- t: 222
- [PRODUCER] Consumer return: 222
- [PRODUCER] Producing 4...
- n2: 4
- t: 111
- [PRODUCER] Consumer return: 111
- [PRODUCER] Producing 5...
- n1: 5
- None
- [CONSUMER] Consuming 5...
- t: 222
- [PRODUCER] Consumer return: 222
以上为典型的生产者消费者模型
在该模型中, yield的原则为左接收(先),右发生(后),而send是先发送,后接收
第一步,使用send(None)命令激活(只能使用该固定格式),和该命令对应的yield执行右发生
当第二次及以后的send时,yield执行左接收后,执行其他代码,直到遇到下一个yield执行右发送,从而完成一次循环
当yield完成一次循环后,send接收yield的发送值并执行其他代码,直到下一次send
最后,使用close()命令,关闭整个流程
yield和return的位置关系
若yield之后还存在return关键词,则return之后携带的内容只会出现在生成器函数抛出异常时的StopIteration中:
- def func():
- yield 1
- yield 2
- return 'end'
-
- t=func()
- print(next(t))
- print(next(t))
- print(next(t))
- ---------------------------------------
- #输出结果:
- 1
- 2
- Traceback (most recent call last):
- File "D:/Pycharm/TEST/0410.py", line 11, in <module>
- print(next(t))
- StopIteration: end
7.闭包函数
闭包函数本质上就是函数内部再嵌套函数,并且内层函数需要调用外出函数的变量,最后内层函数作为结果输出.
闭包函数输出的是一个函数,所以要拿到最终的结果,需要对输出的函数再次进行调用.
闭包函数的使用最需要注意以下两点:
- def out():
- count=0#此为不可变类型,故内层函数要修改的话需要声明,用[0]代替则不需要声明
- def inner():
- nonlocal count
- count+=1
- return count
- return inner
-
- t=out()
- print(t(),t(),t())
- ---------------------------------------
- #输出结果:
- >>>1 2 3
- def out(n):
- f=[]
- for i in range(1,n):
- def inner():
- return i*i
- f.append(inner)
- return f
-
- f1,f2,f3=out(4)
-
- print(f1(),f2(),f3())
- ---------------------------------------
- #输出结果:
- >>>9 9 9 #由于闭包返回的函数在没有在调用时并没有执行,所以在最后执行再去查找变量时,变量i已经是3,所以输出结果都是9,并不是1,4,9!
- def out(n):
- f=[]
- for i in range(1,n):
- def inner(x=i):
- return x*x
- f.append(inner)
- return f
-
- f1,f2,f3=out(4)
-
- print(f1(),f2(),f3())
- ---------------------------------------
- #输出结果:
- >>>1 4 9 #由于在内层函数每次都用参数x绑定了变量i,所以最终输出结果为1,4,9
8.装饰器
装饰器类似于闭包,本质上都是用函数是'包装'函数.
- def dec(func):
- def wrapper(*args,**kwargs):
- print('This is a decorator')
- func(*args,**kwargs)
- return wrapper
-
- def func1():
- print('run func1')
- func1()
- print('=======================================')
- #用函数dec修饰func1后
- func1=dec(func1)
- func1()
- ---------------------------------------
- #输出结果:
- run func1
- =======================================
- This is a decorator
- run func1
为了简洁性和代码的复用性,Python可以采用@语法糖的形式,@dec的语法是等同于func2=dec(func2)
- @dec
- def func2():
- print('func2 is running')
- func2()
- -----------------------------------------
- #输出结果:
- This is a decorator
- func2 is running
从形式上来说,确实达到了在不改动原代码的前提下,为原函数增加的新的功能,但其实原函数的元信息已经改变
- def func2():
- print('func2 is running')
- print(func2.__name__)
-
- @dec
- def func2():
- print('func2 is running')
- print(func2.__name__)
- ---------------------------------------
- #输出结果:
- func2
- wrapper
但Python 用functools模块中的wraps方法解决了这个问题,这才是真正的装饰器
- import functools
-
- def dec(func):
- @functools.wraps(func)
- def wrapper(*args,**kwargs):
- print('This is a decorator')
- func(*args,**kwargs)
- return wrapper
- def func2():
- print('func2 is running')
- print(func2.__name__)
-
- @dec
- def func2():
- print('func2 is running')
- print(func2.__name__)
- ---------------------------------------
- #输出结果:
- func2
- func2
以上是不带参数的装饰器,若需要增加参数的话,就得再增加一层包含的层级
- import functools
-
- def dec(text):
- print(text)
- def wrap(func):
- @functools.wraps(func)
- def wrapper(*args,**kwargs):
- print('decorator with parameter')
- return func(*args,**kwargs)
- return wrapper
- return wrap
-
- @dec('parameter')
- def func():
- print('func is running')
- func()
- ---------------------------------------
- #输出结果:
- parameter
- decorator with parameter
- func is running
装饰器也是可以多层嵌套的:等同于a装饰(b装饰(c装饰func)),既 func=a(b(c(func)))
- @a
- @b
- @c
- def func():
- pass
在执行函数前打印start,执行函数后打印end的装饰器例子:
- import functools
- def dec(func):
- @functools.wraps(func)
- def wrapper(*args,**kwargs):
- print('start')
- func(*args,**kwargs)
- print('end')
- return wrapper
- @dec
- def func():
- print('func is running!')
- func()
- ---------------------------------------
- #输出结果:
- start
- func is running!
- end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。