day 10 命名空间和作用域
1默认参数的陷阱
#1 默认参数的陷阱: 如果默认参数的值是一个可变数据类型 # 那么每一次调用函数的时候 如果不传值就公用这个数据类型的资源 def qqxing(k,l={}): # l.append(1) l[k]='v' print(l) qqxing(1) qqxing(2) qqxing(3)
qqxing(4,{})#传值就不公用 <<< {1: 'v'} {1: 'v', 2: 'v'} {1: 'v', 2: 'v', 3: 'v'}
{4: 'v'}
2作业讲解
#2.写函数,检查获取传入列表或元租对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者 def func(l): return l[1::2] print(func([1,2,3,4,5])) <<< [2, 4]
#3 写函数,判断用户传入的值长度是否大于5 def func(x): return len(x)>5 if func('abcd'): print('长度确实大于5') print(func((1,2,3,4,5,6))) <<< True
#4 写函数检查传入列表的长度 如果大于2 那么仅保留前俩个长度的内容 并将新内容返回给调用者 def func(s): if len(s)<2: return "长度小于2" else: return s[:2] print(func('112')) <<< 11
#5 写函数 计算传入字符串中数字 字母 空格以及其他的个数 并返回结果 def func(s): dic={'num':0,'alpha':0,'space':0,'others':0} for i in s: if i.isdigit(): dic['num']+=1 elif i.isalpha(): dic['alpha']+=1 elif i.isspace(): dic['space']+=1 else: dic['others']+=1 return dic print(func('111 a**')) <<< {'num': 3, 'alpha': 1, 'space': 2, 'others': 2}
#6写函数 检查用户传入的对象(字符串 列表 元祖)的每一个元素是否含有空内容 并返回结果 def func(x): if type(x)is str: for i in x: if i==" ": return True elif x and type(x) is list or type(x) is tuple: for i in x: if not i: return True elif not x: return True print(func([])) <<< True
7#写函数 检查传入字典的买一个value的长度 如果大于2 那么仅保留前俩个长度的内容 并将新内容返回给调用者 dic={'k1':'v1v1','k2':[11,22,33,44]} def func(dic): for k in dic: if len(dic[k])>2: dic[k]=dic[k][:2] return dic print(func(dic)) print(dic) print(func({1:'1111',7:'666'})) print(dic) <<< {'k1': 'v1', 'k2': [11, 22]} {'k1': 'v1', 'k2': [11, 22]} {1: '11', 7: '66'} {'k1': 'v1', 'k2': [11, 22]}
#8写函数 接收俩个数字参数返回比较大的那个数字 def func(a,b): if a>b: return a else: return b print(func(1,9)) def func(a,b): return a if a>b else b print(func(1,3)) <<< 9 3
#三元运算 def func(a,b): a=1 b=5 c=a if a>b else b print(c) print(func(5,1)) <<< 5 None
#9 写函数 用户传入修改的文件名与要修改的内容 执行函数 完成整个文件的批量修改操作 def func(filename,old,new): with open(filename,encoding='utf-8') as f,open("%s.bak" % filename,'w',encoding="utf-8") as f2: for line in f: if old in line: line=line.replace(old ,new) f2.write(line) import os os.remove(filename) os.rename('%s.bak'% filename,filename) func('小护士班主任','hhhhh','666666')
3 函数的命名空间
a=1 def func(): print(a+1) func() <<<2
#命名空间有三种 ''' 内置命名空间 python解释器自带的 python解释器一启动内置的名字就被加载到内存里 全局命名空间 我们写的代码但不是函数中的代码 在程序从上到下执行的过程中依次加载进内存 放置了我们设置的所有变量名和函数 局部命名空间 函数内部定义的名字 当调用函数的时候才会产生这个命名空间 随着函数的执行这个命名空间就消失 在局部 可以使用内置和全局命名空间的名字 在全局 可以使用内置但不能使用局部命名空间的名字 在内置 不能使用局部和全局的名字 ''' def func(): a=1 func() # print(a) NameError: name 'a' is not defined def max(l): print('in max func') print(max((1,2,3))) <<< in max func None
''' 在正常情况下 直接使用内置的名字 当我们在全局定义了和内置相同的名字时 会使用全局的名字 如果自己没有就找上一级函数要 直到内置命名空间都没有就报错 多个函数拥有多个独立的局部名字空间 不互相共享''' def input(): print("in input now") def func(): print(input) func() '''func 函数的内存地址 函数名() 函数的调用 函数的内存地址() 函数的调用 ''' <<< <function input at 0x00000250E5F1D1E0>
''' 俩种作用域 全局作用域 作用在全局---内置和全局命名空间中的名字都属于全局 globals() 局部作用域 作用在局部---函数内的名字(局部命名空间中的名字) locals()''' ''' 对于不可变的数据类型 在局部可以查看全局作用域中的变量 但不能直接修改 如果想要修改 要在程序的一开始添加global声明 如果在一个局部内声明了一个global变量 那么这个变量在局部的所有操作将对全局的变量有效''' a=1 def func(): global a a=2 print(a) func() print(a) <<< 2 2
a=1 b=2 def func(): x='aaa' y='bbb' print(locals()) print(globals()) func() print(globals()) #永远打印全局的名字 print(locals()) #本地的 输出什么 根据locals所在的位置 <<< {'x': 'aaa', 'y': 'bbb'} {'__name__': '__main__', '__doc__': '\n内置命名空间 python解释器自带的 python解释器一启动内置的名字就被加载到内存里\n全局命名空间 我们写的代码但不是函数中的代码 在程序从上到下执行的过程中依次加载进内存\n 放置了我们设置的所有变量名和函数\n局部命名空间 函数内部定义的名字 当调用函数的时候才会产生这个命名空间 随着函数的执行这个命名空间就消失\n\n在局部 可以使用内置和全局命名空间的名字\n在全局 可以使用内置但不能使用局部命名空间的名字\n在内置 不能使用局部和全局的名字\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F7CBF16470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/python全栈/me第一部分/day10命名空间闭包.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x000001F7CBECD1E0>} {'__name__': '__main__', '__doc__': '\n内置命名空间 python解释器自带的 python解释器一启动内置的名字就被加载到内存里\n全局命名空间 我们写的代码但不是函数中的代码 在程序从上到下执行的过程中依次加载进内存\n 放置了我们设置的所有变量名和函数\n局部命名空间 函数内部定义的名字 当调用函数的时候才会产生这个命名空间 随着函数的执行这个命名空间就消失\n\n在局部 可以使用内置和全局命名空间的名字\n在全局 可以使用内置但不能使用局部命名空间的名字\n在内置 不能使用局部和全局的名字\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F7CBF16470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/python全栈/me第一部分/day10命名空间闭包.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x000001F7CBECD1E0>} {'__name__': '__main__', '__doc__': '\n内置命名空间 python解释器自带的 python解释器一启动内置的名字就被加载到内存里\n全局命名空间 我们写的代码但不是函数中的代码 在程序从上到下执行的过程中依次加载进内存\n 放置了我们设置的所有变量名和函数\n局部命名空间 函数内部定义的名字 当调用函数的时候才会产生这个命名空间 随着函数的执行这个命名空间就消失\n\n在局部 可以使用内置和全局命名空间的名字\n在全局 可以使用内置但不能使用局部命名空间的名字\n在内置 不能使用局部和全局的名字\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F7CBF16470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/python全栈/me第一部分/day10命名空间闭包.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x000001F7CBECD1E0>}
a=1 def func(a): a=2 return a func(a) print(func(a)) print(a) <<< 2 1
#函数的嵌套和作用域链 def max(a,b): return a if a>b else b def the_max(x,y,z): #函数的嵌套调用 c=max(x,y) return max(c,z) print(the_max(1,2,3)) <<< 3
#函数的嵌套定义 内部函数可以使用外部函数的变量 #nonlocal只能用于局部变量 找上层中离当前函数最近一层的局部变量 如果上层没有就找上上层 #声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量 #对全局无效 对局部也只是对最近的一层有影响 a=1 def outer(): a=1 def inner(): a=3 def inner2(): nonlocal a #声明了一个上面第一层局部变量 a+=1 print(a)#不可变数据类型的修改 inner2() print('inner',a) inner() print("outer:",a) outer() print('全局:',a) <<< 4 inner 4 outer: 1 全局: 1
a=0 def outer(): a=1 def inner(): a=2 def inner2(): nonlocal a a+=2 print(a) inner2() print(a) print(inner2.__closure__) inner() print(a) outer() <<< 4 4 (<cell at 0x000001DA4C34F768: int object at 0x00007FF88554B3B0>,) 1
def func(): print(123) func() func() #函数名就是内存地址 func2=func #函数名可以赋值 func2() <<< 123 123 123
def func(): print(123) func() func2=func l=[func,func2] #函数名可以作为容器类型的元素 print(l) for i in l: i() <<< 123 [<function func at 0x00000186D7B0D1E0>, <function func at 0x00000186D7B0D1E0>] 123 123
func(): print(123) def wahaha(f): f() return f #函数名可以作为函数的返回值 qqxing=wahaha(func)#函数名可以作为函数的参数 qqxing() <<< 123 123
5闭包
#闭包:嵌套函数 内部函数调用外部函数的变量 def outer(): a=1 def inner(): print(a) print(inner.__closure__) #如果有个cell就是闭包 # __closure__属性定义的是一个包含 cell 对象的元组, # 其中元组中的每一个 cell 对象用来保存作用域中变量的值。 inner() outer() <<< (<cell at 0x0000017917B4F768: int object at 0x00007FF88554B350>,) 1
#闭包最常用写法 def outer(): a=1 print('2') def inner(): print(a) return inner inn=outer() inn() print(inn) outer() <<< 2 1 <function outer.<locals>.inner at 0x0000024FCA7A9C80> 2
import urllib from urllib.request import urlopen ret=urlopen('https://i.cnblogs.com/EditArticles.aspx').read() print(ret.decode('utf-8')) print(ret) <<< <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" c.........
import urllib from urllib.request import urlopen def get_url(): url="https://ilovefishc.com/html5/" ret=urlopen(url).read() print(ret.decode('utf-8')) get_url() <<< ....
import urllib from urllib.request import urlopen def get_url(): url="https://ilovefishc.com/html5/" def get(): ret=urlopen(url).read() print(ret) return get get_func=get_url() get_func()
#3 函数的命名空间