函数基础
1. 速查笔记
#-- 函数相关的语句和表达式 myfunc('spam') # 函数调用 def myfunc(): # 函数定义 return None # 函数返回值 global a # 全局变量 nonlocal x # 在函数或其他作用域中使用外层(非全局)变量 yield x # 生成器函数返回 lambda # 匿名函数
2. 函数的好处
代码复用、保持代码一致性、可扩展性
函数的参数
1. 速查笔记
#-- 函数参数,不可变参数通过“值”传递,可变参数通过“引用”传递 def f(a, b, c): print(a, b, c) f(1, 2, 3) # 参数位置匹配 f(1, c = 3, b = 2) # 参数关键字匹配 def f(a, b = 1, c = 2): print(a, b, c) f(1) # 默认参数匹配 f(1, 2) # 默认参数匹配 f(a = 1, c = 3) # 关键字参数和默认参数的混合 # Keyword-Only参数:出现在*args之后 必须用关键字进行匹配 def keyOnly(a, *b, c): print('') # c就为keyword-only匹配 必须使用关键字c = value匹配 def keyOnly(a, *, b, c): ...... # b c为keyword-only匹配 必须使用关键字匹配 def keyOnly(a, *, b = 1): ...... # b有默认值 或者省略 或者使用关键字参数b = value
#-- 可变参数匹配: * 和 ** def f(*args): print(args) # 在元组中收集不匹配的位置参数 f(1, 2, 3) # 输出(1, 2, 3) def f(**args): print(args) # 在字典中收集不匹配的关键字参数 f(a = 1, b = 2) # 输出{'a':1, 'b':2} def f(a, *b **c): print(a, b, c) # 两者混合使用 f(1, 2, 3, x = 4, y = 5) # 输出1, (2, 3), {'x':4, 'y':5}
示例:
# -*- coding:utf-8 -*- def canshu(a,*args,**kwargs): print('位置参数值a: %s '%a) print(args) print(kwargs) #函数默认的返回值个数为0时,返回None,如果返回值个数为一个,那么就是return后的值,如果返回值个数大于1,以元组形式返回 #return后的语句,不会再执行 return 0 test= canshu('python','ruby','java',c = 'shell',d = 'perl') print(test)
运行结果:
位置参数值a: python
('ruby', 'java')
{'c': 'shell', 'd': 'perl'}
0
2. 参数的其他知识点
#-- 函数调用时的参数解包: * 和 ** 分别解包元组和字典 func(1, *(2, 3)) <==> func(1, 2, 3) func(1, **{'c':3, 'b':2}) <==> func(1, b = 2, c = 3) func(1, *(2, 3), **{'c':3, 'b':2}) <==> func(1, 2, 3, b = 2, c = 3) #-- 函数属性:(自己定义的)函数可以添加属性 def func():..... func.count = 1 # 自定义函数添加属性 print.count = 1 # Error 内置函数不可以添加属性 #-- 函数注解: 编写在def头部行 主要用于说明参数范围、参数类型、返回值类型等 def func(a:'spam', b:(1, 10), c:float) -> int : print(a, b, c) func.__annotations__ # {'c':<class 'float'>, 'b':(1, 10), 'a':'spam', 'return':<class 'int'>} # 编写注解的同时 还是可以使用函数默认值 并且注解的位置位于=号的前边 def func(a:'spam'='a', b:(1, 10)=2, c:float=3) -> int : print(a, b, c)
函数的局部变量与全局变量-作用域
1. 速查笔记
#-- Python函数变量名解析:LEGB原则,即: """ local(functin) --> encloseing(相邻的) function locals --> global(module) --> build-in(python) 说明:以下边的函数maker为例 则相对于action而言 X为Local N为Encloseing """ #-- 嵌套函数举例:工厂函数 def maker(N): def action(X): return X ** N return action f = maker(2) # pass 2 to N f(3) # 9, pass 3 to X #-- 嵌套函数举例:lambda实例 def maker(N): action = (lambda X: X**N) return action f = maker(2) # pass 2 to N f(3) # 9, pass 3 to X #-- nonlocal和global语句的区别 # nonlocal应用于一个嵌套的函数的作用域中的一个名称 例如: start = 100 def tester(start): def nested(label): nonlocal start # 指定start为tester函数内的local变量 而不是global变量start print(label, start) start += 3 return nested # global为全局的变量 即def之外的变量 def tester(start): def nested(label): global start # 指定start为global变量start print(label, start) start += 3 return nested
2.全局变量的作用域是整个函数,局部变量作用域是定义该变量的子程序
递归函数
定义:在函数内部,可以调用其他函数,如果一个函数在内部调用自身,就是递归函数
特性:① 必须有一个明确的结束条件;② 每一次更深的递归时,问题规模相比上次递归应减少
简单示例:裴波那契数列
def fibo(n):
if n<3:
return 1
return fibo(n-2)+fibo(n-1)
print(fibo(5))
匿名函数lambda
1. 速查笔记
#-- 匿名函数:lambda f = lambda x, y, z : x + y + z # 普通匿名函数,使用方法f(1, 2, 3) f = lambda x = 1, y = 1: x + y # 带默认参数的lambda函数 def action(x): # 嵌套lambda函数 return (lambda y : x + y) f = lambda: a if xxx() else b # 无参数的lambda函数,使用方法f() #-- lambda函数与map filter reduce函数的结合 list(map((lambda x: x + 1), [1, 2, 3])) # [2, 3, 4] list(filter((lambda x: x > 0), range(-4, 5))) # [1, 2, 3, 4] functools.reduce((lambda x, y: x + y), [1, 2, 3]) # 6 functools.reduce((lambda x, y: x * y), [2, 3, 4]) # 24
装饰器
1.速查笔记
#-- 函数装饰器:是它后边的函数的运行时的声明 由@符号以及后边紧跟的"元函数"(metafunction)组成 @staticmethod def smeth(x): print(x) # 等同于: def smeth(x): print(x) smeth = staticmethod(smeth)
定义:在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)
经典示例:
# -*- coding:utf-8 -*- import time def timer(func): #把被装饰的函数ceshi的内存地址传给了func def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print('测试函数运行时间',(stop_time-start_time)) return deco #返回deco的内存地址 @timer def ceshi(a): time.sleep(3) print('测试%s'%a) ceshi('装饰器')
2. 原则:①不能修改被装饰函数的源代码;②不能修改被装饰函数的调用方式
3.实现装饰器的技能储备
① 函数本身即是变量
② 高阶函数,把一个函数名当做实参穿给另一个函数
③ 嵌套函数
生成器
1.速查笔记 #-- 生成器函数:yield VS return def gensquare(N): for i in range(N): yield i** 2 # 状态挂起 可以恢复到此时的状态 for i in gensquare(5): # 使用方法 print(i, end = ' ') # [0, 1, 4, 9, 16] x = gensquare(2) # x是一个生成对象 next(x) # 等同于x.__next__() 返回0 next(x) # 等同于x.__next__() 返回1 next(x) # 等同于x.__next__() 抛出异常StopIteration
#-- 生成器表达式:小括号进行列表解析 G = (x ** 2 for x in range(3)) # 使用小括号可以创建所需结果的生成器generator object next(G), next(G), next(G) # 和上述中的生成器函数的返回值一致 #(1)生成器(生成器函数/生成器表达式)是单个迭代对象 G = (x ** 2 for x in range(4)) I1 = iter(G) # 这里实际上iter(G) = G next(I1) # 输出0 next(G) # 输出1 next(I1) # 输出4 #(2)生成器不保留迭代后的结果 gen = (i for i in range(4)) in gen # 返回True in gen # 返回True in gen # 返回False,其实检测2的时候,1已经就不在生成器中了,即1已经被迭代过了,同理2、3也不在了
2. 生成器表达式
局限性:只能适合简单的算法
示例:
test = (x**2 for x in range(1,10))
print(next(test))
print(test.__next__())
3. 生成器函数 yield
斐波那契函数的打印示例:
def fib(max): a,b,n = 1,1,0 while n<max: yield b a,b = b,a+b n+=1 return b test = fib(10) print(test.__next__()) print(next(test)) for i in test: print(i)