咱们在补充这两个知识点以前,咱们先看一下下面这个例子:python
a = 1 def func(): print(a) # 1 func() a = 1 def func(): # 这里不可以对更改全局做用域变量的值。只可以赋值。否则会报出下面的错误。 a += 1 # 报错 UnboundLocalError: local variable 'a' referenced before assignment func()
局部做用域对全局做用域的变量(此变量只能是不可变的数据类型)只能进行引用,而不能进行改变,只要改变就会报错,可是有些时候,咱们程序中会遇到局部做用域去改变全局做用域的一些变量的需求,这怎么作呢?这就得用到关键字global:面试
global第一个功能:在局部做用域中能够更改全局做用域的变量。数组
global第二个功能:利用global在局部做用域也能够声明一个全局变量。缓存
# 这是一个十分重要的例子。必定要深入的体会。 count = 1 count1 = 2 def search(): global count # 将count变量变为全局的,而后能够在函数体(局部做用域)中能够更改全局做用域的变量。 count += 2 # 那么咱们如今就能够对全局变量count的值进行修改。 def search1(): global count1 # 将count1变量变为全局的,而后能够在函数体(局部做用域)中能够更改全局做用域的变量。 count = 6 # 若是没有global这个关键字,那么咱们不能够对count的值进行修改操做,只能够进行赋值的操做。 count1 = 5 # 那么咱们如今就能够对全局变量count1的值进行赋值修改。 print(count) # 6 print(count1) # 5 search() print(count) # 3 这里打印count的时候,取值是从全局做用域开始找--》到内置做用域结束。这里的count在前面已经被更改了(global count count += 2),因此这里输出的结果为3 search1() print(count) # 3 这里打印count的时候,取值是从全局做用域开始找--》到内置做用域结束。这里的count在前面已经被更改了(global count count += 2),因此这里输出的结果为3 print(count1) # 5 这里打印count的时候,取值是从全局做用域开始找--》到内置做用域结束。这里的count在前面已经被更改了(global count1 count1 = 5),因此这里输出的结果为5
因此global关键字有两个做用:函数
1.声明一个全局变量。源码分析
2.在局部做用域想要对全局做用域的全局变量进行修改时,须要用到 global(限于字符串,数字)。编码
nonlocal是python3x新加的功能,与global用法差很少,就是在局部做用域若是想对父级做用域的变量进行改变时,须要用到nonlocal。code
def add_b(): b = 42 def do_global(): b = 10 print(b) def dd_nonlocal(): nonlocal b b = b + 20 print(b) dd_nonlocal() print(b) do_global() print(b) add_b() # 输出的结果为: # 10 # 30 # 30 # 42
nonlocal的总结:orm
1.不能更改全局变量。对象
2.在局部做用域中,对父级做用域(或者更外层做用域非全局做用域)的变量进行引用和修改,而且引用的哪层,从那层及如下此变量所有发生改变。
函数名的理解:函数名的定义和变量的定义几乎一致,在变量的角度,函数名其实就是一个变量,具备变量的功能:能够赋值;可是做为函数名他也有特殊的功能就是加上()就会执行对应的函数,因此咱们能够把函数名当作一个特殊的变量,那么接下来,咱们就来研究一下这个特殊的变量。
def func(): a = 1 b = 2 print(a) print(a+b) print(func) # <function func at 0x000001FBBA424678> # 注释,函数名至关于变量,函数名指向的是函数的内存地址,,其实深一步理解可得知,与其说函数名()能够执行这个函数,不如说是函数的内存地址()才是执行这个函数的关键。
def func(): a = 1 b = 2 print(a) print(a+b) return '函数执行结束' print(func) # <function func at 0x000001FBBA424678> a = func # 函数名能够赋值给其余变量,把函数当成一个变量赋值给另外一个变量 print(a) # <function func at 0x000001FBBA424678> print(a()) # 函数执行结束 # 经过变量的赋值,变量a,和变量func都指向的这个函数的内存地址,那么a() 固然能够执行这个函数了。
函数名能够当作容器类的元素,其实这个也不难理解,函数名就是一个变量,个人变量是能够当作容器类类型的元素的:
a = 1 b = 'alex' c = '武sir' l1 = [a, b, c] for i in l1: print(i) ''' # 结果: 1 alex 武sir '''
那么函数名也是能够的:
def func1(): print("in func1: 嘻嘻") def func2(): print("in func2: 哈哈") def func3(): print("in func3: 咯咯") def func4(): print("in func4: 吱吱") lst = [func1, func2, func3, func4] for i in lst: i()
# 变量能够作的,函数名均可以作到,函数名能够当作函数的参数 def func1(): print('in func1') def func2(f): print('in func2') f() func2(func1)
# 函数名能够做为函数的返回值 def func1(): print('in func1') def func2(f): print('in func2') return f ret = func2(func1) ret() # ret, f, func1 都是指向的func1这个函数的内存地址
小结:函数名是一个特殊的变量,他除了具备变量的功能,还有最主要一个特色就是加上() 就执行,其实他还有一个学名叫第一类对象。
f-strings 是python3.6开始加入标准库的格式化输出新的写法,这个格式化输出比以前的%s 或者 format 效率高而且更加简化,很是的好用。相信这个格式化的输出是你之后惟一的选择。
f-strings格式化输出的结构是F(f)+ str的形式,在字符串中想替换的位置用{}展位,与format相似,可是用在字符串后面写入替换的内容,而他能够直接识别。
name = 'zhouqian' age = 18 sex = '男' msg = F'姓名:{name},性别:{age},年龄:{sex}' msg1 = f'姓名:{name},年龄:{age},性别:{sex}' print(msg) print(msg1) # 姓名:zhouqian,性别:18,年龄:男 # 姓名:zhouqian,年龄:18,性别:男
他能够加任意的表达式,很是方便。
print(f'{3*21}') # 63 name = 'AndreasZhou' print(f"所有大写:{name.upper()}") # 所有大写:ANDREASZHOU # 字典也能够 teacher = {'name': '周乾', 'age': 18} msg = f"The teacher is {teacher['name']}, aged {teacher['age']}" print(msg) # The comedian is 周乾, aged 18 # 列表也行 l1 = ['周乾', 18] msg = f'姓名:{l1[0]},年龄:{l1[1]}.' print(msg) # 姓名:周乾,年龄:18. # 也能够插入表达式 def sum_a_b(a,b): return a + b a = 1 b = 2 print('求和的结果为' + f'{sum_a_b(a,b)}') # 求和的结果为3 name = 'zhouqian' age = 18 ajd = 'handsome' speaker = f'Hi {name}.'\ f'You are {age} years old.'\ f'You are a {ajd} boy!' print(speaker) # Hi zhouqian.You are 18 years old.You are a handsome boy! print(f"{{73}}") # {73} print(f"{{{73}}}") # {73} print(f"{{{{73}}}}") # {{73}} m = 21 # ! , : { } ;这些标点不能出如今{} 这里面。 # print(f'{;12}') # 报错 # 因此使用lambda 表达式会出现一些问题。 # 解决方式:可将lambda嵌套在圆括号里面解决此问题。 x = 5 print(f'{(lambda x: x*2) (x)}') # 10
总结:f-string的格式化输出更加简洁,方便,易读。并且他的处理速度对以前的%s 或者format 有了较高的提高,因此之后尽可能使用此种格式化输出。
匿名函数,顾名思义就是没有名字的函数,那么什么函数没有名字呢?这个就是咱们之后面试或者工做中常常用匿名函数 lambda,也叫一句话函数。
如今有一个需求:大家写一个函数,此函数接收两个int参数,返回和值。
def func(a,b): return a+b print(func(3,4))
那么接下来咱们用匿名函数完成上面的需求:
func = lambda a,b: a+b print(func(3, 4)) # 7
咱们分析一下上面的代码:
语法:
函数名 = lambda 参数:返回值
1)此函数不是没有名字,他是有名字的,他的名字就是你给其设置的变量,好比func.
2)lambda 是定义匿名函数的关键字,至关于函数的def.
3)lambda 后面直接加形参,形参加多少均可以,只要用逗号隔开就行。
func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs print(func(3, 4,c=666,name='alex')) # {'name': 'alex'} # 全部类型的形参均可以加,可是通常使用匿名函数只是加位置参数,其余的用不到。
4)返回值在冒号以后设置,返回值和正常的函数同样,能够是任意数据类型。
5)匿名函数无论多复杂.只能写一行.且逻辑结束后直接返回数据
接下来作几个匿名函数的小题:
写匿名函数:接收一个可切片的数据,返回索引为0与2的对应的元素(元组形式)。
func = lambda x:(x[0],x[2]) print(func('afafasd'))
写匿名函数:接收两个int参数,将较大的数据返回。
func = lambda x,y: x if x > y else y print(func(3,100))
黄色一带而过:all() any() bytes() callable() chr() complex() divmod() eval() exec() format() frozenset() globals() hash() help() id() input() int() iter() locals() next() oct() ord() pow() repr() round()
all():可迭代对象中,全都是True才是True。
any():可迭代对象中,有一个True就是True。
# all 可迭代对象中,全都是True才是True # any 可迭代对象中,有一个True 就是True # print(all([1,2,True,0])) # False # print(any([1,'',0])) # True
bytes:用于不一样编码之间的转化。
# s = '你好' # bs = s.encode('utf-8') # print(bs) # s1 = bs.decode('utf-8') # print(s1) # bs = bytes(s,encoding='utf-8') # print(bs) # b = '你好'.encode('gbk') # b1 = b.decode('gbk') # print(b1.encode('utf-8'))
callable:函数用于检查一个对象是不是可调用的。若是返回True,object仍然可能调用失败;但若是返回False,调用对象ojbect绝对不会成功。
name = 'alex' def func(): pass print(callable(name)) # False print(callable(func)) # True
ord:输入字符找该字符编码的位置
chr:输入位置数字找出其对应的字符
# ord 输入字符找该字符编码的位置 # print(ord('a')) # print(ord('中')) # chr 输入位置数字找出其对应的字符 # print(chr(97)) # print(chr(20013))
eval:执行字符串类型的代码,并返回最终结果。
eval('2 + 2') # 4 n=81 eval("n + 4") # 85 eval('print(666)') # 666
exec:执行字符串类型的代码。
s = ''' for i in [1,2,3]: print(i) ''' exec(s)
hash:获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。
print(hash(12322)) print(hash('123')) print(hash('arg')) print(hash('alex')) print(hash(True)) print(hash(False)) print(hash((1,2,3))) ''' -2996001552409009098 -4637515981888139739 1 2528502973977326415 '''
help:函数用于查看函数或模块用途的详细说明。
print(help(list)) print(help(str.split))
int:函数用于将一个字符串或数字转换为整型。
print(int()) # 0 print(int('12')) # 12 print(int(3.6)) # 3 print(int('0100',base=2)) # 将2进制的 0100 转化成十进制。结果为 4
float:函数用于将整数和字符串转换成浮点数。
complex:函数用于建立一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。若是第一个参数为字符串,则不须要指定第二个参数。。
print(float(3)) # 3.0 print(complex(1,2)) # (1+2j)
bin:将十进制转换成二进制并返回。
oct:将十进制转化成八进制字符串并返回。
hex:将十进制转化成十六进制字符串并返回。
print(bin(10),type(bin(10))) # 0b1010 <class 'str'> print(oct(10),type(oct(10))) # 0o12 <class 'str'> print(hex(10),type(hex(10))) # 0xa <class 'str'>
divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。
round:保留浮点数的小数位数,默认保留整数。
pow:求xy次幂。(三个参数为xy的结果对z取余)
print(divmod(7,2)) # (3, 1) print(round(7/3,2)) # 2.33 print(round(7/3)) # 2 print(round(3.32567,3)) # 3.326 print(pow(2,3)) # 两个参数为2**3次幂 print(pow(2,3,3)) # 三个参数为2**3次幂,对3取余。
repr:返回一个对象的string形式(原形毕露)。
# %r 原封不动的写出来 # name = 'taibai' # print('我叫%r'%name) # repr 原形毕露 print(repr('{"name":"alex"}')) print('{"name":"alex"}')
红色重点讲解:abs() enumerate() filter() map() max() min() open() range() print() len() list() dict() str() float() reversed() set() sorted() sum() tuple() type() zip() dir()
print() 屏幕输出。
''' 源码分析 def print(self, *args, sep=' ', end='\n', file=None): # known special case of print """ print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) file: 默认是输出到屏幕,若是设置为文件句柄,输出到文件 sep: 打印多个值之间的分隔符,默认为空格 end: 每一次打印的结尾,默认为换行符 flush: 当即把内容输出到流文件,不做缓存 """ ''' print(111,222,333,sep='*') # 111*222*333 print(111,end='') print(222) #两行的结果 111222 f = open('log','w',encoding='utf-8') print('写入文件',fle=f,flush=True)
int():pass
str():pass
bool():pass
set(): pass
list() 将一个可迭代对象转换成列表,pass
tuple() 将一个可迭代对象转换成元组,pass
dict() 经过相应的方式建立字典,pass
l1 = list('abcd') print(l1) # ['a', 'b', 'c', 'd'] tu1 = tuple('abcd') print(tu1) # ('a', 'b', 'c', 'd')
abs() 返回绝对值
i = -5 print(abs(i)) # 5
sum() 求和
print(sum([1,2,3]))# 6 print(sum((1,2,3),100))# 106
min() 求最小值
print(min([1,2,3])) # 返回此序列最小值 ret = min([1,2,-5,],key=abs) # 按照绝对值的大小,返回此序列最小值 print(ret) # 加key是能够加函数名,min自动会获取传入函数中的参数的每一个元素,而后经过你设定的返回值比较大小,返回最小的传入的那个参数。 print(min(1,2,-5,6,-3,key=lambda x:abs(x))) # 能够设置不少参数比较大小 dic = {'a':3,'b':2,'c':1} print(min(dic,key=lambda x:dic[x])) # x为dic的key,lambda的返回值(即dic的值进行比较)返回最小的值对应的键 # 输出的结果为: # 1 # 1 # 1 # c
max() 最大值与最小值用法相同。
reversed() 将一个序列翻转, 返回翻转序列的迭代器 reversed 示例:
l = reversed('你好') # l 获取到的是一个生成器 print(list(l)) print('__next__' in dir(l)) ret = reversed([1, 4, 3, 7, 9]) print(list(ret)) # [9, 7, 3, 4, 1] # 输出的结果为: # ['好', '你'] # True # [9, 7, 3, 4, 1]
bytes() 把字符串转换成bytes类型
s = '你好太白' bs = s.encode('utf-8') print(bs) # 结果:b'\xe4\xbd\xa0\xe5\xa5\xbd\xe6\xad\xa6\xe5\xa4\xa7' s1 = bs.decode('utf-8') print(s1) # 结果: 你好太白 s = '你好' bs = bytes(s,encoding='utf-8') print(bs) # 将字符串转换成字节 bs1 = str(bs,encoding='utf-8') print(bs1) # 将字节转换成字符串
zip() 拉链方法。函数用于将可迭代的对象做为参数,将对象中对应的元素打包成一个个元组,
而后返回由这些元祖组成的内容,若是各个迭代器的元素个数不一致,则按照长度最短的返回,
lst1 = [1,2,3] lst2 = ['a','b','c','d'] lst3 = (11,12,13,14,15) for i in zip(lst1,lst2,lst3): print(i) 结果: (1, 'a', 11) (2, 'b', 12) (3, 'c', 13)
sorted排序函数
语法:sorted(iterable,key=None,reverse=False) iterable : 可迭代对象 key: 排序规则(排序函数),在sorted内部会将可迭代对象中的每个元素传递给这个函数的参数.根据函数运算的结果进行排序 reverse :是不是倒叙,True 倒叙 False 正序 lst = [1,3,2,5,4] lst2 = sorted(lst) print(lst) #原列表不会改变 print(lst2) #返回的新列表是通过排序的 lst3 = sorted(lst,reverse=True) print(lst3) #倒叙 结果: [1, 3, 2, 5, 4] [1, 2, 3, 4, 5] [5, 4, 3, 2, 1] 字典使用sorted排序 dic = {1:'a',3:'c',2:'b'} print(sorted(dic)) # 字典排序返回的就是排序后的key 结果: [1,2,3] 和函数组合使用 # 定义一个列表,而后根据一元素的长度排序 lst = ['天龙八部','西游记','红楼梦','三国演义'] # 计算字符串的长度 def func(s): return len(s) print(sorted(lst,key=func)) # 结果: # ['西游记', '红楼梦', '天龙八部', '三国演义'] 和lambda组合使用 lst = ['天龙八部','西游记','红楼梦','三国演义'] print(sorted(lst,key=lambda s:len(s))) 结果: ['西游记', '红楼梦', '天龙八部', '三国演义'] lst = [{'id':1,'name':'alex','age':18}, {'id':2,'name':'wusir','age':17}, {'id':3,'name':'taibai','age':16},] # 按照年龄对学生信息进行排序 print(sorted(lst,key=lambda e:e['age'])) 结果: [{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}]
filter筛选过滤
语法: filter(function,iterable) function: 用来筛选的函数,在filter中会自动的把iterable中的元素传递给function,而后根据function返回的True或者False来判断是否保留此项数据 iterable:可迭代对象 lst = [{'id':1,'name':'alex','age':18}, {'id':1,'name':'wusir','age':17}, {'id':1,'name':'taibai','age':16},] ls = filter(lambda e:e['age'] > 16,lst) print(list(ls)) 结果: [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 1, 'name': 'wusir', 'age': 17}]
map
映射函数 语法: map(function,iterable) 能够对可迭代对象中的每个元素进映射,分别取执行function 计算列表中每一个元素的平方,返回新列表 lst = [1,2,3,4,5] def func(s): return s*s mp = map(func,lst) print(mp) print(list(mp)) 改写成lambda lst = [1,2,3,4,5] print(list(map(lambda s:s*s,lst))) 计算两个列表中相同位置的数据的和 lst1 = [1, 2, 3, 4, 5] lst2 = [2, 4, 6, 8, 10] print(list(map(lambda x, y: x+y, lst1, lst2))) 结果: [3, 6, 9, 12, 15]
reduce
from functools import reduce def func(x,y): return x + y # reduce 的使用方式: # reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行 ret = reduce(func,[3,4,5,6,7]) print(ret) # 结果 25 reduce的做用是先把列表中的前俩个元素取出计算出一个值而后临时保存着, 接下来用这个临时保存的值和列表中第三个元素进行计算,求出一个新的值将最开始 临时保存的值覆盖掉,而后在用这个新的临时值和列表中第四个元素计算.依次类推 注意:咱们放进去的可迭代对象没有更改 以上这个例子咱们使用sum就能够彻底的实现了.我如今有[1,2,3,4]想让列表中的数变成1234,就要用到reduce了. 普通函数版 from functools import reduce def func(x,y): return x * 10 + y # 第一次的时候 x是1 y是2 x乘以10就是10,而后加上y也就是2最终结果是12而后临时存储起来了 # 第二次的时候x是临时存储的值12 x乘以10就是 120 而后加上y也就是3最终结果是123临时存储起来了 # 第三次的时候x是临时存储的值123 x乘以10就是 1230 而后加上y也就是4最终结果是1234而后返回了 l = reduce(func,[1,2,3,4]) print(l) 匿名函数版 l = reduce(lambda x,y:x*10+y,[1,2,3,4]) print(l) 在Python2.x版本中recude是直接 import就能够的, Python3.x版本中须要从functools这个包中导入 龟叔本打算将 lambda 和 reduce 都从全局名字空间都移除, 舆论说龟叔不喜欢lambda 和 reduce 最后lambda没删除是由于和一我的写信写了好多封,进行交流而后把lambda保住了.
蓝色将来会讲: classmethod() delattr() getattr() hasattr() issubclass() isinstance() object() property() setattr() staticmethod() super()