Python基础—内置函数和匿名函数
一、前引
我们之前学过函数的知识,知道函数的调用方式:
函数名()
然后函数在调用之前需要定义,定以后我们就可以使用了,但是有没有发现有些恨特别呢?
比如说print(),我们用的很频繁的一个函数,打印内容,我们再使用这个函数的时候,好像我们也没有定义这个函数啊,为什么就能直接拿来用了呢?
诸如此类的函数还有很多,如len()、input()等等
其实这些函数就是python中的内置函数,python环境中已经为我们定义好的一些完成特定功能的函数,在python环境的任何地方我们可以直接调用。
那这些内置函数到底有多少个呢?今天就来数一数.
二、内置函数
接下来,我们就一起来看看python里的内置函数。截止到python版本3.6.2,现在python一共为我们提供了68个内置函数。它们就是python提供给你直接可以拿来使用的所有函数。这些函数有些我们已经用过了,有些我们还没用到过,还有一些是被封印了,必须等我们学了新知识才能解开封印的。那今天我们就一起来认识一下python的内置函数。这么多函数,我们该从何学起呢?
上面就是内置函数的表格,68个内置函数堵在这里,下面我们按照功能的类别归类成以下6大类,依次来学习。
1.作用域相关
基于字典的方式获取局部变量和全局变量
globals(): 全局变量的字典
locals(): 获取执行本方法所在命名空间内的局部变量的字典
locals(): 打印局部变量,以字典形式返回,可以使用get方法
vars(): 如果没有参数,和locals()一样,返回本地变量名和值,放在字典中,如果有参数,则是查看某一个对象的所有方法,放在字典里面。
2.其他:
字符串类型代码的执行
eval():将字符串类型的代码去掉引号并执行,不推荐使用
exec():将字符串类型的代码去掉引号后并执行,eval升级版,不推荐使用
code = ''' import os print(os.path.abspath('.')) ''' code = ''' print(123) a = 20 print(a) ''' a = 10 exec(code,{'print':print},) print(a)
compile:将字符串类型的代码编译。代码对象能够通过exec语句来执行或者eval()进行求值。
参数说明:
1. 参数source:字符串或者AST(Abstract Syntax Trees)对象。即需要动态执行的代码段。
2. 参数 filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。当传入了source参数时,filename参数传入空字符即可。
3. 参数model:指定编译代码的种类,可以指定为 ‘exec’,’eval’,’single’。当source中包含流程语句时,model应指定为‘exec’;当source中只包含一个简单的求值表达式,model应指定为‘eval’;当source中包含了交互式命令语句,model应指定为'single'。
>>> #流程语句使用exec >>> code1 = 'for i in range(0,10): print (i)' >>> compile1 = compile(code1,'','exec') >>> exec (compile1) 3 7 >>> #简单求值表达式用eval >>> code2 = '1 + 2 + 3 + 4' >>> compile2 = compile(code2,'','eval') >>> eval(compile2) >>> #交互语句用single >>> code3 = 'name = input("please input your name:")' >>> compile3 = compile(code3,'','single') >>> name #执行前name变量不存在 Traceback (most recent call last): File "<pyshell#29>", line 1, in <module> name NameError: name 'name' is not defined >>> exec(compile3) #执行时显示交互命令,提示输入 please input your name:'pythoner' >>> name #执行后name变量有值 "'pythoner'"
输入输出相关
input():获取用户输入
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源码剖析
import time for i in range(0,101,2): time.sleep(0.1) char_num = i//2 #打印多少个'*' per_str = '\r%s%% : %s\n' % (i, '*' * char_num) if i == 100 else '\r%s%% : %s'%(i,'*'*char_num) print(per_str,end='', flush=True) #小越越 : \r 可以把光标移动到行首但不换行 打印进度条
数据类型相关:
type(a):返回变量a的数据类型
内存相关:
id(a):返回参数a的内存地址
hash(a):a是参数,返回一个可hash变量的哈希值,不可hash的变量会报错
hash函数会根据一个内部的算法对当前可hash变量进行处理,返回一个int数字。
*每一次执行程序,内容相同的变量hash值在这一次执行过程中不会发生改变。
t = (1,2,3) l = [1,2,3] print(hash(t)) #可hash print(hash(l)) #会报错 ''' 结果: TypeError: unhashable type: 'list' ''' hash实例
文件操作相关
open():打开一个文件,返回一个文件操作符(文件句柄)
模块操作相关
__import__:导入一个模块
# 第一种直接导入 import time # 第二种导入字符串名字 os = __import__('os') print(os.path.abspath('.')) # 实际是通过sys模块找到'os'文件的路径,再导入使用
help(): 在控制台执行help()进入帮助模式,查看任意变量或者变量类型的有关操作
调用相关
callable(a): a是参数,查看这个参数是否可调用
如果a是一个函数名,则返回True
def func():pass print(callable(func)) #参数是函数名,可调用,返回True print(callable(123)) #参数是数字,不可调用,返回False
dir(): 默认查看全局空间内的属性,也可以接受一个参数查看这个参数内的方法或变量
print(dir(list)) #查看列表的内置方法 print(dir(int)) #查看整数的内置方法
3.数字相关
数字——数据类型相关:bool, int, float, complex
数字——进制转换:bin, oct, hex
数字——数学运算:abs, divmod, min, max, sum, round, pow
min和max高级用法
''' max比较字典类型的大小 ''' l = [1, 3, 100, -1, 2] print(max(l)) dic = {'age1': 18, 'age2': 12} print(max(dic)) # 比较的是字典的key print(max(dic.values())) # 比较的是字典的值,但是不是对应那个键 # 结合zip函数比较 print(max(zip(dic.values(), dic.keys()))) # 比较字典的值,并显示对应的键
''' 最终的使用方法。 ''' people = [ {'name': 'alex', 'age': 1000}, {'name': 'wupeiqi', 'age': 10000}, {'name': 'alex', 'age': 9000}, {'name': 'alex', 'age': 18}, ] print(max(people, key=lambda dic:dic['age'])) # max()对可迭代对象的每一个元素比较,key接收元素的获取函数(匿名函数) # min()和max()一样。
4.数据结构相关
序列——列表与元组相关:强转类型:list和tuple
序列——字符串相关:str, format, bytes, bytearray, memoryview, ord, chr, ascii, repr
format(str,格式化范式):格式化函数,
# format('a','>10') # 格式化字符a的输出 # format(12,'08b')
bytes():将字符根据编码方式转化成对应编码方式的字节
bytes():将字符根据编码方式转化成对应编码方式的字节
chr():返回数字序号在Ascii中对应的字符,65-->A, 97-->a, 122-->z
ord():返回字符在Ascii中对应的数字序号
ascii():判断内容是否ascii字符集中,在的话返回,不在返回\u....一堆数字
repr():显示的原本的数据,没有任何处理
ret = bytearray('alex',encoding='utf-8') print(id(ret)) print(ret[0]) ret[0] = 65 print(ret) print(id(ret))
ret = memoryview(bytes('你好',encoding='utf-8')) print(len(ret)) print(bytes(ret[:3]).decode('utf-8')) print(bytes(ret[3:]).decode('utf-8'))
数据集合——字典和集合:dict, set, frozenset
数据集合:
len(): 计算可迭代类型的长度
enumerate(iter[,x]): 枚举,遍历可迭代对象,返回每个对象并为其加上序号,x为序号起始数,默认为0
li = [1,2,3,4] for index,element in (li,0): print(index,element)
all(): 判断可迭代类型中的所有元素是否都为真,是返回True,任意为假返回false
any(): 判断可迭代类型中元素是否有一个为真,是返回True,全为假返回false
zip(拉链):跟拉链一样,将两个可迭代类型中的元素一一对应,包裹在元组里,放在列表中
print(list(zip(('q', 'b', 'c'), (1, 2, 3)))) # [('q', 1), ('b', 2), ('c', 3)] print(list(zip(('abcd'), ('123')))) # [('a', '1'), ('b', '2'), ('c', '3')] # 可以拼接多个可迭代对象。不止两个
slice(): 切片
l = 'hello' s1 = slice(3, 5) # l[s1] = l[3, 5] s2 = slice(1, 4, 2) # l[s2] = l[1, 4, 2] print(l[s1]) print(l[s2])
sorted方法
给列表排序的两个方法(前提,列表中元素可比较)
方法1.用List的成员函数sort进行排序,在本地进行排序,不返回副本
方法2.用built-in函数sorted进行排序(从2.4开始),返回副本,原始输入不变
参数说明:
iterable:是可迭代类型;
key:传入一个函数名,函数的参数是可迭代类型中的每一项,根据函数的返回值大小排序;
reverse:排序规则. reverse = True 降序 或者 reverse = False 升序,有默认值。
返回值:有序列表
people = [ {'name': 'alex', 'age': 1000}, {'name': 'wupeiqi', 'age': 10000}, {'name': 'alex', 'age': 9000}, {'name': 'alex', 'age': 18}, ] print(sorted(people, key=lambda dic:dic['age']))
5.匿名函数
匿名函数:为了解决功能简单的需求而设计的一句话函数
#这段代码 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = lambda n:n**n print(calc(10))
上面是我们对calc这个匿名函数的分析,下面给出了一个关于匿名函数格式的说明
函数名 = lambda 参数 :返回值 #参数可以有多个,用逗号隔开 #匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值 #返回值和正常的函数一样可以是任意数据类型
我们可以看出,匿名函数并不是真的不能有名字。
匿名函数的调用和正常的调用也没有什么分别。
除此之外,匿名函数也不是浪得虚名,它真的可以匿名。在和其他功能函数合作的时候
l=[3,2,100,999,213,1111,31121,333] print(max(l)) dic={'k1':10,'k2':100,'k3':30} print(max(dic)) print(dic[max(dic,key=lambda k:dic[k])])
6.map、filter、reduce函数的用法
map(func, iter)
映射函数:
创建一个迭代器,使用可迭代对象的每个参数计算函数并返回。当最短的可迭代用尽时停止。
map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
注:map函数内部会的机制会自动遍历传进来的可迭代对象。然后对遍历后的元素指定比较规则。(这里理解很重要)
num = [1, 2, 4, 5, 2, 8] # 第一步需求,将列表中的数字全部平方 # new_li = [] # def square(array): # for i in array: # new_li.append(i**2) # return new_li # # print(square(num)) # 第二步需求,将列表中的数字全部减一 # new_li = [] # def reduce(array): # for i in array: # new_li.append(i-1) # return new_li # # print(reduce(num)) # 当需求过于巨大,需要一个一个实现,此时我们可以定义一个可以使用不同函数作用的函数 def square(num): return num**2 def reduce(num): return num - 1 def map_test(func, array): ret = [] for i in array: res = func(i) ret.append(res) return ret print(map_test(square, num)) print(map_test(reduce, num))
# map函数使用 li = [1, 2, 3, 4, 5] def square(num): return num**2 # 传入有名函数 map(square, li) # 传入匿名函数 map(lambda x:x**2, li) # 结果 [1, 4, 9, 16, 25]
filter(func, iter): 过滤函数
返回一个迭代器,产生函数(item)为true的iterable项。如果function为None,则返回结果为true的项。
# 有个需求,需要过滤movie_people中sb的人 movie_people = ['sb_alex', 'wupeiqi_sb', 'linhaifeng', 'sb_yuanhao'] ret = [] for p in movie_people: if not p.startswith('sb'): ret.append(p) print(ret) # # ['linhaifeng'] # 封装成函数,过滤元素 def filter_test(array): ret = [] for p in array: if not p.startswith('sb'): ret.append(p) return ret print(filter_test(movie_people)) # ['wupeiqi_sb', 'linhaifeng'] # 需求更改,去除以sb结尾 # 所以不能将逻辑写死 def sb_show(n): return n.endswith('sb') def filter_test(func, array): ret = [] for p in array: if not func(p): ret.append(p) return ret res = filter_test(sb_show, movie_people) print(res) # ['sb_alex', 'linhaifeng', 'sb_yuanhao'] res = filter_test(lambda n:n.endswith('sb'), movie_people) print(res) # ['sb_alex', 'linhaifeng', 'sb_yuanhao']
# 请利用filter()过滤出1~100中平方根是整数的数,即结果应该是: # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] import math def is_sqr(x): return math.sqrt(x) % 1 == 0 print(list(filter(is_sqr, range(1, 101)))) 匿名函数写法: print(list(filter(lambda x:math.sqrt(x)%1==0,range(1,101))))
reduce(func, iter)
返回一个结果,将连个参数的函数累积到序列的项上,从做到右,以便将序列减少到单个值
- 为了快速的进行累加,连乘的计算,使代码更简洁
from functools import reduce
# reduce的推导过程 numbers = [1, 2, 3, 100] # 需求1,将列表中元素累乘 res = 1 for num in numbers: res *= num print(res) # 需求2,封装成函数 def reduce_test(array): res = 1 for num in array: res *= num return res print(reduce_test(numbers)) # 需求3,要求功能可变,并置顶初始参数 def multi(x, y): return x*y # 等价于 lambda x,y:x*y def reduce_test(func, numbers, init=None): if init is None: res = 1 else: res = init for num in numbers: res = func(res, num) return res print(reduce_test(lambda x,y:x*y, numbers, 10))
# reduce的使用 from functools import reduce li = [1,2,3,4,5] print(reduce(lambda x,y:x*10+y, li)) ''' 过程: x=1,y=2 >>> x*10+y = 1*10+2 = 12, 并将12赋值给x,y取值3 >>> x*10+y = 12*10+3 = 123, 并将123赋值给x,y取值4 依次下去,最后-->12345 '''