使用函数的目的: 可读性强,复用性强
# 函数签名: 函数签名值得是函数名,参数个数和类型以及返回值类型
定义函数:
def 函数名: 功能 return "返回值"
return 返回值的几种情况详解
没有返回值的情况:返回None
1.不写 return;
2.只写return;(结束一个函数的继续);
3.return None;不常用;
返回一个值:
1.可以返回任何数据类型;
2.只要返回就可以接受到;
3.如果在一个程序中有多个return,那么只执行第一个;
返回多个值:
1.多个返回值用多个变量接受:有多少返回值就用多少个变量接受;
2.多个返回值用一个变量接受:得到的是一个元祖;
函数参数的几种情况详解
没有参数:
定义函数和调用函数时括号里都不写内容;
有一个参数:
传什么就是什么;
有多个参数:
1.站在实参的角度上:
1.按照位置传参;
2.按照关键字传参;
3.混着使用(必须先按着位置传参,在按照关键字传参;不能给一个变量传多个值);
2.站在形参的角度上:
1.位置参数:必须传,且有几个参数传几个值;
2.默认参数:可以不传,如果不传就是驶入默认的参数,如果传入就使用传入的参数;在形参中 --- '形参'='默认值';
***默认参数的陷阱:如果默认参数的值是一个可变数据类型,那么每一次调用函数的时候,如果不传值就公用这个数据类型的资源;默认参数可变数据类型只要不重新赋值,list指向的地址永远不变,切记切记!
***顺序:必须先定义位置参数,*args,后再定义默认参数,再写**kwargs;
动态参数解释
可以接受任意个参数
1.*args;# *args(args可以任意变换 习惯使用args) # 接受的是按照位置传参的值,组织成一个元祖;## 站在实参的角度上,给一个元祖加上*,就是将这个元祖按照顺序打散;
2.**kwargs;# **kwargs(kwargs可以任意变换 习惯使用kwargs) # 接受的是按照关键字传参的值,组织成一个字典;## 站在实参的角度上,给一个字典加上**,就是将这个字典按照顺序打散;
函数的进阶
命名空间
一个函数具有——python解释器
#1 内置命名空间
# python解释器一启动就可以使用的名字存储在内置命名空间中;#内置的函数在启动解释器的时候被加载进内存里;
#2 全局命名空间——我们写入的代码而不是函数中的代码
# 是在程序从上到下被执行的过程中依次加载进内存;#放置了我们设置的而所有变量名和函数名;
#3 局部命名空间——函数
# 就是函数内部定义的名字;#当调用函数的时候,才会产生这个名字空间,随着函数执行的结束,这个命名空间就消失了;
***依赖倒置关系:内置》》》全局》》》同一个局部(多个局部名字不共享)
在局部:可以使用内置,也可以使用全局的名字;
在全局:可以使用内置,不能使用局部的名字;
在内置:不能使用全局,也不能使用局部的名字;
# 在正常情况下,直接使用内置的名字;
# 当我们在全局定义了和内置名字空间同名的名字时,会使用全局的名字;
# 当使用名字本空间有的情况下,不向上层调用;
# 如果使用名字本空间没有的情况下,找上一层调用,如果内置空间都没有,报错;
# 多个函数应该拥有多个独立的局部名字空间,不互相共享;
作用域:
全局作用域:
# 作用在全局——(内置和全局名字空间中的名字都属于全局作用域);
# ***globalse();查看全局作用域的名称;
局部作用域:
# 作用在局部——函数(局部名字空间中的名字属于局部作用域);
# 对于不可变数据类型 在局部可是查看全局作用域中的变量;不能直接修改,如果需要修改,需要在程序的一开始添加global声明;
# ***locals();根据locals的位置输出此域的名称;当前可用的变量;
***global;#如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效;
***nonlocal;#只能用于局部变量,找上层中离当前函数最近一层的局部变量;声明了nonlacal的内部函数的变量修改会影响到离当前函数最近的一层的局部变量;
函数的本质:函数名就是内存地址
1.函数名可以赋值;
2.函数名可以作为容器类型的容器;
3.函数名可以作为函数的参数;函数名可以作为函数的返回值;
符合以上三个条件:第一类对象
闭包:
嵌套函数,内部函数调用外部函数的变量
# 闭包的意义
保证变量不被侵害
让闭包索使用的变量常驻内存
# 可以通过函数name.__closure__ 只要元祖不为空,则函数为闭包函数
三元运算:
变量=条件返回True的结果 if 条件 else 条件返回Falsh的结果;
装饰器
装饰器的形成过程:
最简单的装饰器>>>有返回值>>>有一个参数>>>万能参数;
装饰器的作用:
# 不想修改函数的调用方式,但还想再原来的函数前后添加功能
装饰器原则:开放封闭原则
# 开放:对扩展是开放的
# 封闭:对修改是封闭的
语法糖
1.# @装饰器函数名; #优先执行@后的内容 执行完成后与前面的@拼接为装饰器
2.# 紧贴着被装饰的函数;
装饰器的固定模式:
def wrapper(f): #(warpper 函数名可变 更换过后需要跟后面语法糖@装饰器名称一样#f是被装饰函数) def inner(*args,**kwargs): #'被装饰之前要做的事' ret = f(*args,**kwargs) #装饰器 ret接受inner的返回值 就是被装饰函数的返回值 #'被装饰之后要做的事' return ret return inner
# @wrapper #语法糖 @装饰器函数名
# 被装饰的函数 定义函数时
函数名._name_ ;#查看字符串格式的函数名
函数名._doc_ ;#查看这个函数的注释 doc-document
补充:
from functools import wraps (别人已经写好的装饰器)*************
@wraps(inner)********
# 装饰器传参相当于三层闭包 在最外层接受装饰器传入的参数
定义自己装饰器时使用 ---inner前使用 在闭包wrapper中嵌套的inner函数之前使用
不会丢掉原有的名字 和备注信息
迭代器
迭代器的意义
# 让不同的数据类型拥有相同的遍历方式
迭代器的好处
# 从容器类型中一个一个的取值,会把所有的值都取到,且一个值只能取一次。
# 迭代器可以节省空间(未释放前)
可迭代协议
可迭代对象,例如容器,需要有一个__iter__方法,该方法返回一个迭代器对象;
迭代器协议
内部含有和__iter__和__next__方法的就是迭代器;
可迭代的.__iter__()方法就可以得到一个迭代器;
迭代器中的__next__()方法可以一个一个的获取值;
for循环
# 只有是可迭代对象的时候才能使用for;
# 当我们遇到一个新的变量,不确定能不能使用for循环的时候,判断它是否可迭代;
***补充:
可迭代对象 以及生成器都可以转化为迭代器 iter(xxx) 转化完后可以使用__next__()方法
***补充:
from itertools import chain chain() # 将可迭代数据连接起来 例如: a = [1, 2, 3, 4] b = ['x', 'y', 'z'] for x in chain(a, b): print(x) # 输出 1 2 3 4 x y z
生成器
***生成器函数:
只要含有 yield 关键字的函数都是生成器函数;#yield 与 return不可共用,且需要写在函数内部;
yield返回的是一个生成器;
从生成器中取值的几个方法:
# __next__()
# for循环
# 数据类型的强制转换(将生成器里的值全部取出来放到内存中,占用内存)
send()
# send() 获取下一个值得效果和next基本一致;#只是在获取下一个值得时候,给上一个yield的位置传递一个数据;
使用send()的注意事项:
# 第一次使用生成器的时候 时使用__next__()获取下一个值;
# 最后一个yield不能接收外部的值;
****yield from
# 用在生成器里,从一个容器类型里面取得值直接返回 接收到的是分开一个一个的值:例如;
def ceshi(): a='abcdef' yield from a g=ceshi() for i in g: print(i) # 结果为 a / b / c /d /e /f (/为回车)
列表推导式:(各种推导式)
list=[i for i in range(10)]#把i放到列表中;(放入的 i 可以操作)
list=[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型 ];(遍历)
完整的列表推导式:
list=[满足条件的元素相关操作 for 元素 in 可迭代数据类型 if 元素的相关条件];# 满足相关条件执行元素操作;(筛选)
生成器表达式:
g=(每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型)
g=(i for i in range(10))#g是一个生成器;
for i in g;print(i) ;将生成器里的值取出来
解包
如果列表中有3个元素,那么刚好可以分配给3个变量。除了列表对象可以解包之外,任何可迭代对象都支持解包,可迭代对象包括元组、字典、集合、字符串等;
内置函数
python中的内建函数
callable();#可以检查一个对象是否是可调用的;
dir();dir() 是一个内置函数,用于列出对象的所有属性及方法。在 Python 中,一切皆对象,模块也不例外,所以模块也可以使用 dir();
help();# 用于查看函数或模块用途的详细说明;比dir()更加详细,可以查看到内置的注释之类;
import;#用于动态加载类和函数;# import 函数名 + 别名;# 重命名
open();#文件的操作;
id();#(内容,打印出内存地址);
hash();# 哈希;用于获取取一个对象(字符串或者数值等)的哈希值;
input();#函数接受一个标准输入数据,返回为 string 类型。
print(); # print() 方法用于打印输出,最常见的一个函数;关键字参数(sep -- 用来间隔多个对象,默认值是一个空格。 end -- 用来设定以什么结尾。默认值是换行符 ,我们可以换成其他字符串。file -- 要写入的文件对象,flush--输入布尔值,True立即把内容输出到流文件,不作缓存)
eval();# eval() 函数用来执行一个字符串表达式,并返回表达式的值;# 简单计算类;
exec();# exec() 将字符串类型的代码执行,没有返回值;# 流程类;
single();#交互语句使用single
compile();compile() 函数将一个字符串编译为字节代码,代码对象能够通过exec语句来执行或者eval()进行求值;参数 source--对象 filename--如果不是从文件读传入'' model--指定编码种类例如evec,eval,single
***complex;复数 bytes();
bytes 函数返回一个新的 bytes 对象,该对象是一个 0 <= x < 256 区间内的整数不可变序列。它是 bytearray 的不可变版本。(***网络编程 只能传二进制 照片和视频,Html网页爬取到的也是bytes编码:
str>>>bytes***
str.encode();# encode编码 str.encode('设置编码方式utf-8;utf-16;gbk...')
bytes>>>str***
bytes.decode()#decode编码 bytes.decode('设置编码方式utf-8;utf-16;gbk...') )
参数:source--对象
如果 source 为整数,则返回一个长度为 source 的初始化数组;
如果 source 为字符串,则按照指定的 encoding 将字符串转换为字节序列;
如果 source 为可迭代类型,则元素必须为[0 ,255] 中的整数;
如果 source 为与 buffer 接口一致的对象,则此对象也可以被用于初始化 bytearray。
如果没有输入任何参数,默认就是初始化数组为0个元素。
bytearray();# bytearray() 方法返回一个新字节数组。这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256。(优点:修改的时候节省内存 缺点:只能通过字符编码修改)
memoryview();# memoryview() 函数返回给定参数的内存查看对象(Momory view)。所谓内存查看对象,是指对支持缓冲区协议的数据进行包装,在不需要复制对象基础上Python代码访问。
ord();# ord() 函数是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常 *****(字符转化为Unicode编码 );
chr();# chr() 用一个范围在 range(256)内的(就是0~255)整数作参数,返回一个对应的字符;(从Unicode编码转化回字符);
ascll();# 只要是ascll码中的内容,就打印出来;不是的话转化为u
repr();# repr() 函数将对象转化为供解释器读取的形式;(repr()保留原格式---%r内部调用的就是repr());(%r打印时能够重现它所代表的对象(rper() unambiguously recreate the object it represents));
forzenset();#frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素;
重要的
len();# len() 方法返回对象(字符、列表、元组等)长度或项目个数;
enumerate();#enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中;
all();all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False;元素除了是 0、空、FALSE 外都算 TRUE;
ang();any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。元素除了是 0、空、FALSE 外都算 TRUE;
very重要
zip();zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个迭代器并返还迭代器。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同;
sorted();sorted() 函数对所有可迭代的对象进行排序操作。(可以传入key)
sort 与 sorted 区别:
1.sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
2.list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
filter();filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到迭代器中。(可以传入key)
map();map() 会根据提供的函数对指定序列做映射。第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回一个迭代器。(可以传入key);
filter() 与 map()
filter():
1.执行了filter 之后的结果集合 小于等于执行之前的个数;
2.filter只管筛选,不会改变原来的值;
map():
1.执行前后元素个数不变;
2.值可能发生改变;
匿名函数
************函数名=lambda 参数 : 返回值
可以与 min max filter map sorted 组合使用
例如
my_list = [3,5,-4,-1,0,-2,-6] sorted(my_list, key=lambda x: abs(x)) # 在遍历my_list 将其元素传入lambda中进行处理
补充:
python 基础模块 operator
# sorted排序非lambda配合包
# perator模块中另两个非常重要的方法是itemgetter和attrgetter。
这两个函数可以从一个序列或者对象中去获取指定的元素或属性值。
例如:attrgetter
class Ob(): def __init__(name,age,birthday): self.name = name self.age = age self.birthday = birthday ob1 = Ob("xx1",20,datetime.date(1992,12,2)) ob2 = Ob("xx2",16,datetime.date(2000,10,20)) ob3 = Ob("xx3",25,datetime.date(1883,3,5)) objs = [ob1,ob2,ob3] sorted(objs,key=operator.attrgetter("age")) # 获取age属性进行排序 sorted(objs,key=operator.attrgetter("birthday.year")) # 获取birthday中的datetime下的year方法进行排序 # 内部通过反射获取对象属性 # itemgetter就是遍历字典等元素使用