# python学习笔记 ## 第一章 计算机基础 ### 1.1 硬件 计算机基本的硬件:CPU/内存/主板/硬盘/网卡/显卡,硬件与硬件之间需要系统来统一协调工作 ### 1.2 操作系统 操作系统是用于控制硬件与硬件之间的工作,常见的操作系统有三大类: - windows - linux - centos(公司线上一般用) - redhat - mac ### 1.3 解释器和编译器 编程语言的开发者写的一个工具,将用户写入的指令变成二进制 ### 1.4解释型语言和编译型语言 解释型语言:一边执行程序,一边将翻译成二进制让电脑运行,例如:python/PHP 编译型语言:翻译完后,在执行程序,例如:c/c++ ### 1.5 软件 软件即应用程序,就是我们电脑上的应用,例如记事本、游戏等 ### 1.6 进制 计算机能够识别的语言,是编程语言,即不同进制的编程语言 - 二进制:计算机内部。0101010101 - 8进制 - 10进制 - 16进制 ## 第二章 python入门 ### 2.1 环境的安装 - 解释器:py2/py3(环境变量) - 开发工具:pycharm ### 2.2 编码 #### 2.2.1编码类型 - ASCII - 一个英文字母占一个字节空间 - 一个中文字符占两个字节空间 - unicode - 两个字节表示一个字符(包括中文) - utf-8 - 一个中文字符占三个字节 - gbk/gbk2312 - 中文两个字符 #### 2.2.2python 编码相关 - 对于Python默认解释器编码 - py2:ASCII - py3:utf-8 如果想要修改默认编码,则可以使用 ```python #-*- coding:utf-8 -*- ``` 注意:对于操作文件时,要按照:以什么编码写入的,就要用什么编码去打开 ### 2.3 变量 ```python name = 'liujia' ``` 为什么要用变量 ? 就是为了以后调用变量多代表的值 ### 2.4 py2和py3的区别 - 字符串的类型不同 - py3: str bytes - py2: unicode str - 原来py2中的unicode就是现在的str,同理py2找那个的str是现在的bytes - 默认的解释器编码 - py3:utf-8 - py2:ascii - 输入输出 - int - int long - 除法 - rang和xrang - 模块和包 - py2中 需要在前面加__inti__ - 字典 - keys - py2:列表 - py3:迭代器,可以循环但是不可以索引 - values - py2:列表 - py3:迭代器,可以循环但是不可以索引 - items - py2:列表 - py3:迭代器,可以循环但是不可以索引 - map/filter - py2:列表 - py3:迭代器,可以循环但是不可以索引 ## 三章 数据类型 - int - bool - str - bytes ```python v = 'liujia'.encode('utf-8') #将字符串转换为字节(由unicode编码转换为utf-8编码) v = "liujia".encode('gbk') # #将字符串转换为字节(由unicode编码转换为gbk编码) ``` - list - tuple - dict - set - None ### 3.1 整形int #### 3.1.1 整形的长度 py2中有:intlong py3中有:int #### 3.1.2 整除 py2和py3中整除是不一样的 ### 3.2 布尔 布尔值就是用于表示真假,True和False 其他类型转换成布尔值: - None/""/o/空列表/空集合/空元组/空字典 ### 3.3 字符串str 字符串是写代码中最常见的,python内存中的字符串是按照unicode编码储存的,字符串是不可变 #### 3.3.1字符串独有的功能: - 大小写:upper/lower ```python a = 'liujia' data = a.upper() ``` - 判断是否是数字:isdecimal ```python choice = input('请输入内容:') if choice is.decimal(): choice = int(choice) print(choice) ``` - 去除空白+ + +指定字符串 strip/lstrip/rstrip ```python v1 = 'liujia ' print(v1.strip()) ``` - 替换 replace ```python v1 ='liujia' v1 = v1.replace('jia','danni') ``` - format ```python name = '我叫{0},年龄{1}'。format('liujia',2) ``` - join ```python name = 'liujia' reslt = "**".join(name)#循环每个元素,并在元素与元素之间加入连接符 ``` - split ```python v1 = 'liu|jia' print(v1.split('|')) #生成的是一个列表 ``` - startswith/endswith ```python name = 'liujia' flag = name.startswith('liu') print(flag) ``` - encode - ```python name = '刘佳' v1 = name.encode('utf-8') v1 = name.encode('gbk') ``` #### 3.3.2 公共功能 - 索引,获取一个字符串 - 切片,获取一段子序列 - 步长 ```python name = 'liujai' val = name[::-1] print(val) ``` - 长度,或者字符串长度 - for循环 ```python name = 'alex' for item in name: print(item) name = 'alex' for item in name: print(item) break print('123') name = 'alex' for item in name: print(item) continue print('123') ``` #### 3.3.3 字符串格式化 ```python #方式一 msg = '我是%s,年龄%s' %('liujia',19) msg = '我是{n1},年龄{n2}' %{'n1':'liujia','age':19} #方式二 msg = '我是{0},年龄{1}'.format(*('liujia',19)) #相当于位置传参 msg = '我是{name},年龄{age}'.format(**('name':'liujia','age':19)) #相当于关键字传参 ``` ### 3.4 列表 ```python user_list = ['liujia','liudanni',99] ``` #### 3.4.1 独有功能 - append,在列表的最后追加一个元素 ```python """ 示例一: users = [] while True: name = input('请输入姓名:') users.append(name) print(users) """ """ 示例二: # 录入用户和密码 users = [] for i in range(0,3): name = input('请输入用户名和密码:') users.append(name) print(users) # ['alex,123', 'oldboy,888', 'lishaoqi,123'] # 用户和密码校验 username = input('请输入要登陆用户名:') password = input('请输入要登陆密码:') for item in users: result = item.split(',') # ['alex','123'] user = result[0] pwd = result[1] if user == username and pwd == password: print('登陆成功') break """ ``` - insert - remove - pop - clear - reverse 反转 ```python v1 = [1,2,3111,32,13] print(v1) v1.reverse() print(v1) ``` - sort ```python v1 = [11,22,3111,32,13] print(v1) # v1.sort(reverse=False) # 从小到大(默认) # v1.sort(reverse=True) # 从大到小 # print(v1) ``` #### 3.4.2 公共功能 - len ```python user = ['刘佳','刘丹妮',66] user_len = len(user) print(user_len) ``` - 索引 ```python user = ['刘佳','刘丹妮',66] val = users[0] print(val) ``` - 切片 ```python user = ['刘佳','刘丹妮',66] val = user[0:2] ``` - 删除 ```python user = ['刘佳','刘丹妮',66] #方式1 user.pop(1) print(user) #方式2 del user[1] print(user) ``` 注意:字符串是不可变类型 - 修改 ```python user = ['刘佳','刘丹妮',66] user[1] = '刘丹霓' ``` - 步长 ```python val = user[0:2:2] ``` - for 循环 ```python user = ['刘佳','刘丹妮',66] for i in user: print(i) ``` 总结: - 增: - append / insert - 删: - remove / pop / clear / del users[2] - 改: - users[3] = "新值" - 查: - 索引/切片 - 列表的嵌套 ```python user=[66,'liujia',['刘佳','刘丹妮',66]] user[2][1] ``` ### 3.5 元组 #### 3.5.1 元组的书写规范 ```python user = (111,222,333,'liujia') ``` #### 3.5.2 公共功能 - 索引 ```python user = (111,222,333,'liujia') print(user[1]) ``` - 切片 ```python user = (111,222,333,'liujia') print(user[0:2]) ``` - 步长 ```python user = (111,222,333,'liujia') print(user[0:2:2]) ``` - 删除(无) - 修改(无) - for循环 ```python user = (111,222,333,'liujia') for item in user: print(item) ``` - len 无独有功能 ### 3.6 字典 #### 3.6.11字典的定义 帮助用户去表示一个事物的信息(事物的多个属性) 基本格式 ```python data = {键:值,键:值,键:值} info = {"name":'刘伟达','age':18,'gender':'男','hobby':'同桌'} ``` #### 3.6.2 独有的功能 - keys,获取字典中所有的键 ```python # for item in info.keys(): # print(item) ``` - values,获取子字典中所有的值 ```python # for item in info.values(): # print(item) ``` - items,获取字典中所有的键值对 ```python # for v1,v2 in info.items(): # print(v1,v2) ``` - get ```python info = {'k1':'v1','k2':'v2'} # v1 = info['k11111'] # v2 = info.get('k1111') # None就是Python中的空 # v3 = info.get('k1111',666) # print(v2) # None数据类型,改类型表示空(无任何功能,专门用于提供空值) ``` - pop ```python info = {'k1':'v1','k2':'v2'} result = info.pop('k2') print(info,result) del info['k1'] ``` - update ```python info = {'k1':'v1','k2':'v2'} # 不存在,则添加/存在,则更新 info.update({'k3':'v3','k4':'v4','k2':666}) print(info) ``` #### 3.6.3 公共功能 - len ```python info = {"name":'刘伟达','age':18,'gender':'男','hobby':'同桌'} print(len(info)) ``` - 索引 ```python info = {"name":'刘伟达','age':18,'gender':'男','hobby':'同桌'} info['name'] ``` - 切片(无) - 步长(无) - for循环 ```python info = {"name":'刘伟达','age':18,'gender':'男','hobby':'同桌'} for item in info.keys(): print(item) for item in info.values(): print(item) for k,v in info.items(): print(k,v) ``` - 修改(存在就修改,不存在就增加) ```python #改值 info = {"name":'刘伟达','age':18,'gender':'男','hobby':'同桌'} info['name'] ='liujia' #改键,删除后再增加 del info['name'] info['lk'] = 'x1' ``` - 删除 ```python info = {"name":'刘伟达','age':18,'gender':'男','hobby':'同桌'} del info['name'] print(info) ``` ### 3.7 集合 - 无序 - 无重复 #### 3.7.1 独有功能 - add - discard - update - intersection - union - difference - symmertric_difference #### 3.7.2 公共功能 - len - for - 索引(无) - 步长(无) - 切片(无) - 删除(无) - 修改(无) ### 3.8 内存相关 ```python v1 = [11,22,33] v2 = v1 # 练习1 (内部修改) v1 = [11,22,33] v2 = v1 v1.append(666) print(v2) # 含 666 # 练习2:(赋值) v1 = [11,22,33] v2 = v1 v1 = [1,2,3,4] print(v2) # 练习3:(重新赋值) v1 = 'alex' v2 = v1 v1 = 'oldboy' print(v2) ``` ```python v = [1,2,3] values = [11,22,v] # 练习1: """ v.append(9) print(values) # [11,22,[1,2,3,9]] """ # 练习2: """ values[2].append(999) print(v) # [1, 2, 3, 999] """ # 练习3: """ v = 999 print(values) # [11, 22, [1, 2, 3]] """ # 练习4: values[2] = 666 print(v) # [1, 2, 3] ``` 查看内存地址 ```python """ v1 = [1,2,3] v2 = v1 v1.append(999) print(v1,v2) print(id(v1),id(v2)) """ """ v1 = [1,2,3] v2 = v1 print(id(v1),id(v2)) v1 = 999 print(id(v1),id(v2)) """ ``` ## 第四章 文件操作 ### 4.1 深浅拷贝 - 浅拷贝 copy,只拷贝第一层 - 深拷贝deepcopy,拷贝所有层 ### 4.2 文件操作 - 打开 - r,只能读。 【**】 - w,只能写,写之前清空。 【**】 - a,只能追加。【*】 - r+ - 读:默认从0的光标开始读,也可以通过 seek 调整光标的为位置。 - 写:从光标所在的位置开始写,也可以通过 seek 调整光标的位置。 - w+ - 读:默认光标永远在写入的最后或0,也可以通过 seek 调整光标的位置。 - 写:先清空。 - a+ - 读:默认光标在最后,也可以通过 seek 调整光标的位置。然后再去读取。 - 写:永远写到最后。 - 操作 - 读 - read() - read(2) # 字符 - readlines() - write - 关闭 ## 第五章 函数 ### 5.1 三元运算 ```python v = 前面的值 if 条件 else 后面的值 #等同于 if 条件: v = 前面的值 else: v = 后面的值 例如: v = val1 if 5>3 else val2 ``` 例 ```python #让用户输入值,如果是整数,则转换成整数,否则值为None data = input('>>>') v = int(data) if data.isdecimal() else None ``` ### 5.2 函数 用一个函数名,去代替整个函数的代码,在运行中值需要调用函数名就可以,方便简洁。 注意:函数只有被调用后才会运行,仅仅放在代码中是不会运行的 #### 5.2.1函数式编程 ```python def get_data(): v = [11,22,11,333,444] print(v) get_data() ``` 对于函数编程: - 本质:将一段代码拿到别处起个名字,以后可以通过名字来调用这段代码 - 场景: - 代码重复执行 - 代码量特别多,超过一屏幕,不方便看 #### 5.2.2 函数的基本结构 ```python #函数的基本结构 def 函数名(): #函数内容 pass #函数的执行 函数名() ``` ```python def get_list(): v = [11,22,33,44] li = [] for i in v: li.append(i) print(li) get_list() #注意:函数不被调用,内部代码永远不会执行 ``` ### 5.3 参数 ```python def get_data(a1): #a1叫做形式参数 v = [11,22,11,333,444] print(v[a1]) get_data(0) #0/1/2 叫实际参数 get_data(1) get_data(2) ``` 示例 ```python #写出一个函数,计算列表中所有元素的和 def get_list_sum(a1): data = 0 for i in a1: data += i print(data) get_list_sum([11,22,44,66]) ``` #### 5.3.1参数的基本知识 - 任意个数 - 任意类型 ```python def func(a1,a2,a3) print(a1,a2,a3) func(1,"asdf",True) ``` #### 5.3.2 位置传参 ```python def func(a1,a2): print(a1,a2) func(1,3) #上面的a1、a2与下面的1、3是根据位置来对应的 ``` #### 5.3.3 关键字传参 ```python def func(a1,a2): print(a1,a2) func(a1=1,a2=3) #关键字传参和位置传参可以一起用,但有原则: #位置传参一定要在关键字传参的前面 def func1(a1, a2, a3): print(a1, a2, a3) # func(1, 2, a3=9) # func(1, a2=2, a3=9) # func(a1=1, a2=2, a3=9) # func(a1=1, 2,3) # 错误 ``` #### 5.3.4 默认传参 ```python #1.在传形式参数的时候,就将其中的一个形式参数赋值 #2.如果执行函数时,没有a3或者a4,则默认执行原来的值 def func(a1,a2,a3=9,a4=10): print(a1,a2,a3,a4) func(11,22) func(11,22,10) func(11,22,10,100) func(11,22,10,a4=100) func(11,22,a3=10,a4=100) func(11,a2=22,a3=10,a4=100) func(a1=11,a2=22,a3=10,a4=100) ``` ```python #如果想要给value设置默认是空列表 #不推荐使用可变类型(坑) def func(data,value=[]) pass #推荐使用不可变类型 def func(data,value=None) if not value: value = [] #示例 def func(data,value=[]): value.append(data) return value v1 = func(1) # [1,] v2 = func(1,[11,22,33]) # [11,22,33,1] ``` #### 5.3.5万能参数 - *args - 可以接受任意个数的位置参数,并将参数转换成元组 ```python #调用函数的时候没有有* def func(*args): print(args) func(1,2,3,4) ``` ```python #调用函数的时候有* def func(*args): print(args) func(*(1,2,3,4)) func(*[1,2,3,4]) ``` - **kwargs - 可以接受任意个数的关键字参数,并将参数转换成字典。 ```python #调用函数的时候没有* def func(**kwargs): print(kwargs) func(k1=1,k2=9) ``` ```python #电泳函数的室友有** def func(**kwargs): print(kwargs) func(**{k1:1,k2:9}) # kwargs={'k1':1,'k2':9} ``` #### 5.3.6 综合运用 *args + **kwargs ```python def func(*args,**kwargs): print(args,kwargs) # func(1,2,3,4,5,k1=2,k5=9,k19=999) ``` ### 5.4 返回值 - 函数没有返回值,默认返回:None - 函数内部执行过程中遇到return,就终止。 ```python def func(): 内容 return 9 #默认的返回值是None func('uhkn') ``` ```python #示例: #让用户输入一点字符串,计算字符串中有多少A字符。有多少个就在文件a.txt中学多少个"刘佳" def sum_A(data): sum = 0 for i in data: if i == "A": sum += 1 return sum def write_file(line): with open("a.txt",mode = "w",encoding = "utf-8") as file flie.write(line) content = input("请输入:") v = sum_A(content) line = "刘佳" * v def write_file(line): ``` ### 5.5 作用域 - 作用域理解 ![](C:UsersLJ VS LDNDesktoppython学习笔记相关资料作用域理解图.jpg) ```python #示例 a = 1 def s1(): x1 = 666 print(x1) print(a) print(b) b = 2 print(a) s1() a = 88888 def s2(): print(a,b) s1() s2() ``` - 总结: - 一个函数就是一个局部作用域,局部作用域在全局作用域中 - 作用域中数据查找的规则:优先在自己的作用域找,自己没有就不断往父级找,直到找到为止 - 查找数据只能在函数调用命令之前找,函数不被调用是不会执行的,记住一定是在执行命令之前找 ```python # x = 10 # def func(): # x = 9 # print(x) # def x1(): # x = 999 # print(x) # # func() # x = 10 # def func(): # x = 9 # print(x) # def x1(): # x = 999 # print(x) # x1() # # func() # x = 10 # def func(): # x = 9 # print(x) # def x1(): # x = 999 # print(x) # print(x) # x1() # # func() # x = 10 # def func(): # x = 8 # print(x) # def x1(): # x = 999 # print(x) # x1() # print(x) # # func() # x = 10 # def func(): # x = 8 # print(x) # def x1(): # print(x) # x1() # print(x) # # func() # x = 10 # def func(): # x = 8 # print(x) # def x1(): # print(x) # x = 9 # x1() # x = 10 # print(x) # # func() # # x = 10 # def func(): # x = 8 # print(x) # def x1(): # print(x) # # x1() # x = 9 # x1() # x = 10 # print(x) # # func() ``` - 子作用域只能找到父级中的值,默认无法为父级的变量进行赋值(global/nonlocal可以强制做) ```python name = ["liujai",'liudanni'] def func(): global name name = '我' func() print(name) ``` ### 5.6函数小高级 #### 5.6.1函数名可以当做变量来用 ```python def func(): print(123) v1 = func v1() ``` ```python def func(): print(123) def bar(): print(456) info = {'k1':func,'k2':bar} info['k1']() info['k2']() ``` ```python def func(): return 123 list = [func(),func()] #列表中func()是这个函数运行后的返回值 ``` #### 5.6.2函数可以当做参数来进行传递 ```python def func(arg): print(arg) def bar(): return 123 func(bar) ``` ### 5.7 lambda表达式 ```python #三元运算,为了解决简单的if else问题 v = a if 1>3 else b #lambda是为了解决简单的函数情况 def func(a1,a2) return a1 + 111 func =lambda a1,a2 : a1 + 100 ``` ```python #练习题1 USER_LIST = [] def func0(x): v = USER_LIST.append(x) return v result = func0('alex') print(result) #练习题2 def func0(x): v = x.strip() return v result = func0(' alex ') print(result) #总结:关于返回值是不是None,就得看函数有没有反回具体的值 #1.比如练习1中append命令指示添加到列表中,没有反回具体的值 #2.练习2中strip是去除空白返回了结果,所以有具体的值 ``` ### 5.8 内置函数 其他类: - len - open - range - id - type ```python class Foo: pass obj = Foo() if type(obj) == Foo: print('obj是Foo类的对象') ``` - issubclass ```python class Base: pass class Base1(Base): pass class Foo(Base1): pass class Bar: pass print(issubclass(Bar,Base)) print(issubclass(Foo,Base)) #判断Foo是不是Base的派生类 ``` - isinstance ```python class Base(object): pass class Foo(Base): pass obj = Foo() print(isinstance(obj,Foo)) # 判断obj是否是Foo类或其基类的实例(对象) print(isinstance(obj,Base)) # 判断obj是否是Foo类或其基类的实例(对象) ``` - super ```python class Base(object): # Base -> object def func(self): super().func() print('base.func') class Bar(object): def func(self): print('bar.func') class Foo(Base,Bar): # Foo -> Base -> Bar pass obj = Foo() obj.func() # super().func() 根据self对象所属类的继承关系,按照顺序挨个找func方法并执行(找到第一个就不在找了) ``` 输入输出类: - print - input 强制转换: - int - str - bool - list - tuple - dict - set 数学相关: - abs 绝对值 - float 转成浮点型(小数) - max - min - sum 求和 - divmod 两数相除的商和余数 编码相关: - chr - chr,将十进制数字转换成unicode编码中所对应的字符串 - ord - ord,根据字符串在unicode编码中找到对应的十进制 - 应用:生成随机验证码 ```python import random def get_random_code(lengtn=6): data = [] for i in range(length): v = random.randint(65,90) data.append(v) return "",join(data) code = get_random_code() print(code) ``` - divmon应用 做分页 ```python a,b = divmod(1005,7) print(a,b) ``` ```python #练习题:请通过分页对数据进行展示 """ 要求: 每页显示10条数据 让用户属兔想要查看的页面 """ USER_LIST = [] for in in range(1,836) temp = { 'name':"你的数字名字是%s"%(i,) 'email':'%s@qq.com'%s(i,) } USER_LIST.append(temp) count = len(USER_LIST) per_page = 10 max_num,b = divmod(count,per_page) if b > 0: max_num += 1 while True: page = input('请输入要跳转的页码:') if page < 1 or page > mix_num: print('您输入的页码错误,必须在1-%s'%(max_mun,)) else: """ # 第1页:USER_LIST[0:10] -> 0123456789 # 第2页:USER_LIST[10:20] # 第3页:USER_LIST[20:30] ... """ start = (page - 1)*per_page end = page * per_page data = USER_LIST[start:end] for v in data: print(v) ``` ### 5.9 进制转换 - bin,将10进制转换为二进制 ```python num = 13 v1 = bin(num) print(v1) ``` - oct,将十进制转换成八进制,同bin - int,将其他进制转换为十进制 ```python v1 = '0b1101' result = int(v1,base=2) print(result) # 八进制转化成十进制 v1 = '0o1101' result = int(v1,base=8) print(result) # 十六进制转化成十进制 v1 = '0x1101' result = int(v1,base=16) print(result) ``` - hex,将十进制转换成十六进制,同bin ### 5.10 函数中高级 #### 5.10.1 函数可以当做返回值 ```python def func(): print(123) def bar(): return func v = bar() v() ``` #### 5.10.2 闭包 ```python def func(name): def innner(): print(name) return inner v1 = func('liujia') v1() v2 = func('eric') v2() ``` ![](C:UsersLJ VS LDNDesktoppython学习笔记相关资料闭包.jpg.png) 总结: - 函数执行的流程分析(函数式谁创建的) - 闭包概念:为函数创建一块区域并为其维护自己数据,以后执行时候方便调用 #### 5.10.3 高阶函数 - 将函数当做参数传递 - 把函数当做返回值 注意:对函数进行赋值 ```python def func(): print(123) def bar(a): return a v1 = bar(func) v1() ``` ### 5.11 装饰器 ```python #装饰器的编写 def func(arg): def inner(*args,**kwargs) #需要添加的操作 ret = arg(*args,**kwargs) #需要添加的操作 return ret return inner @func def index(): print(123) #执行函数,自动触发装饰器 v = index() print(v) ``` ```python #装饰器编写格式 def 外层函数(参数): def 内层函数(*args,*kwargs) return 参数(*args,**kwargs) return 内层函数 @外层函数 def index(): pass index() ``` #### 5.11.1 带参数的装饰器 ```python def func(counter): def inner(arg): def bar(*args,**kwargs): ret = arg() return ret return bar return innner @func(6) def index(): pass v = index() print(v) ``` ### 5.12 推导式 - 列表的推导式 - 基本格式 ```python #目的:方便生成一个列表 v1 = [i for i in range(10)] v2 = [ i+100 for i in range(10)] v3 = [99 if i>5 else 66 for i in range(10)] v4 = [lambda : 100 for i in range(10)] v5 = [lambda : 1 for i in range(10)] v8 = [lambda x:x*i for i in range(10)] # 新浪微博面试题 # 1.请问 v8 是什么? # 2.请问 v8[0](2) 的结果是什么? def num(): return [lambda x:i*x for i in range(4)] # num() -> [函数,函数,函数,函数] print([ m(2) for m in num() ]) # [6,6,6,6] ``` - 集合推导式 ```python v1 = { i for i in 'alex' } ``` - 字典推导式 ```python v1 = {'k'+str'i':i for i in range(10)} ``` ## 第六章 模块 ### 6.1 模块 - 内置模块,python内部提供过的功能 ```python import sys ``` - 第三方模块,下载/安装/使用 ```python #吧pip.exe 所在的目录添加到环境变量中 pip install 安装的模块名字 #例如:pip install xlrd ``` - 自定义模块(自己写的函数) - xxx.py ```python def f1(): print(123) def f2(): print(125) ``` - x1.py ```python #调用自定义函数里面的内容 import xxx xxx.f1() xxx.f2() ``` - 定义模块 - 定义模块是可以把一个py文件或者一个文件夹(包)当做一个模块,以方便以后其他py文件的调用 对于包的定义: - py2:文件中必须要有:__init__.py(可以自己创建) - py3中,不需要 ### 6.2 sys python解释器相关的数据 - sys.getrefcount,获取一个值得应用计数 - sys.getrecursionlimit,python默认支持的递归数量 - sys.stdout.write-->print ```python #打印进度条 import time for i in range(1,101): msg = "%s%%" %i print(msg,end="") time.sleep(0.05) ``` - sys.argv ```python #让用户执行脚本传入要删除的文件路径,在内部帮助用户将目录删除 import sys C:Python36python36.exe D:/code/s21day14/7.模块传参.py D:/test sys.argv = [D:/code/s21day14/7.模块传参.py, D:/test] path = sys.argv[1] impor shutil shutil.rmtree(path) ``` - sys.path,默认pythn去导入模块时,会按照sys.path中的路劲挨个寻找 ```python import sys sys.path.append('D:\') import xxx #引用默认路径之外的模块 ``` ### 6.3 json json是一个特殊的字符串【长的像列表/字典/字符串/数字/真假】 为什么要这么做: 1. 方便除python以外的解释器来运行python编写的代码 2. 方便将其他解释器编写的代码,转化成python能识别的东西 ```python import json #序列化,将python的值转化成json格式的字符串 v = [11,22,4,{"k1":"v2"},True,"saf"] v1 = json.dumps(v) print(v1) #反序列化,将json格式的字符串转化成python的数据类型 v2 = '['alex',123]' print(type(v2)) v3 = json.loads(v2) print(v3,type(v3)) #字典或者列表中有中文,序列化时候想要保持中文显示,如果不保留显示的就是二进制: v = {'k1':'alex','k2':'李杰'} import json val = json.dumps(v,ensure_ascii=False) print(val) ``` #### 6.3.1 json和pickle - json: - 优点,所有语言通用;缺点,只能序列化基本的数据类型(int float str list dict bool) - ``` # 1.所有的字符串都是双引号 # 2.最外层只能是列表或者字典 # 3.只支持 int float str list dict bool # 4.存在字典字典的key只能是str # 5.不能连续load多次 ``` - pickle:优点,python中所有的佛那个下都能被它序列化;缺点:序列化的内容只有python能识别 - ``` # 1.几乎所有的数据类型都可以写到文件中 # 2.支持连续load多次 ``` - 他们两个的用法是一样的 ### 6.4 os - os.stat('文件名').st_size 读取文件的大小 ```python import os file_size = os.stat('刘丹妮.mp4').st_size read_size = 0 with open('刘丹妮.mp4',mode = 'rb') as f1,open('a.mp4',mode='wb') as f2: while read_size < file_size: chunk = f1.read(1024)#每次最多读取1024字节 f2.write(chunk) read_size += len(chunk) val = int(read_size/file_size*100) print('%s%%/r' %val,end="") ``` - os.path.exists(path) , 如果path存在,返回True;如果path不存在,返回False - os.path.abspath() , 获取一个文件的绝对路径 ```python path = '20190409_192149.mp4' import os v1 = os.path.abspath(path) print(v1) ``` - os.path.dirname ,获取路径的上级目录 - ```python import os v = r"D:codes21day1420190409_192149.mp4" print(os.path.dirname(v)) ``` - os.path.join ,路径的拼接 ```python import os path = "D:codes21day14" # user/index/inx/fasd/ v = 'n.txt' result = os.path.join(path,v) print(result) result = os.path.join(path,'n1','n2','n3') print(result) ``` - os.listdir , 查看一个目录下所有的文件【第一层】 - ```python import os result = os.listdir(r'D:codes21day14') for path in result: print(path) ``` - os.walk , 查看一个目录下所有的文件【所有层】 ```python import os result = os.walk(r'D:codes21day14') for a,b,c in result: # a,正在查看的目录 b,此目录下的文件夹 c,此目录下的文件 for item in c: path = os.path.join(a,item) print(path) ``` - os.makedirs,创建目录和子目录 ```python import os file_path = r'db/sf/sf/er/xxx.txt' file_folder = os.patn.dirname(file_path) if not os.path.exists(file_path) os.makedirs(file_folder) with open(file_path,mode='w',encoding='utf-8') as f: f.write('asdf') ``` - os.rename,重命名 ```python import os os.rename('sb','250') ``` 6.4特殊补充 ```python v1 = r"D:codes21day14 1.mp4" (推荐) print(v1) v2 = "D:\code\s21day14\n1.mp4" print(v2) #python在执行过程中,对很敏感,如果按照案例中的来写,很容易就系统报错,r的作用是让左右都被认为仅仅只是,区别去 这种 ``` ### 6.5 shutil 和md5加密 ```python import shutil shutil.rmtree(path) #删除目录(不是文件) shutil.move('liuajia','liudanni') #重命名 #压缩文件 shutil.make_archive('liujia','zip','D:code(压缩的路径)') #解压文件 shutil.unpack_archive('liujia.zip',extract_dir=r'D:codexxx',format='zip') ``` ```python # import hashlib # md5 = hashlib.sha1('盐'.encode()) # md5.update(b'str') # print(md5.hexdigest()) ``` ### 6.6 collections模块 和 random随机模块 ```python from collections import OrderedDict oidc = OrderdDict([('a',1)],('b',2),('c',3)) print(odic) for k in odic: print(k,odic[k]) ``` ```python from collections import namedtuple #可命名元组 Course = namedtuple('Course',['name','price','teacher']) python = Course('python',19800,'alex') print(python) print(python.name) print(python.price) #创建一个类,这个类没有方法Course,所有属性的值都不能修改 ``` ```python mport random print(random.uniform(1,5)) print(random.choice([1,2,3,4,5])) # 验证码 抽奖 print(random.sample([1,2,3,4],3)) # 一个奖项抽取多个人 # choice # sample # shuffle # 洗牌 算法 ``` ### 6.7 导入模块 ```python #文件夹a 1.py 2.py #文件夹b 3.py 4.py #这表示有a,b两个文件夹,每个文件夹中各有py文件 导入模块 import 模块 # 这种适用于内置函数,或者是同一目录下的文件,比如1.py和2.py from 模块 import 函数 #首先需要用sys.path.append()将需要的目录添加进去,比如这里就是sys.path.append(文件夹b),然后才能执行 ``` ```python import jd #第一次加载,会加载一边jd中所有的内容 import jd #已经加载过,就不用在加载 ``` - 调用模块 - import - import 模块1 - import 模块1.模块2.模块3 - from xx import xxx - from 模块.模块 import 函数 函数() - from 模块.模块 import 函数 as f f() - from 模块.模块 import* 函数1() 函数2() - from 模块 import 模块 模块.函数() - from 模块 import 模块 as m m.函数() - 注意:文件和文件夹的命名不能是导入的模块名称相同,否则就会直接在当前目录中查找。 ### 6.8 time和datetime UTCGMT:世界时间 本地时间:本地时区的时间 #### 6.8.1 time模块 - time.time(),时间戳:1970-1-1 00:00 - time.sleep(10) 等待秒数 - time.timezone 跟地区相关 #### 6.8.2 datatime模块 ```python #获取当地时间 v1 = datetime.now() print(v1) #查看不同时区的时间 tz = timezone(timedelta(hours=7)) #东7区时间 v2 = datetime.now(tz) print(v2) v3 = datetime.utcnow() #当前UTC时间 ``` ```python import time from datetime import datetime,timezone,timedelta #将datetime格式转换成字符串格式 v1 = datetime.now() print(v1) val = v1.strftime("%Y-%m_%d %H-%M-%S") print(val) #字符串转换成datetime v3 = datetime.strptime('2010-11-12','%Y-%m-%d') print(v3) #datetime时间的加减 v4 = datetime.strptime('2010-11-12','%Y-%m-%d') v5 = v4 - timedelta(days=150) data = v5.strftime('%Y-%m-%d') print(data) #时间戳和datetime关系 #将时间戳转化为datetime格式 ctime = time.time() print(ctime) v6 = datetime.fromtimestamp(ctime) print(v6) #将datetime格式转化为时间戳 v7 = datetime.now() val = v7.timestamp() print(val) ``` ### 6.9 异常处理 #### 6.9.1 基本格式 ```python try: val = input('请输入数字:') num = int(val) except Exception as e: print('操作异常') ``` ```python #写函数去,接受一个列表。列表中都是url,请访问每个地址并获取结果。 import requests def func(url_list): result = [] try: for url in url_list: response = requsts.get(url) result.append(response.text) except Exception as e: pass return result #当try那里出错,将不会再执行接下来的for循环 def func2(url_list): result = [] for url in url_list: try: response = requests.get(url) result.append(response.text) except Exception as e: pass return result #当try那里出错,继续执行接下来的for循环 ``` #### 6.9.2 主动触发异常 ```python try: int('123') raise Exception('阿萨大大是阿斯蒂') # 代码中主动抛出异常 except Exception as e: print(e) ``` 应用场景: ```python def func(): result = True try: with open('x.log',mode='r',encoding='utf-8') as f: data = f.read() if 'alex' not in data: raise Exception() except Exception as e: result = False return result ``` #### 6.9.3 自定义异常 ```python class MyException(Exception): def __init__(self,message): super().__init__() self.message = message try: raise MyException('asdf') except MyException as e: print(e.message) ``` ### 6.10 迭代器 #### 6.10.1迭代器的定义 自己不用写,只需要学会用 迭代器:对可迭代对象中的元素进行逐一获取,表象:具有'' __next__ ''方法且每次调用都获取可迭代对象中的元素(从前到后一个个获取) - 列表转化为迭代器: - v1 = iter([11,22,33,44]) - v1 = [11,22,33,44].__iter__() - 迭代器想要获取每个值,就必须反复执行 ```python v1 = [11,22,33,44] #列表转化成迭代器 v2 = iter(v1) result = v2.__next__() result = v2.__next__() result = v2.__next__() result = v2.__next__() #如果报错:Stopiteration,表示已经迭代完成 v1 = [11,22,334,44] v2 = iter(v1) while True: try: val = v2.__next__() print(val) exceppt Exception as e: break ``` - for 循环 ```python v1 = [11,22,334,44] #内部会将v1转换成迭代器 #内部会反复执行 迭代器.__next__() #取完后不报错 for item in v1: print(item) ``` #### 6.10.2 可迭代对象 - 内部具有 __iter__() 方法并且返回一个迭代器 ```python v1 = [11,223,33,44] result = v1.__iter__() ``` - 可以被for循环 如何让一个对象变成可迭代对象? 在类中事项__iter__方法并返回一个迭代器(生成器) ```python class Foo: def __iter__(self): return iter([1,2,3,4]) obj = Foo() class Foo: def __iter__(self): yield 1 yield 2 yield 3 obj = Foo() ``` ### 6.11生成器(函数的变异) ```python #函数 def func(): return 123 func() ``` ```python #生成器很熟(内部包含有yield) def func(): print('F1') yield 1 print('F2') yield 2 print('F3') yield 100 print('F4') #函数内部代码不会执行,返回一个生成器对象,只有被for循环才只想内部代码 v1 = func() #生成器是可以被for循环,一旦开始循环那么函数内部得代码就会开始执行 for item in v1: print(item) ``` #### 6.11.1 生成器推导式 ```python #正常循环 def func(): result = [] for i in range(10): result.append(i) return result v1 = func() for item in v1(): print(v1) #推导式 v1 = [i for i in range(10)]#列表推导式立即循环创建所有的元素 #正常循环 def func(): for i in range(10): def f(): return i yield f v2 = func() for item in v2(): print(item()) #推导式 v2 = (lambda :i for i in range(10)) for item in v2: print(item()) #生成器推导式,创建了一个生成器,内部循环未执行。也就是说,i还是一个变量,还没有赋值,只有等到for循环的时候,i就从0开始循环。 ``` - 案例 ```python def func(): count = 1 while True: yield count count += 1 if count == 99 return val = func() for item in val: print(item) ``` - 示例:读文件 ```python def func(): """ 分批次去读取文件的内容,将文件的内容返回给调用者 """ cursor = 0 while True: with open('a.txt',mode='r',encoding='utf-8') as f: f.seek(cursor) #将光标移动到指定的位置 data_list = [] for i in range(10): len = f.readline() if not len: return data_list.append(len) cuesor = f.tell() #获取光标的位置 f.close() for row in data_list: yiled row for item in func(): print(item) ``` ## 第七章 面向对象 ``` # 新式类和经典类 # py2 继承object就是新式类 # 默认是经典类 # py3 都是新式类,默认继承object # 新式类 # 继承object # 支持super # 多继承 广度优先C3算法 # mro方法 # 经典类 # py2中不继承object # 没有super语法 # 多继承 深度优先 # 没有mro方法 ``` ### 7.1 面向对象的基本格式 ```python class 类: def 方法名(self,name) print(name) return 123 def 方法名(self,name) print(name) return 123 def 方法名(self,name) print(name) return 123 #调用类中的函数 1.创建改类的对象 obj = 类名() 2.对象调用方法 resut = obj.方法名('liujia') print(result) ``` 应用场景:遇到很多函数,需要给函数进行分类规划【封装】 ### 7.2对象的作用 存储一些值,方便以后调用 ```python class File: def read(self): with open(self.xxx,mode='r',encoding='utf-8') as f: data = read() return data def write(self,content): with open(self.xxx,mode='w',encoding='uttf-8') as f: f.write(content) #示例化一个File类的对象 obj1 = File() #在对象中写了一个xxxx = 'test.log' obj1.xxx = 'test.log' #通过对象调用类中的read方法,read方法中的self就是obj obj1.read() obj1.write('liujia') #实例化了一个File类的对象 obj2 = File() obj2.xxxxxx = 'info.txt' obj.read() obj2.write('liujia') ``` ```python class Person: def show(self): temp = "我是%s,今年%s岁,性别%s" %(self.name,self.age,self.gender) print(temp) obj = Person() obj.name = 'liujia' obj.age = 2 obj.gender = 'boy' obj.show() ``` ```python class Person: def __init__(self,n,a,g)#初始化方法(构造方法),给对象的内部做初始化 self.name = n self.age = a self.gender = g def show(self): temp = "我是%s,今年%s岁,性别%s" %(self.name,self.age,self.gender) print(temp) #类()实例化对象时,会自动执行此类的__init__方法 obj = Person('lijia',2,'boy') obj.show() ``` 总结:将数据封装到对象中,方便使用 ```python """ 如果写代码时,函数比较多比较乱。 1. 可以将函数归类并放到同一个类中。 2. 函数如果有一个反复使用的公共值,则可以放到对象中。 """ class File: def __init__(self,path): self.file_path = path def read(self): print(self.file_path) def write(self,content): print(self.file_path) def delete(self): print(self.file_path) def update(self): print(self.file_path) p1 = File('log.txt') p1.read() p2 = File('xxxxxx.txt') p2.read() ``` ```python #1.循环让用户输入:用户名/密码/邮箱。输入完成后再进行数据打印。 USER_LIST = [] class User: def __init__(self,name,pwd,email): self.name = name self.pwd = pwd self.email = email while True: name = input('请输入用户名:') pwd = input('请输入密码:') email = input('请输入邮箱:') p = Person(name,pwd,email) USER_LIST.append(p) for item in USER_LIST: temp = "我的名字:%s,密码:%s,邮箱%s" %(item.name,item.password,item.email,) print(temp) ``` 示例:游戏开发 ```python class Police: def __init__(self,name) self.name = name self.hp = 10000 def tax(self): msg = "%s收了个税。" %(self.name,) print(msg) def fight(self): msg = "%s去战了个斗。" %(self.name,) lsq = Police('李邵奇') zzh = Police('渣渣会') tyg = Police('堂有光') class Bandit: def __init__(self,nickname) self.nickname = nickname self.hp = 1000 def murder(self,name): msg = "%s去谋杀了%s" %(self.nickname, name,) lcj = Bandit('二蛋') lp = Bandit('二狗') zsd = Bandit('狗蛋') # 1. 二狗去谋杀渣渣会,二狗生命值-100; 渣渣会生命值减5000 lp.murder(zzh.name) lp.hp = lp.hp - 100 zzh.hp = zzh.hp - 5000 # ... ``` ```python class Police: def __init__(self,name) self.name = name self.hp = 10000 def dao(self,other): msg = "%s个了%s一刀。" %(self.name,other.nickname) self.hp = self.hp - 10 other.hp = other.hp - 50 print(msg) def qiang(self): msg = "%s去战了个斗。" %(self.name,) def quan(self,other): msg = "%s个了%s一全。" %(self.name,other.nickname) self.hp = self.hp - 2 other.hp = other.hp - 10 print(msg) class Bandit: def __init__(self,nickname) self.nickname = nickname self.hp = 1000 def qiang(self,other): msg = "%s个了%s一全。" %(self.nickname,other.name) self.hp -= 20 other.hp -= 500 lcj = Bandit('二蛋') lsq = Police('李邵奇') lsq.dao(lcj) lsq.quan(lcj) lcj.qiang(lsq) ``` ### 7.3 继承 ```python #父类(基类) class Base: def f1(self): pass #子类(派生类) class Foo(Base): def f2(self): pass #创建一个子类的对象 obj = FOO() #执行对象方法时,有限在自己的类中找,如果没有就去父类中找 obj.f2() obj.f1() ``` 问题:什么时候才能用到继承?多个类中如果有公共的方法,可以放到基类中避免重负编写 ```python class Base: def f1(self): pass class Foo(Base): def f2(self): pass class Bar(Base): def f3(self): pass obj1 = Foo() obj2 = Bar() ``` 继承关系中查找方法的顺序: ```python # 示例一 class Base: def f1(self): print('base.f1') class Foo(Base): def f2(self): print('foo.f2') obj = Foo() obj.f1() obj.f2() # 示例二 class Base: def f1(self): print('base.f1') class Foo(Base): def f2(self): self.f1() print('foo.f2') obj = Foo() obj.f2() # 示例三 class Base: def f1(self): print('base.f1') class Foo(Base): def f2(self): self.f1() print('foo.f2') def f1(self): print('foo.f1') obj = Foo() obj.f2() # 示例四 class Base: def f1(self): self.f2() print('base.f1') def f2(self): print('base.f2') class Foo(Base): def f2(self): print('foo.f2') obj = Foo() obj.f1() # 示例五 class TCPServer: pass class ThreadingMixIn: pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass # 示例六 class BaseServer: def serve_forever(self, poll_interval=0.5): self._handle_request_noblock() def _handle_request_noblock(self): self.process_request(request, client_address) def process_request(self, request, client_address): pass class TCPServer(BaseServer): pass class ThreadingMixIn: def process_request(self, request, client_address): pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass obj = ThreadingTCPServer() obj.serve_forever() #注意事项: #self 到底是谁? #self 是哪个类创建的,就从此类开始找,自己没有就找父类。 ``` ### 7.4 多态(多种形态/多种类型)鸭子模型 ```python def func(arg): v = arg[1] print(v) #只要传入的参数能够满足arg[1],无论它是那种类型,那种形态 ``` 面试题:什么是鸭子模型 ```python #对于一个函数而言,python对于函数的参数类型不会限制,arg传入的参数可以试各种形态,在函数中如果有:arg.send方法,那么就是对传入参数类型的一个限制 #这就是鸭子模型,类似于上述的函数我们认为只要呱呱叫的就是鸭子,只要能满足send方法就可以做参数 ``` 面向对象的三个特性:封装、多态、继承 ### 7.5 成员 #### 7.5.1 对象成员 - 实例变量 ```python class Abc: def __init__(self,name): self.name = name obj = Abc(liujia) #在对象中添加了一个变量name ``` #### 7.5.2类成员 - 类变量 ```python class Abc: name = 'liujia' def func(self): pass def bar(self): pass #name就是类变量 ``` 定义:写在类的下一级和方法是同一级 访问、调用: ```python #类.类变量名称 #对象.类变量名称 ``` 总结:找变量有限找自己的,自己没有就找类或者基类;修改或者复制只能在自己的内部设置 - 绑定方法 定义:至少有一个self参数 执行:先创建对象,又对象.方法() ```python class FOO: def func(self,a,b): print(a,b) obj = FOO() obj.func(1,2) ``` - 类方法 定义: 1. @classmethon装饰器 2. 至少有cls参数,当前类 执行: 1. 类.类方法() 2. 对象.类方法()(不推荐) ```python class Foo: def __init__(self): self.name = 123 def func(self, a, b): print(self.name, a, b) @staticmethod def f1(): print(123) @classmethod def f2(cls,a,b): print('cls是当前类',cls) print(a,b) obj = Foo() obj.func(1, 2) Foo.f1() Foo.f2(1,2) ``` - 静态方法 定义: 1. @staticmethod装饰器 2. 参数没有限制,可以不传,也可以传多个 执行: 1. 类.静态方法名() 2. 对象.静态方法名()(不推荐) ```python class Foo: def __init__(self): self.name = 123 def func(self): print(self.name,a,b) @staticmethod def f1(): print(123) obj = Foo() obj.func() FOO.f1() #可以直接用类调用方法,也可以用对象调用方法 ``` - 属性 定义: 1. @property装饰器 2. 只有一个self参数 执行: 对象.方法 不用加括号 ```python class Foo: @property def func(self): print(123) return 999 obj = Foo() result = obj.func print(result) ``` ```python #属性的应用 class Page: def __init__(self,total_count,current_page,per_page_count=10): self self.total_count = total_count self.per_page_count = per_page_count self.current_page = current_page @property def start_index(self): return (self.current_page - 1)*self.per_page_count @property def end_index(self) return self.current_page*per_page_count user_list = [] for i in range(250): user_list.append('alex-----%s' %(i,)) current_page = int(input('请输入想要查看的页码:')) p = Page(250,current_page) data_list = user_list[p.start_index:p.end_index] for item in data_list: print(item) ``` #### 7.5.3 成员修饰符 - 公有,所有地方都能访问到 - 私有,自能自己访问,前面加__ ```python class Foo: def __init__(self, name): self.__name = name def func(self): print(self.__name) obj = Foo('alex') # print(obj.__name) obj.func() ``` ```python class Foo: __x = 1 @staticmethod def func(): print(Foo.__x) # print(Foo.__x) Foo.func() ``` ```python class Foo: def __fun(self): print('msg') def show(self): self.__fun() obj = Foo() # obj.__fun() obj.show() ``` #### 7.5.4 嵌套 - 函数:参数可以试任意类型 - 字典:对象和类都可以做字典的key和value - 继承关系的查找关系 ```python class School(object): def __init__(self,title,addr): self.title = title self.address = addr class ClassRoom(object): def __init__(self,name,school_object): self.name = name self.school = school_object s1 = School('北京','沙河') s2 = School('上海','浦东') s3 = School('深圳','南山') c1 = ClassRoom('全栈21期',s1) c1.name c1.school.title c1.school.address # ############################################ v = [11,22,33,{'name':'山海','addr':'浦东'}] v[0] v[3]['name'] ``` ```python class Foo: def __init__(self,num): self.num = num cls_list = [] for i in range(10): cls_list.append(Foo) for i in range(len(cls_list)): obj = cls_list[i](i) print(obj.num) ``` ```python class Foo: def f1(self): print('f1') def f2(self): print('f2') obj = Foo() v = [ obj.f1,obj.f2 ] for item in v: item() #当做参数传递 ``` ```python class Foo: pass class Foo(object): pass # 在python3中这俩的写法是一样,因为所有的类默认都会继承object类,全部都是新式类。 # 如果在python2中这样定义,则称其为:经典类 class Foo: pass # 如果在python2中这样定义,则称其为:新式类 class Foo(object): pass class Base(object): pass class Bar(Base): pass ``` ```python class School(object): def __init__(self,title): self.title = title def rename(self): pass class Course(object): def __init__(self,name,school_object): self.name = name self.school = school_object def reset_price(self): pass class Classes(object): def __init__(self,cname,course_object): self.cname = cname self.course = course_object def sk(self): pass s1 = School('北京') c1 = Course('Python',s1) c2 = Course('Go',s1) cl1 = Classes('全栈1期',c1) #类似想要多个元素组合在一起,应该要一级一级来 ``` ```python class StackConfig(object): list_display = '李邵奇' def changelist_view(self): print(self.list_display) class UserConfig(StackConfig): list_display = '利奇航' class AdminSite(object): def __init__(self): self._register = {} def registry(self,key,arg=StackConfig): self._register[key] = arg def run(self): for key,value in self._register.items(): obj = value() obj.changelist_view() site = AdminSite() site.registry(1) site.registry(2,StackConfig) site.registry(3,UserConfig) site.run() #对象和类在字典中的应用 ``` ### 7.6 特殊成员 #### 7.6.1 __init__ ```python class Foo: def __init__(self,name): self.name = name obj = Foo('liujia') ``` #### 7.6.2 __new__ ```python class Foo: def __init__(self,name): self.name = name def __new__(cls,*args,**kwargs): """ 用于创建空对象,构造方法 """ return object.__new__(cls) obj = Foo() #object,它new了一个对象出来 ``` #### 7.6.3 __call__ ```python class Foo: def __call__(self,*args,**kwargs): print(123) obj = Foo() obj() #对象加(),就执行call方法 ``` #### 7.6.4 __getitem__ __setitem__ __delitem__ ```python class Foo(object): def __setitem__(self, key, value): pass def __getitem__(self, item): return item + 'uuu' def __delitem__(self, key): pass #实现字典里的方法 obj1 = Foo() obj1['k1'] = 123 # 内部会自动调用 __setitem__方法,添加 val = obj1['xxx'] # 内部会自动调用 __getitem__方法,索引 print(val) del obj1['ttt'] # 内部会自动调用 __delitem__ 方法,删除 ``` #### 7.6.5 __str__ ```python class Foo: def __str__(self): """ 只有在打印对象的时候,会自动调用此方法,并将其返回值显示在页面 """ obf = Foo() print(obj) ``` ```python class User(object): def __init__(self,name,email): self.name = name self.email = email def __str__(self): return "%s %s" %(self.name,self.email,) user_list = [User('二狗','2g@qq.com'),User('二蛋','2d@qq.com'),User('狗蛋','xx@qq.com')] for item in user_list: print(item) #打印出来的不再是函数的地址,而是__str__的返回值 ``` #### 7.6.6 __dict__ ```python class Foo(object): def __init__(self,name,age,email): self.name = name self.age = age self.email = email obj = Foo('alex',19,'xxxx@qq.com') print(obj) print(obj.name) print(obj.age) print(obj.email) val = obj.__dict__ # 去对象中找到所有变量并将其转换为字典 print(val) ``` #### 7.6.7 上下文管理 __enter__ __exit__ ```python class Foo: def __enter__(self): self.x = open('a.txt',mode='a',encoding='utf-8') return self.x #return的值赋给了下面的ff def __exit__(self,exc_type,exc_val.exc_tb): self.x.close() with Foo() as ff: ff.write('liujia') ``` ```python class Foo(object): def do_something(self): print('内部执行') class Context: def __enter__(self): print('进入') return Foo() def __exit__(self, exc_type, exc_val, exc_tb): print('退出') with Context() as ctx: print('内部执行') ctx.do_something() #总结,就是在执行某个函数之前,先执行一个程序,在执行另一个程序 ``` #### 7.6.8 两个对象相加 __add__ ```python val = 5 + 8 print(val) val = "alex" + "sb" print(val) class Foo(object): def __add__(self, other): return 123 obj1 = Foo() obj2 = Foo() val = obj1 + obj2 print(val) #加减乘除都可以,类似的 ``` ### 7.7 栈 ```python class Stack: """ 后进先出来 """ def __init__(self): self.data_list = [] def push(self,val): """ 向栈中压入一个数据(入栈) """ self.data_list.append(val) def pop(self): """ 从栈中拿走一个数据 """ return self.data_list.pop() ``` ### 7.8 约束 ```python #约束子类中必须写send方法,如果不写,则调用的时候就会报错: class Interface(object): def send(self): raise NotImplementedError() class Message(Interface): def send(self): print('woshinibaba') class Email(Interface): def send(self): print('woshinimama') obj = Email() obj.send() ``` ### 7.9 反射 根据字符串的形式去某个对象中操作他的成员 - getattr(对象,字符串) 根据字符串的形式去某个对象中获取对象的成员 ```python class Foo: def __init(self,name): self.name = name obj = Foo('liujia') #获取变量 v1 = getattr(obj,'name') #获取方法 method_name = getattr(obj,'login') method_name() ``` - hasattr(对象,‘字符串’) 根据字符串的形式去某个对象中判断是否有该成员 ```python #!/usr/bin/env python # -*- coding:utf-8 -*- from wsgiref.simple_server import make_server class View(object): def login(self): return '登陆' def logout(self): return '等处' def index(self): return '首页' def func(environ,start_response): start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')]) # obj = View() # 获取用户输入的URL method_name = environ.get('PATH_INFO').strip('/') if not hasattr(obj,method_name): return ["sdf".encode("utf-8"),] response = getattr(obj,method_name)() return [response.encode("utf-8") ] # 作用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。 server = make_server('192.168.12.87', 8000, func) server.serve_forever() ``` - setattr(对象,'变量','值') 根据字符串的形式去某个对象中设置成员 ```python class Foo: pass obj = Foo: obj.k1 = 999 setattr(obj,'k1',123) print(obj.k1) ``` - delattr(对象,'变量') 根据字符串的形式去某个对象中删除成员 ```python class Foo: pass obj = Foo() obj.k1 = 999 delattr(obj,'k1') print(obj.k1) ``` 反射获取 - 通过对象来获取实例变量、绑定方法 - 通过类来获取类变量、类方法、静态方法 - 通过模块名来过去模块中的任意变量 - 通过本文件来过去本文件中的任意模块 - getattr(sys.modules[__name__],'变量名') - python一切皆对象 - 包 - py文件 - 类 - 对象 python一切皆对象,所以以后想要通过字符串的形式操作内部成员都可以通过反射的机制实现 ### 7.10 模块:importlib 根据字符串的形式导入模块 ```pythn 模块 = importlib.import_module('utlis.redis') ``` ### 7.11 单例模式 - 无论实例化多少次,永远用的都是第一次实例化出来的对象 ```python class Foo: pass #多例,每实例化一次就会创建一个新的对象 obj1 = Foo() obj2 = Foo() #单例,无论实例化多少次,都是用的第一次创建的那个对象 ``` #### 7.11.1单例模式标准 ```python class Singleton(object): instance = None def __new__(cls,*args,**kwargs): if not cls.instance: cls.instance= object.__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() ``` 文件的连接池 ```python class Filehelper(object): instance = None def __init__(self,path) self.file_object = open(path,mode='r',encoding='utf-8') def __new__(cls,*args,**kwargs): if not cls.instance: cls.instance = object.__new__(cla) return cls.instance obj1 = Filehelper('x') obj2 = Filehelper('x') ``` 通过模块导入的特性也可以实现单例模式: ```python #jd.py class Foo: pass obj = Foo() ``` ```python #app.py import jd #加载jd.py,在加载最后会实例化一个Foo对象并赋值给obj print(jd.obj) ``` ### 7.12 日志 日志的处理本质 ```python file_handler1 = logging.FileHandler('x2.log', 'a', encoding='utf-8') fmt1 = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s") file_handler1.setFormatter(fmt1) logger = logging.Logger('xxxxxx', level=logging.ERROR) logger.addHandler(file_handler1) # logger.addHandler(file_handler2) logger.error('你好') ``` 基本格式 ```python logging.basicConfig( filename='wf.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=logging.ERROR ) #缺点是只能对一个文件进行操作(公司里不使用),推荐使用下面的的推荐方法 ``` 推荐处理日志方法 ```python import logging file_handler = logging.FileHandler(filename='x1.log',mode='a',encoding='utf-8') logging.basicConfig( format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s' datefmt = '%Y-%m-%d %H:%M:%S %p' handlers = [file_handler,], level=logging.ERROR ) logging.error('你好') ``` 推荐处理日志方式+日志分割 ```python import time import logging for logging import handlers file_handler = handlers.TimeRotatingFileHandler(filename ='x2.log',when='s',interval=5,encoding='utf-8') #这里的s是指以秒分割的基本单位,5是指每隔5秒分割一次 logging.basicConfig( format='%(asctime)s-%(name)s-%(levelname)s-%(module)s: %(message)s' datefmt='%Y-%m-%d %H:%M:%S %p' handlers=[file_handler,], level=logging.ERROR ) for i in range(1,1000): time.sleep(1) logging.error(str(i)) ``` ```python logging.basicConfig #使用方便 #不能实现编码问题:不能同时在文件和屏幕上输出 ``` logger对象的使用(文件屏幕同时输出) - 创建一个logger对象 - 创建一个文件操作 - 创建一个屏幕操作 - 创建一个格式 - 给logger对象绑定文件操作 - 给logger对象绑定屏幕操作 - 给文件操作符 设定格式 - 给屏幕操作符 设定格式 - 用logger对象来操作 ```python import logging logger = logging.getLogger() fh = logging.FileHandler('log.log') sh = logging.StreamHandler() logger.addHandler(fh) logger.addHandler(sh) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) sh.setFormatter(formatter) logger.warning('message') ``` 注意事项: ```python #在应用日志时候,如果想要保留异常的堆栈信息(其实就是报在第几行出去,出错原因是啥,就是pycharm的报错样式) import logging import requests logging.basicConfig( filename='wf.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=logging.ERROR ) try: requsts.get('http://www.xx.com') except Exception as e: msg = str(e)#调用e.__str__方法 logging.error(msg,exc_info=True) #转化成字符串后,加入exc_info=True即可 ``` ### 7.13 项目格式 项目名 - bin 主文件 - conf 配置 - src 业务逻辑 - db 数据文件 - lib 扩展模块 - log 日志文件 ## 第十三章 面试题 ### 1.默认参数 ```python - def func(a,b=[]) 有什么陷阱? - 看代码写结果 def func(a,b=[]) b.append(a) return b a1 = func(1) #[1] a1 = func(2,[11,22]) #[2,11,22] a1 = func(3) #[1,3] def func(a,b=[]): b.append(a) print(b) func(1) func(2,[11,22,33]) func(3) # [1] [11,22,33,2] [1,3] ``` ### 2 带参数的装饰器 ```python # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,并返回最后一次执行的结果【面试题】 def xxx(counter): print('x函数') def wrapper(func): print('wrapper函数') def inner(*args,**kwargs): for i in range(counter): data = func(*args,**kwargs) # 执行原函数并获取返回值 return data return inner return wrapper @xxx(5) def index(): return 8 v = index() print(v) ``` ### 3 sys.path.append("/root/mods")的作用 ```python #路径拼接,会将/root/mods 加入sys.path中,在python中模块路径找不到经常使用 ``` ### 4.字符串如何进行反转? ```python a = 'liudanni' list_a = [] for i in a: list_a.append(i) b = "".join(list_a[::-1]) print(b) ``` ### 5 不用中间变量交换a和b的值。 ```python a = 1 b = 2 a,b = b,a ``` ### 6*args和**kwargs这俩参数是什么意思?我们为什么要用它。 - ```python #*arg位置参数,可以传任意个数和任意内容的位置参数,功能齐全#**kwargs关键字参数,可以传任意个数和任意内容的位置参数,功能齐全 ``` ### 7.函数的参数传递是地址还是新值? - 地址 ### 8.看代码写结果: ```python my_dict = {'a':0,'b':1} def func(d): d['a'] = 1 return d func(my_dict) my_dict['c'] = 2 print(my_dict) #my_dict = {'c': 2, 'b': 1, 'a': 1} ``` ### 9.什么是lambda表达式 - 用来表示简单的函数,比如 ```python lambda x:x+100 ``` ### 10.range和xrang有什么不同? - ```python # #在python2中,rang() 和 xrang() 经常用来做for循环# 在python3中,去掉了python2中的 rang() ,把 xrang() 改成了 rang()# 所以python3中的 rang() 就是python2中的xrang()# rang是开辟一块内存来存列表,但是xrang是生成一个生成器,不断将内容加进去,占用的内存少 ``` ### 11."1,2,3" 如何变成 ['1','2','3',] ```python a = "1,2,3" b = a.split(",") print(b) ``` ### 12.['1','2','3'] 如何变成 [1,2,3] ```python a = ['1', '2', '3'] list_a = [] for i in a: list_a.append(int(i)) print(list_a) ``` ### 13.def f(a,b=[]) 这种写法有什么陷阱? ```python # 当传入的参数是默认的b=[]时候,b=[]是函数一开始就创建的,b并没有闭包# 当传入的参数b!=[]时候,就没啥影响 ``` 1. 如何生成列表 [1,4,9,16,25,36,49,64,81,100] ,尽量用一行实现。 ```python v = [i**2 for i in range(11)] ``` 1. python一行print出1~100偶数的列表, (列表推导式, filter均可) ```python v = [i for i in range(101) if i%2 ==0] ``` 1. 把下面函数改成lambda表达式形式 ``` def func(): result = [] for i in range(10): if i % 3 == 0: result.append(i) return result ``` 2. 如何用Python删除一个文件? ```python import sys #执行脚本时传入想要删除的文件路径 C:Python36python36.exe D:/code/s21day14/7.模块传参.py D:/test sys.argv = [D:/code/s21day14/7.模块传参.py, D:/test] path = sys.argv[1] import shutil shutil.rmtree(path) ``` 1. 如何对一个文件进行重命名? ```python import os os.rename('sb.txt','250,txt') ``` 1. python如何生成随机数? ```python import random a = random.randint(0,10) print(a) ``` 1. 从0-99这100个数中随机取出10个数,要求不能重复,可以自己设计数据结构。 ```python import random random_list = [] for i in range(10): a = random.randint(0,99) if a not in random_list: random_list.append(a) print(random_list) ``` 1. 用Python实现 9*9 乘法表 (两种方式) ``` for i in range(1,10): for j in range(1,i+1): print('%s*%s=%s' %(i,j,i*j,),end=" ") print() for i in range(1,10): y = 1 while i >= y: print('%s*%s=%s' %(i,y,i*y),end=" ") y += 1 print() ``` 1. 请给出下面代码片段的输出并阐述涉及的python相关机制。 ```python def dict_updater(k,v,dic={}): dic[k] = v print(dic) dict_updater('one',1) dict_updater('two',2) dict_updater('three',3,{}) {'one': 1} {'one': 1, 'two': 2} {'three': 3} #这个设计到闭包: #dic={}是在创建函数的时候就创建的,当没有传dic时,用的及时默认的,即创建函数式创建的 #如果传了dic相关的值,那么就相当于重新创建了一个 ``` 2. 写一个装饰器出来。 ```python def func(arg): def inner(*args,**kwargs): ret = arg(*args,**kwargs) return ret return inner @func def bar(): print(123) bar() ``` 1. 用装饰器给一个方法增加打印的功能。 ```python def func(arg): def inner(*args,**kwargs): print('打印') ret = arg(*args,**kwargs) print('打印') return ret return inner @func def bar(): print(123) bar() ``` 面试题:什么是鸭子模型 ```python #对于一个函数而言,python对于函数的参数类型不会限制,am传入的参数可以试各种形态,在函数中如果有:arg.send方法,那么就是对传入参数类型的一个限制 #这就是鸭子模型,类似于上述的函数我们认为只要呱呱叫的就是鸭子,只要能满足send方法就可以做参数 ``` 1. as 请写出log实现(主要功能时打印函数名) 看不懂这题 ```python @log def now(): print(inner) now() #答案 def func(): def inner(*args,**kwargs) ret = arg() return ret return inner ``` 2. 请列举经常访问的技术网站和博客 - 博客园 - CSDN 3. 请列举最近在关注的技术 - 爬虫 4. 请列举你认为不错的技术书籍和最近在看的书(不限于技术) - 青铜时代 - 温柔的夜 类变量的应用 ```python class Base: x = 1 obj = Base() print(obj.x) # 先去对象中找,没有再去类中找。 obj.y = 123 # 在对象中添加了一个y=123的变量。 print(obj.y) obj.x = 123 print(obj.x) print(Base.x) ```