<笔记>第一篇:函数笔记
- 为什么要用函数?防止代码冗余、可读性差、可扩展性差(不易修改)
- return:一旦遇到return ,结束整个函数,可以返回任何类型的值,返回多个值会成被组织成元祖被返回,也可以用多个值接收
- 求最大值:max = x if x>y else y
- 位置参数:位置参数必须传值,不传值就会报错且必须在关键字参数前面,一个形参只能赋值一次
- 默认参数:将变化比较小的值设置成默认参数
-
def stu_info(name,sex = "male"): """打印学生信息函数,由于班中大部分学生都是男生, 所以设置默认参数sex的默认值为'male' """ print(name,sex) stu_info('alex') stu_info('eva','female')
-
- 参数陷阱:默认参数设定成一个可变数据类型
-
def defult_param(a, l=[]): l.append(a) print(l) defult_param('A') # ['A'] defult_param('B') # ['A', 'B'] defult_param('C') # ['A', 'B', 'C']
-
- 动态参数:
- 把按照位置传值多余的参数都由*args统一接收,保存成一个元祖形式
- 把按照关键字传值多余的参数都由**kwargs统一接收,保存成一个元祖形式
- 标准写法
-
标准模式 def 函数名(参数1,参数2,*args,默认参数,**kwargs): """注释:函数功能和参数说明""" 函数体 …… return 返回值
-
- 解释器遇到函数:当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。
- 命名空间(三种):
- 全局命名空间:类似于全局变量
- 局部命名空间:函数内的命名空间,类似局部变量
- 内置命名空间:存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。
- 加载顺序
- 内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
-
在局部调用:局部命名空间->全局命名空间->内置命名空间
- 在全局调用:全局命名空间->内置命名空间
- 函数名的本质:函数的内存地址,可以当函数的参数和返回值
- 闭包函数:内部函数包含对外部作用域而非全局作用域名字的引用,该内部函数称为闭包函数
- 装饰器函数:在不修改原函数及其调用方式的情况下对原函数进行扩展
- 版本1.0---没有实现返回值和参数
-
import time def func1(): print('in func1') def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner func1 = timer(func1) func1()
-
- 版本2.0--没有实现参数
-
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer #==> func1 = timer(func1) def func1(): print('in func1') func1()
-
-
版本3.0---装饰器也被称为'语法糖'
-
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func2('aaaaaa') print(func2('aaaaaa'))
-
-
固定格式
-
def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' re = func(*args,**kwargs) '''执行函数之后要做的''' return re return inner
-
-
装饰器完美符合开放封闭原则:扩展开放,修改封闭
-
扩展版本:版本4.0多个装饰器装饰同一个函数
-
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper2 @wrapper1 def f(): print('in f') f()
-
- 版本1.0---没有实现返回值和参数
-
思考:索引取值和for取值的区别?
-
字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的。
-
什么是可迭代?可以将某个数据集内的数据"一个挨着一个的取出来",就叫迭代.从结果上来看能被for循环的就叫可迭代的
-
更底层,可迭代需要满足什么?可以被迭代需要满足可迭代协议(内部实现了__iter__方法)
-
可以被迭代的对象,后面跟__iter__方法就叫迭代器
-
print([1,2].__iter__()) # <list_iterator object at 0x00000000024FA048>
-
-
列表迭代器跟列表相比多了哪些方法?
-
print(set(dir([1, 2].__iter__())) - set(dir([1, 2]))) # {'__setstate__', '__length_hint__', '__next__'}
-
__setstate__:根据索引值确定从哪里开始迭代
-
__length_hint__:计算长度
-
__next__:一个一个取值(取下一个值)
-
- for循环之所以能一个一个取值,是因为反复实现__next__方法
- for循环的本质:for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就 都可以通过for循环来遍历了,而且你看到的效果也确实如此,这就是无所不能的for循环.
- 生成器:我们自己写的这个能实现迭代器功能的东西就叫生成器。(我们自己写实现迭代器功能的函数就叫生成器)
- Python中提供的生成器
- 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
- 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
-
egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析 laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式
# 把列表解析的[]换成()得到的就是生成器表达式
-
-
生成器是惰性执行,需要才执行,调用一次执行一次,这样就不会再内存中生成太多数据
-
优点
-
延迟计算:一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
-
#列表解析 sum([i for i in range(100000000)])#内存占用大,机器容易卡死 #生成器表达式 sum(i for i in range(100000000))#几乎不占内存
-
-
提高代码可读性
-
-
匿名函数:函数名 = lambda 参数 :返回值
-
常用内置函数
-
str类型代码执行:eval,exec
-
数字:bool,int,float,abs,divmod,min,max,sum,round,pow
-
序列——列表和元组相关的:list和tuple
-
序列——字符串相关的:str,bytes,repr
-
序列:reversed,slice
-
数据集合——字典和集合:dict,set,frozenset
-
数据集合:len,sorted,enumerate,zip,filter,map
-
其他:input,print,type,hash,open,import,dir
-
-
递归:在一个函数里再调用这个函数本身,这种魔性的使用函数的方式就叫做递归。
-
递归的最大深度——997
-
修改最大递归深度
-
import sys print(sys.setrecursionlimit(100000))
-
-