def func(**kwargs):
print(*kwargs) #打印:a b
print(kwargs) #打印:{'b': 2, 'a': 1}
# print(**kwargs) #这句报错,你知道为什么吗?
#def print(self, *args, sep=' ', end='\n', file=None):
#这个是print()的函数原型,里面支持*args,但是没有支持**kwargs
dic = {'a':1,'b':2}
func(**dic)
可变的数据类型,比如列表,字典,
不需要global,
python2没有nonlocal,
python3没有nonlocal。
def func1(**kwargs):
print(kwargs)
func1(**{"1":22,"2":4})
# about 魔法* on 打散,聚合的说法 in 动态传参,
# 我再整理下,
# 首先在函数调用的时候,你通过*[1,2,3,4]的形式,将列表打散聚合成元组的形式,
# 此处既有“打散”,也有“聚合”
#在函数内部这个*的作用,
#首先print的时候,你不加*,args输出就是元组,kwargs输出就是字典,
#你加*之后,就变成散的了,
我说个事,选中文字,按Tab键,选中文字往右缩进,
shift+Tab,是往左边缩进
def add_b():
b = 42
def do_global():
# nonlocal b #加上这句话,确实能让3层的b均指向同一个,但是id却又不同。
b = 10
print(b) # 1.10
def dd_nonlocal():
nonlocal b
b = b + 20
print(b) # 2.30
dd_nonlocal()
print(b) # 3.30
do_global()
print(b) # 4.42
add_b()
#*******************************************************
def one():
a = 3
print(id(a))
def two():
nonlocal a
a = 4
print(id(a))
def three():
nonlocal a
a =5
print(id(a))
print(id(a))
return three
print(id(a))
return two
one()()()
#打印结果,三个id都不一样,想不明白啊,
# 1569739616
# 1569739648
# 1569739680
开始函数名,
def f1():
print(1211)
def f2():
print(1222)
def f3():
print(1233)
def f4():
print(1233)
l1 = []
for i in range(1,5):
l1.append('f'+str(i))
print(l1)
for i in l1:
eval(i)() #注意这句话,以及eval()函数,
关于闭包,
# 闭包:就是内层函数对外层函数(非全局)变量的引用。
# 如何判断 内层函数名.__closure__ cell 就是=闭包
def wraaper1():
name = '老男孩'
def inner():
print(name) #这里的name是对外层的引用
inner() #这里即使不调用inner()函数,下面的闭包判断函数依旧成立,
print(inner.__closure__) # cell
wraaper1()
#*****************************************************
name = '老男孩'
def wraaper2():
name1 = 'alex'
def inner():
print(name) #这里既引用了全局的变量,也引用了非全局的,
print(name1) #答案是,这依旧是闭包,
inner()
print(inner.__closure__) # None
wraaper2()
name = '老男孩'
def wraaper2(n):
# n = '老男孩' 相当于
def inner():
print(n)
inner()
print(inner.__closure__) # None
wraaper2(name)
#这里依旧是闭包,问题的关键是内层向外层(非全局)有引用
# 闭包:当函数开始执行时,如果遇到了闭包,他有一个机制,
# 他会永远开辟一个内存空间,将必包中的变量等值放入其中,不会随着函数的执行完毕而消失。
#爬虫爬取的网址的源代码,就有利用这,
下面是装饰器,
下面的序号是上面代码的执行顺序:
# 2:进入2很正常,在前面嘛,但是因为是def,所以直接跳过了,
# 12:上面过来就是@timer了,语法糖修饰的是timer,所以这次会进入timer内部,
# 这行我要来个特写,这一句话完成了不止一个功能,它还把func1的位置穿进去了,
# 2:这次是要要进入timer了,
# 3:timer内的第一行就是一个def函数定义,so直接跳过,
# 10:上面跳过def部分,就直接返回inner的位置了,
# 23:此时fun1实际就是inner,并且前面也把开始func1函数传进去inner了,
# 3:这回是真正开始执行inner,
# 4:pass
# 5:pass
# 12:进入func1代码最开始的真正位置,
# 14:开始执行原来func1函数,
# 15:pass
# 16:pass
# 6:原来func1函数执行完毕,回到inner内,继续,
# 7:pass
# 8:pass
# 9:pass
# 24:这句有点多余,主要是想看最后到哪了,
# 关于传参的问题,
# 首先,你还是得通过原函数的形式来传参,但其实此时的原函数已经是inner了,
# 所以内部的inner需要有个交接的过程,
# 同样的返回值也有同样的问题,
# 所以inner在内部需要接住原本func1函数的返回值,
# inner继续做个交接,然后return这个值,
# 这样传参和返回值都无缝对接了,
#************************************************
# 还有传参你得用动态传参,这样就解决了,你到底该设定几个形参的问题了,
关于装饰器的一个总结:
# 不改变原来函数的调用的前提下增加功能,
# 个人认为就是python通过在内部修改指针,给我们上层人员提供了这么一个好用的功能
下面是把以前遗留问题解决下,
# 4,文件a2.txt内容:每一行内容分别为商品名字,价钱,个数。
# 文件内容:
# 序号 部门 人数 平均年龄 备注
# 1 python 30 26 单身狗
# 2 Linux 26 30 没对象
# 3 运营部 20 24 女生多
# 通过代码,将其构建成这种数据类型:
# [{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'},
# ......]
# 并计算出总价钱。
l1 = []
with open('a1.txt',encoding='utf-8') as f1:
list_name = f1.readline().strip().split()
for i in f1:
for j in li:
l2 = j.strip().split(':')
pass
l1.append(dic)
print(l1)
#*********我是可爱的分割线,上面是老师的写法,下面是我自己的写法********************
#我来总结下:我直接把表头去掉了,而老师则是存储起来,其实这个表头大有用处,可以帮助我们实现更大的通用!!!
#还有其实我们可以在变量用的前面定义,不一定非要在最开始定义,看的好丑!!!
f = open("boy", encoding="utf-8", mode="r")
li = []
l1 = []
l2 = []
with open('boy',encoding='utf-8', mode='r') as f:
li = f.readlines()
for x in range(1,len(li)):
l1 = li[x].strip().split()
l2.append({'序号':l1[0],"部门":l1[1],'人数':int(l1[2]),'平均年龄':int(l1[3]),'备注':l1[4]})
print(l2)
sum = 0
for x in l2:
sum += x['人数']*x['平均年龄']
print(sum)
def extendList(val,list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
# 你可以试试在同位置插入print语句,打印list1,
# 总结:默认参数为可变数据类型时,使用的是同一个,这个是老师总结的,
# 我的理解就是可变数据类型是全局的