python基础学习day11函数的进阶
-
默认参数的陷阱(只针对于默认参数是可变的数据类型):如果默认参数使用的是可变类型数据,那么无论调用多少次这个默认参数,都是同一个(id相同)。默认参数的可变数据类型既不在全局也不再局部,定义后不会消失(局部命称空间会消失)。
def func(num,nums=[]): nums.append(num) return nums ret1 = func(1) print(ret) >>>[1] ret2 = fun(2) print(ret2) >>>[1,2] #将第一次的数据也包含了。 #例: def func(a,list=[]): list.append(a) return list ret1 = func(10,) print(ret1) #[10] print(func(20,[])) #[20] #重新为列表传入参数 print(func(100)) #[10,100] print(ret1) #[10,100]
-
局部作用域的陷阱:在函数中,如果定义一个变量,但是在定义变量之前引用这个变量,即使全局变量有此引用的变量,仍然会报错。
#例1: count = 1 def func(): count += 1 print(count) func() indentationerror: unindent does not match any outer indentation level #例2: count = 1 def func(): print(count) func() #1 #例3: count = 1 def func(): print(count) count = 1 func() unboundlocalerror: local variable 'count' referenced before assignment
-
global nonlocal
-
global:1.在局部作用域里声明一个全局变量。
#1. num = 0 def func(): num = 1 print(num) #0 #2. def func(): global num num = 1 print(num) #会报错。 #3. def func(): global num num = 1 func() print(num) #1 #3. num = 0 def func(): global num num = 1 func() print(num) #1
-
nonlocal:不能够操作全局变量;主要用于内层函数对外层函数的局部变量进行修改。
def func1(): count = 1 def inner(): nonlocal count count+=1 inner()
-
-
函数名的运用
-
函数名指向的是函数的内存地址
-
函数名 + ()就可以执行函数
#例1: def func(): print(1) f1 = func f2 = f1 f2() #1 #例2. def func1(): print(1) def func2(): print(2) func2 = func1 func2() #1
-
函数名可以作为容器类数据类型的元素
#例3: def func1(): print(1) def func2(): print(2) def func3(): print(3) l1 = [func1,func2,func3] for i in l1: i() #1 2 3
-
函数名可以作为函数的参数
def func0(a): print(1) def func1(x): x() func1(func0) #1
-
函数名可以作为函数的返回值。
def func1(): print(1) def func2(x): return x ret = func2(func) ret() #1
-
-
格式化输出(3.6版本之后):
- 基础表达:
```python name = 'python' age = '18' msg = f'我叫{name},今年{age}' #在引号前添加一个字符f ```
-
可以加表达式:
count = 2 print(f'最终结果:{count**2}') name = 'python' print(f'我的名字是{name.upper()}') dic = {'name':'python','age':'18'} msg = f'我叫{dic["name"]},今年{dic["age"]}' #注意双引号与单引号的使用,不能产生歧义。 list = ['python','18'] msg = f'我叫{list[0]},今年{list[1]}'
-
可以结合函数:
def sum1(a,b): return a+b print(f'最终结果是{sum1(1,2)}')
-
优点:1.结构更加优化。2.可以结合表达式和函数使用。3.效率更高
-
迭代器:
-
可迭代对象:
对象:python中一切皆对象。 可迭代:可以进行循环更新的一个值。
以专业角度来说,内部含
__iter__
方法的对象即为可迭代对象。如:str、list、tuple、dict、set、range、文件句柄等。 -
获取对象的所有方法并且以字符串的形式表现:dir()
s1 = 'qwer' print(dir(s1)) #请自测。
-
判断一个对象是否是可迭代对象:
s1 = 'qwer' print('__iter__' in dir(s1)) #true
-
可迭代对象的优点:
- 存储的数据能够直接显示,比较直观。
- 拥有的方法比较多,操作起来方便。
-
可迭代对象的优点:
-
占内存。
-
不能直接通过for循环(不能直接取值),python内部自动将其转换为迭代器(见下文)然后再进行for循环(用next()方法取值,见下文。)。
l1 = [1,2,3,4] for i in l1: print(i) #python内部自动将其转换为迭代器然后再进行for循环
-
-
迭代器:
迭代器的定义:内部含
__iter__
和__next__
方法的对象就是迭代器。例如:文件句柄。 -
判断是否为可迭代器:
with open ('1.txt',encoding='utf-8',mode='w') as f1: print('__iter__' in dir(f1) and '__next__' in dir(f1))
-
可迭代对象可以转换为迭代器:
s1 = 'qwert' obj = iter(s1) #或者: s1.__iter__() print(obj) #请自测,会返回一个迭代器的内存地址
-
对迭代器进行取值:
s1 = 'qwert' obj = iter(s1) next(obj) #会取出字符串s1的第一个元素 next(obj) #会返回字符串s1的第二个元素 #或: obj.__next__()
-
迭代器优点:
1.节省内存,迭代器在内存中相当于只占一个数据的空间,因为每次取值上一条数据都会在内存释放。迭代器具有惰性机制,next一次,只取一个值,绝不多取。
-
迭代器的缺点:
1.不能直观的查看里面的数据。
2.只能一直向下取值。
3.速度慢。
-
可迭代对象与迭代器的对比:
- 可迭代对象是的操作方法比较多,比较直观,储存数据相对少(几百万个数据,8g内存是可以承受的)的一个数据集。
- 当侧重于对于数据可以灵活处理,并且内存空间足够,可将数据设置为一个可迭代对象。
- 迭代器是非常节省内存,可以记录取值位置,可以通过循环加next方法取值,但是不直观,操作方法比较单一的一个数据集。
- 当数据量过大,可选择将数据设置为一个迭代器。
-
用while循环模拟for循环对可迭代对象进行取值:(请自测)
l1 = [1,2,3,4,5,6,7,8] obj = iter(l1) while 1: try: #try:异常处理 print(next(obj)) except stopiteration: break
-
上一篇: 委派模式和策略模式
下一篇: HTML标题重要性与html水平线和注释