函数基础
(一)python基础(三)主要分享的是包括如下几部分:
- 编码进阶
- id、is、小数据池
- 集合和深浅拷贝
- 文件操作
- 函数的初识
- 函数的进阶
(二)具体的分享内容如下:
1.编码的进阶
''' 编码进阶说明: 01 不能编码之间不能相互识别(ASCII码间可以相互转化) 02 字符串加载在内存中的,使用的编码方式为Unicode 03 将加载到内存中的字符串进行数据存储、数据传输时会涉及到编码的转换。主要是进行str和bytes类型的数据的转换。 04 bytes类型只有在传输和存储的数据的时候才会使用 ''' # 01 bytes数据类型:在数据传输、数据存储时会使用到。 # 001 英文字符的表现形式 # str: # 形式:s1 = 'Alex' # 内存的编码方式:Unicode # bytes # 形式;s1 = b'Alex' # 内存中的编码方式;费Unicode # 002 中文字符的表现形式 # str: # 形式:s1 = '中国' # 内存的编码方式:Unicode # bytes # 形式;s1 = b'\xe4\xb8\xad\xe5\x9b\xbd' # 内存中的编码方式;费Unicode # 02 字符串的编码与解码 # 001 str-->bytes 编码:encode() s1 = 'alex' b1 = s1.encode('utf-8') b2 = s1.encode('gbk') print(s1, type(s1)) print(b1, type(b1)) print(b2, type(b2)) # 002 bytes-->str 解码:decode() b1 = b'\xe4\xb8\xad\xe5\x9b\xbd' s1 = b1.decode('utf-8') print(s1)
2.id is 小数据池
''' 说明: 01 id 是判断数据对应的'内存地址',内存地址在python中只是一个标志作用,并不代表该数据在内存中的实际地址(需要在命令窗口下进行验证) 02 == 是判断两个数据对应的值是否相等 03 is 身份运算,判断的是数据的内存地址是否相同(需要子啊命令窗口下进行验证) 04 小数据 (1)作用:一方面是用来节省空间,另一方面是提高性能。 (2)小数据池是在内存中开辟了两个空间,即字符串空间和整型空间,当满足字符串的条件和整型的范围,则无论定义多少个元素都指向同意内存地址。 1)int: -5 至 256 范围。 2)str; 满足一定规则的字符串 ''' s1 = '马玉刚' s2 = '马玉刚' print(s1 == s2) # 判断值是否相等 print(id(s1)) # 判断值的内存地址
3.集合和深浅拷贝
''' 集合说明: 01 集合里面的元素必须是不可变的数据类型,集合本身是可变的数据类型。 02 集合是无序的,不重复的。 03 集合的两个作用。 01)列表去重 02)关系测试,交集、并集、差集 04 集合的for循环 ''' # 01 集合里的元素必须是不可变的类型。 print({(1, 2, 3), '马玉刚'}) print({[1, 2, 3], {'name': '马玉刚'}) # 列表和字典是不可hash的,所以不能作为集合的元素。 # 02 集合作用:列表去重 l1 = [1, 1, 2, 3, 4, 3, 2, 4, 5, 6] set1 = set(l1) # 将列表转换为集合 print(set1) l1 = list(set1) # 将集合转换为列表 print(l1) # 03 集合的作用:关系测试,包括但不限于如下:交集、并集、差集。 # 04 集合的for循环。 set1 = {'alex', 'WuSir', 'barry', '女神', } # 集合中最后一个逗号有和没有都是一样的, 都不会报错。 for i in set1: print(i) # 迭代输出:alex,WuSir,barry,女神 # 05 内置函数frozenset([iterable]):返回一个冻结的集合,即这个集合不能删除或者条件任何集合李的元素,主要作用是速度快。 set2 = frozenset({1, 2, 3, 4, 7, 6}) print(set2, type(set2)) # 不可变的数据类型 输出结果:frozenset({1, 2, 3, 4, 6, 7}) <class 'frozenset'> dic = {set2: 666} # 由于set2是不可变的类型,所以可以做字典的key print(dic) for i in set2: print(i) ''' 深浅copy说明: 01 赋值运算是指右侧数据在内存中开辟一个空间,如果两个变量由统一数据进行赋值,若数据改变,则两个变量的值同时都变。 02 浅copy:第一层开辟新的内存地址,但是从第二层乃至更深的层来说,共用的都是一个。 03 深copy:复制两个完全独立的数据(多少层都是独立的)。 ''' # 01 赋值运算是指右侧数据在内存中开辟一个空间,如果两个变量由统一数据进行赋值,若数据改变,则两个变量的值同时都变 l1 = ['alex', 'WuSir', 'barry', '女神', ] l2 = l1 # 赋值运算 l1.append('日天') print(l1) # ['alex', 'WuSir', 'barry', '女神', '日天'] print(l2) # ['alex', 'WuSir', 'barry', '女神', '日天'] # 02 浅copy:第一层开辟新的内存地址,但是从第二层乃至更深的层来说,共用的都是一个。 # 0201 第一层开辟了新的内存地址。 l1 = ['alex', 'WuSir', 'barry', '女神', ] l2 = l1.copy() l1.append('泰迪') print(l1, id(l1)) print(l2, id(l2)) # 0202 从第二层起,共用统一内存地址。 l1 = ['alex', 'WuSir', 'barry', [1, 2, 3]] l2 = l1.copy() l1[0] = 'SB' l1[-1].append('女神') print(l1, id(l1), id(l1[-1])) # ['SB', 'WuSir', 'barry', [1, 2, 3, '女神']] 35502472 35503496 print(l2, id(l2), id(l2[-1])) # ['alex', 'WuSir', 'barry', [1, 2, 3, '女神']] 35537032 35503496 # 03 深copy:复制两个完全独立的数据(多少层都是独立的),即形成两个新的数据相互不影响。 import copy # 导入系统内存方式。 l1 = ['alex', 'WuSir', 'barry', '女神', ] l2 = copy.deepcopy(l1) l1.append('泰迪') print(l1, id(l1)) # ['alex', 'WuSir', 'barry', '女神', '泰迪'] 42354888 print(l2, id(l2)) # ['alex', 'WuSir', 'barry', '女神'] 42355080 l1 = ['alex', 'WuSir', 'barry', [1, 2, 3]] l2 = copy.deepcopy(l1) l1[-1].append('女神') print(l1, id(l1), id(l1[-1])) # ['alex', 'WuSir', 'barry', [1, 2, 3, '女神']] 32655752 32655560 print(l2, id(l2), id(l2[-1])) # ['alex', 'WuSir', 'barry', [1, 2, 3]] 32657032 32656968
4.文件的操作
''' 文件操作说明: 00)文件操作的基本形式: f1 = open(r'd:\美女护士老师.txt', encoding='utf-8', mode='r') # 打开文件 content = f1.read() print(content, type(content)) f1.close() # 关闭文件 01 文件操作的3个关键要素。 01) open():内置函数,用于打开文件 02) f1:文件句柄形式包括 f1,fh,file_handle,f 03)f1.close():内置函数,用于关闭打开的文件,文件打开后必须手动关闭,否则会极大的消耗内存(with 情况除外。) 02 文件的操作:r 、r+、w、a 1)r :读文件,其中open()默认的mode = r,所以要是读文件的时候,可以默认不写。r模式下读有5种形式: a)read():全部读取。 b)read(n):按照 “字符”读取。 c)readline:按行进行读取。 d)readlines() 返回一个列表,列表中的每个元素是原文件的一行。 e) for循环。(***在工作过程中推荐使用for循环来进行读文件,这样可以极大的降低内存的消耗,提高性能) 2)r+:先读文件后写文件。 3)w :写文件。 a)没有文件创建文件写内容。 b)有文件先清空后写入。 4)a:文件的追加 a)没有文件创建文件写入内容。 b)有文件直接在后面追加。 03 with的可以同时打开多个文件。 04 文件改的操作步骤。 1)以读的模式打开文件 2)已写的模式打开一个新的文件 3)对原文件的内容进行修改,形成新的内容写入新文件 4)删除原文件 5)将新文件的文件名重命名为原文件的文件名 05 文件的其他操作 ''' # 01)相对路径和绝对路径 # 绝对路径:从C、D、E等盘开始的路径,比如'D:\马玉刚.txt' # 相对路径:当前的目录下,同一个文件夹下。 # 02)r模式下读的5种形式: # 第一种 read() 全部读取 f1 = open('马玉刚', encoding='utf-8') # encoding 指定文件的读取时使用的编码方式,与encode、decode无关。 content = f1.read() print(content, type(content)) f1.close() # 第二种 read(n) r:模式 按照 字符去读取 f1 = open('马玉刚', encoding='utf-8') content = f1.read(3) print(content) f1.close() # 第三种 readline() 按行读取,,输入几行即打印出几行。 f1 = open('马玉刚', encoding='utf-8') print(f1.readline().strip()) print(f1.readline().strip()) print(f1.readline().strip()) f1.close() print(666) # 第四种 readlines() 返回一个“列表”,列表中的每个元素是原文件的一行 f1 = open('马玉刚', encoding='utf-8') content = f1.readlines() print(content, type(content)) f1.close() # 第五种 for循环 f1 = open('马玉刚', encoding='utf-8') for line in f1: print(line.strip()) f1.close() # 03) r+先读后写(后追加) f1 = open('马玉刚', encoding='utf-8', mode='r+') content = f1.read() print(content) f1.write('666') f1.write('来了') print(f1.read()) f1.close() # 4) w 模式下文件的操作:(1)没有文件创建文件写入内容。(2)有文件先清空后写入。 f1 = open('log1', encoding='utf-8',mode='w') f1.write('(1)没有文件创建文件写入内容。(2)有文件先清空后写入。') f1.close() # 5)a 模式下的文件操作:(1)没有文件创建文件写入内容。(2)有文件直接在后面追加。 f1 = open('log1', encoding='utf-8',mode='a') f1.write('\n喇叭坏了 fuck') f1.close() # 6)文件的常用操作 # a) readable() :是否可读 # b) writable():是否可写 f1 = open('log1', encoding='utf-8',mode='w') f1.write('又好了....') if f1.readable(): print(f1.read()) print(f1.readable()) f1.close() # c) tell() 告诉你光标的位置(按照字节) f1 = open('马玉刚', encoding='utf-8') content = f1.read(3) print(f1.tell()) f1.close() # d) seek() 调整光标的位置(按照字节) f1 = open('马玉刚', encoding='utf-8') f1.seek(9) content = f1.read() print(content) f1.close() # 7) 文件的修改 # read() 占用内存 import os # 引用内置的函数 with open('alex美文', encoding='utf-8') as f1, \ # 如果是多行的话,可以用'\'来进行换行 open('alex美文.bak',encoding='utf-8',mode='w') as f2: old_content = f1.read() new_contenet = old_content.replace('alex', 'SB') f2.write(new_contenet) os.remove('alex美文') os.rename('alex美文.bak','alex美文') import os with open('alex美文', encoding='utf-8') as f1, \ open('alex美文.bak',encoding='utf-8',mode='w') as f2: for line in f1: new_line = line.replace('SB','alex') f2.write(new_line) os.remove('alex美文') os.rename('alex美文.bak','alex美文')
5.函数的初识
''' 整体说明: 01 面向过程编程和面向面向对象/函数编程的区别。 (1)面向过程编程(流水账),代码重复、可读性差。 (2)面向对象/函数编程的有点是代码可读性高。 02 函数:一个函数封装一个功能 (1)函数的定义的形式: def 函数名(): 函数体 (2)函数的执行者/调用者:函数名() # 注意只要是函数名+(),该函数即被调用,调用后才执行函数体,否则不执行函数 体的内容,函数体的内容执行完成通过return将返回值反馈给函数,完成以上全部操作后才算完成了函数的执行/调用的 过程。 (3)返回值return: a)函数中遇到return则中止函数。 b)返回值返回给函数的调用者。 c)返回值的3种形式。 1)return :返回值是None 2) return 单个值:返回单个值 3)return 多个值:返回的是有这个多个值组成的元祖 (4)函数的参数:形参、实参。 (5)函数的传参形式: a) 实参角度: 1)位置参数 : 从前至后 一一对应,如果不一一对应则进行报错。 2)关键字传参: 不用按照顺序,一一对应,如果不一一对应则进行报错。 3)混合传参: 位置参数一定在前面。 b)形参角度 1) 位置传参: 按照顺序,一一对应 2) 默认传参: 如果不传,则默认使用默认参数,传参则覆盖。 常用的会设置默认参数 3) 动态参数,也叫不定长传参,就是你需要传给函数的参数很多,不定个数,那这种情况下,你就用 *args,**kwargs接收,args是元祖形式,接收除去键值对以外的所有参数,kwargs接收的只是键值 对的参数,并保存在字典中。 (6)形参的顺序:位置参数,*args,默认参数,**kwargs ''' # 01 函数名(): 函数的执行者,调用者 def my_len(): l1 = [1, 2, 34, 55, 66] global c # 在局声明一个全局变量,定义后局部可以修改, c = 0 for i in l1: c += 1 return c # 将c返回给函数调用者 my_len() # 函数的执行者调用者 print(my_len()) print(c) # 02 返回值return: # 0201遇到return函数中止,return后的函数语句不执行。 def my_len(): print(111) # 111 print(222) # 222 return (1, 2, 3), [12, 4] print(333) # 遇到return后,函数中止,该结果不打印。 ret = my_len() print(ret, type(ret)) # ((1, 2, 3), [12, 4]) <class 'tuple'> # 0202 def my_len(): l1 = [1, 2, 34, 55, 66] c = 0 for i in l1: c += 1 return c print(my_len()) # 03 函数的传参:将实参赋值给形参,在函数体中执行之后将结果通过return返回。 l1 = [1, 2, 34, 55, 66] def my_len(s): # 形参 c = 0 for i in s: c += 1 return c print(my_len('fdskalfdsjflsdajf;lsa')) # 21 ret = my_len(l1) # 函数的执行者(实参) print(ret) # 5 # 04 实参角度 # 0401 位置参数:位置参数必须按照顺序,一对一,否则会报错,。 # 少一个实参,所以运行的时候报错。 def func1(a, b, c): print(a + b) func1('alex', 'wusir') # 实参个数和形参个数一一对应,所以,正常运行。 def func1(a, b): # if a > b: # return a # else: # return b return a if a > b else b def func1(a, b): return a if a > b else b # 三元运算,是对if else的优化。 print(func1(100, 200)) # 0402 关键字传参:参数一一对应,但是无顺序要求。 def func2(age,name): print(name,age) func2(name='alex', age=73) # 0403混合传参 def func3(a, b, c, name): print(a, b, c, name) func3(1, 2, 3, name='alex') # 0404 return说明 # 不带return def trans_para(a, b, *args, name1='张三', **kwargs): print(a) print(b) print(name1) print(args, type(args)) print(kwargs, type(kwargs)) trans_para("jinxin", 12, [1, 2, 3, 4], [3, 4, ], (1, 4, 7), {"a": "123", "c": 456}, name1='李苹', country="马玉刚", name='alex', ) # 函数调用者,函数执行者 # # # 带有return def trans_para(a, b, *args, name1='张三', **kwargs): return a, b, name1, args, kwargs print(trans_para("jinxin", 12, [1, 2, 3, 4], [3, 4, ], (1, 4, 7), {"a": "123", "c": 456}, name1='李苹', country="马玉刚", name='alex', )) # ('jinxin', 12, '李苹', ([1, 2, 3, 4], [3, 4], (1, 4, 7), {'a': '123', 'c': 456}), {'country': '马玉刚', 'name': 'alex'}) # 05 形参角度 # 0501 位置参数 def func1(a,b,c,d): print(a,b,c) func1(1,2,3) # 0502 默认参数 : def func2(name,age,sex='男'): print(name,age,sex) func2('alex',73,sex='女') def wfile(name,age,sex='男'): with open('登记表',encoding='utf-8',mode='a') as f1: f1.write('{}|{}|{}\n'.format(name,age,sex)) while 1: name = input('姓名(输入Q/q退出):') if name.upper() == 'Q':break age = input('年龄:') if name.startswith('1'): wfile(name, age) else: sex = input('性别:') wfile(name, age, sex) # # 0503 万能参数 *args, **kwargs # * 的魔性用法 def func4(*args, **kwargs): # 在函数的定义 * ** 聚合 print(args) print(kwargs) # 函数执行时 (1) *iterable 打散(2) **dict 打散 def func4(*args, **kwargs): # 在函数的定义 * ** 聚合 print(args) # print(kwargs) l1 = [1,2,3] l2 = [11,22,33] l3 = (55,66,77) dic = {'name':'alex'} dic1 = {'age':'12'} # func4(*l1,*l2,*l3) func4(**dic,**dic1) func4([1,2,3],[11,22,33],(55,66,77)) # 0504形参的顺序:位置参数、*args、默认参数、**kwargs def func5(a, b, *args, sex='男'): print(a) print(b) print(sex) print(args) print(func5(1, 2, 4, 5, 6, 7, 8, 9)) def func5(a,b,*args,sex='男',**kwargs,): print(a) print(b) print(sex) print(args) func5(1,2,4,5,6,7,8,9,sex='女')
6.函数的进阶
''' 整体说明: 01 python中的空间 (01)全局名称空间:存储的是全局(py文件)的变量与值的对应关系。 (02)临时(局部)名称空间:当函数执行时,会在内存中临时开辟一个空间,此空间记录函数中的变量与值的对应关系,随着函数的结束,临时名称空间而关闭。 (03)内置名称空间:len、print等都是函数的内置函数等。 02 python中空间的加载顺序: 内置名称空间 ---> 全局名称空间 ---> 函数执行时:临时(局部)名称空间 03 python中的作用域:与python中的空间是讲的是一个事情,只是叫法不同。 (01)全局作用域:内置名称空间 全局名称空间 (02)局部作用域:临时(局部)名称空间 04 取值顺序:函数执行时的顺序是:临时(局部)名称空间 ---> 全局名称空间 ----> 内置名称空间;取值时满足“就近原则”取值。 05 函数不执行时不开辟新的空间,只有通过“函数名()”进行函数调用时才开辟一个临时空间,函数执行完成后临时空间关闭。 06 global和nonlocal (1)global a)局部变量只能引用全局变量但是不能修改,修改进行报错,如果想修改则使用global。 b)在局部空间可以声明一个全局变量。 c)变量前增加global可以对全局变量进行修改。 (2)nonlocal a)不能操作全局变量 b)在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。 07 函数的嵌套 08 函数名的应用: (1)函数名可以当做变量使用(函数的内存地址就是变量的值) (2)函数名可以作为函数的参数 (3)函数名可以作为函数的返回值 (4)函数名可以作为容器类型的参数 ''' # 01 函数执行是的取值顺序:临时(局部)名称空间 ---> 全局名称空间 ----> 内置名称空间;取值时满足“就近原则”取值 len = 66 print(len) # 66 a = 1 def func(): a = 66 def func1(): a = 99 print(a) # 99,根据就近原则取值a = 99 func1() func() # 02 global的使用:变量前增加global可以对全局变量进行修改,相当于声明一个全局变量 a = 1 def func(): global a a += 1 print(a) func() def func(): global a a = 1 # print(a) func() print(a) # 03 nonlocal:子名称空间只能引用父名称空间的变量,但是不能修改。 def func1(): a = 1 def inner(): nonlocal a a += 1 print(a) # 1 inner() print(a) # 2 func1() # 04 函数的嵌套:通过函数的嵌套来进行函数调用。 def func1(): print(111) def func2() print(222) print(333) func2() print(444) func1() # 输出结果:111 333 222 444 def func1(): print(111) def func2(): print(222) func1() def func3(): func2() print(333) func3() # 输出结果: 222 111 333 # 05)函数名的运用 # 0501 函数名可以当做变量使用 def func1(): print(111) # 最后调用函数func1时,输出:111 a = 1 b = a print(b) # 首先打印 1 print(func1) # 其次输出:<function func1 at 0x00000000003E3E18> (函数名当做变量使用) f1 = func1 f2 = f1 f2() # 函数调用者 func1() # 0502 函数名作为函数的参数 def func1(): print(111) # 最后输出:111 def func2(x): print(x) # 首先输出func1作为变量的值:<function func1 at 0x00000000001D3E18> x() # 通过func1()调用函数func1。 # 0503 #函数名可以作为函数的返回值 def func1(): print(111) # 第4步:通过函数输出:111 def func2(x): return x # 第2步:返回func1 ret = func2(func1) # 第1步: 调用函数func2,参数为func1 ret() # 第3步:通过func1(),调用函数func1 # 0504 函数名可以作为容器类数据类型的参数(在工作过程中会经常会用到) def func1(): print(111) def func2(): print(222) def func3(): print(333) def func4(): print(444) l1 = [func1, func2, func3, func4] for i in l1: i() # 循环调用函数进行函数执行 dic = { 1: func1, 2: func2, 3: func3, 4: func4, } while 1: choice = int(input('请输入数字:')) dic[choice]() # 函数的调用通过“函数名()”进行函数的调用和执行。