Python.学习笔记.md
一、Python学习笔记
1. 第一章 计算机基础
1-1. 1.1 硬件
计算机基本的硬件由:CPU / 内存 / 主板 / 硬盘 / 网卡 / 显卡 等组成,只有硬件但硬件之间无法进行交流和通信。
1-2. 1.2 操作系统
操作系统用于协同或控制硬件之间进行工作,常见的操作系统有那些:
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。- windows
- win xp
- win7
- win10
- Windows sever
- linux
- centos 【公司线上一般用】
- Redhat 企业级
- Ubuntu 适合个人开发,图形化好
- mac
1-3. 1.3 解释器或编译器
编程语言的开发者写的一个工具,将用户写的代码转换成010101交给操作系统去执行。
1-3-1. 1.3.1 解释和编译型语言
解释型语言就类似于: 实时翻译,代表:Python / PHP / Ruby / Perl
编译型语言类似于:说完之后,整体再进行翻译,代表:C / C++ / Java / Go ...
1-4. 1.4 软件(应用程序)
软件又称为应用程序,就是我们在电脑上使用的工具,类似于:记事本 / 图片查看 / 游戏
1-5. 1.5 进制
对于计算机而言无论是文件存储 / 网络传输输入本质上都是:二进制(010101010101),如:电脑上存储视频/图片/文件都是二进制; QQ/微信聊天发送的表情/文字/语言/视频 也全部都是二进制。
进制:
- 2进制,计算机内部。
- 8进制, 逢8进1
- 10进制,人来进行使用一般情况下计算机可以获取10进制,然后再内部会自动转换成二进制并操作。
- 16进制,一般用于表示二进制(用更短的内容表示更多的数据),一版是:\x 开头。10-15:ABCDEF
1-6. 1.6 单位换算
1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B=8b
2. 第二章 Python入门
2-1. 2.1 环境的安装
-
解释器:py2 / py3 (环境变量)
- python 2.7.16(2020官方不再维护)
- python 3.6.8(推荐,不用最新版本)
最好安装在根目录下,如果同时安装2.7版本,更改解释器exe名字并做区分
Linux解释器路径 #!/usr/bin/env python
-
开发工具:pycharm
-
ctrl+?可以快速注释多行pycharm
-
Ctrl+D快速复制可以快速复制上一行
-
2-2. 2.2 编码
2-2-1. 2.2.1 编码基础
编码 | 简介 |
---|---|
ASCII | 英文及符号,8bit表示一内容,2**8=1byte |
Unicode | 万国码,32bit表示一内容,2**32=4byte |
UTF-8 | 压缩的Unicode,8bit为一单位,省去高位0. 中文:3byte=24bit |
GBK | 支持简体中文和繁体中文,中文是2字节 |
GB2312 | 简体中文 |
2-2-2. 2.2.2 python编码相关
对于Python默认解释器编码:
- py2: ascii
- py3: utf-8
如果想要修改默认编码,则可以使用:
# -*- coding:utf-8 -*-
注意:对于操作文件时,要按照:以什么编写写入,就要用什么编码去打开。
2-3. 2.3 变量
2-3-1. 2.3.1 变量的作用
为某个值创建一个“外号”,以后在使用时候通过此外号就可以直接调用。
2-3-2. 2.3.2变量命名要求
-
变量名只能包含:字母/数字/下划线
-
数字不能开头
-
不能是python的关键字。
[‘and’, ‘as’, ‘assert’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’,‘except’, ‘exec’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’,‘lambda’, ‘not’, ‘or’, ‘pass’, ‘print’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’,‘yield’]
-
建议:
-
见名知意: name = "alex" age= 18
-
用下划线连接:alex_dad = "吴佩其"
-
补充:AlexDad = '吴佩其' (驼峰式命名)
# 建议变量名不要用:str/int/list/tuple/set/dict/float # user_list = [11,22,33] # 推荐 # list = [11,22,33] # 不推荐 # list = 'alex' # v = (11,22,33) # v1 = list(v)
-
2-4. 2.4 注释
- 单行注释 #注释
- 多行注释 """注释"""
- 文件注释 文件开头"""内容"""
2-5. 2.5 输入输出
2-5-1. 2.5.1 语法格式
差别对比 | 输入 | 输出 |
---|---|---|
python2 | raw_input("输入") | print "输出" |
python3 | input("输入") | print("输出") |
注意:input()获取的数据类型为字符串
2-5-2. 2.5.2 格式化输出
-
%s: 字符串占位符
# 字符串格式化存在的意义 name = input('姓名:') do = input('在干什么:') template = "%s在教室,%s。" %(name,do,) #最后加逗号 print(template) # 直接做占位符 # template = "我是%s,年龄%s, 职业%s。" %("alex",73,'讲鸡汤',) # print(template)
-
%d: 整形站位符
# template = "我是%s,年龄%d, 职业%s。" %("alex",73,'讲鸡汤',) # print(template)
-
%%: 输出%
# name = 'alex' # template = "%s现在手机的电量是100%%" %(name,) # print(template)
-
练习
name = input('请输入姓名:') age = input('请输入年龄:') job = input('请输入职业:') hobby = input('请输入爱好:') msg = ''' ------------ info of Alex Li ---------- Name : %s Age : %s job : %s Hobbie: %s ------------- end ----------------''' data = msg %(name,age,job,hobby,) print(data)
-
特殊格式1
msg = "我是%s,年龄%s" %('alex',19,) print(msg) msg = "我是%(n1)s,年龄%(n2)s" % {'n1': 'alex', 'n2': 123, } print(msg)
-
特殊格式2
# v1 = "我是{0},年龄{1}".format('alex',19) v1 = "我是{0},年龄{1}".format(*('alex',19,)) print(v1) # v2 = "我是{name},年龄{age}".format(name='alex',age=18) v2 = "我是{name},年龄{age}".format(**{'name':'alex','age':18}) print(v2)
2-5-3. 2.6 运算符
2-5-4. 2.6.1算数运算符
+、-、*、/、%、**、//
# 练习题: 1 ~ 100 之间所有的数相加。
# total = 0
# count = 1
# while count <=100:
# total = total + count
# count = count + 1
# print(total)
# 练习题:打印 1 ~ 100 之间的奇数。
count = 1
while count <= 100:
val = count % 2
if val == 1:
print(count)
count = count + 1
2-5-5. 2.6.2 比较运算符
>/>=/</<=/==/!=
2-5-6. 2.6.3 赋值运算符
+=/-=
# count = 1
# while count <=100:
# print(count)
# count +=1 # count = count + 1
2-5-7. 2.6.4 逻辑运算符
and or not
- 一般用于判断
if 1 > 0 and 1 > 2:
print('666')
-
二般用于取值(面试)
- or
""" 对于 or,如果有遇到 value= 1 or 9 第一个值如果是转换成布尔值如果是真,则value=第一值。 第一个值如果是转换成布尔值如果是假,则value=第二值。 如果有多个or条件,则从左到右依次进行上述流程。 示例: v1 = 0 or 1 v2 = 8 or 10 v3 = 0 or 9 or 8 """
- and
"""对于and,如果遇到 value= 1 and 9 这种情况 如果第一个值转换成布尔值是True,则value=第二个值。 如果第一个值转换成布尔值是False,则value=第一个值。 如果有多个and条件,则从左到右依次进行上述流程。 示例: v1 = 1 and 9 v2 = 1 and 0 v3 = 0 and 7 v4 = 0 and "" v5 = 1 and 0 and 9 """
- 结合
# 先看and再看or # v1 = 1 and 9 or 0 and 6 # print(v1)
-
优先级
在没有()的情况下not 优先级高于 and,and优先级高于or,即优先级关系为()>not>and>or,同一优先级从左往右计算。
2-5-8. 2.6.5 成员运算
in/ not in
2-5-9. 2.6.6 优先级
算数>比较>赋值>逻辑(not>and>or)
2-5-10. 2.6.7 逗号运算符
- a,b=b,a 交换两个值
- a,b=取值
2-6. 2.7 流程控制
2-6-1. 2.7.1 if语句
# 请实现一个功能:让用户输入性别,如果是 男,则输出:
再见;如果是 女:则输出 来呀来呀;
gender = input("请输入性别:")
""" 如果是男生:打印再见 否则:打印来呀来呀 """
if gender == "男":
print('再见')
else:
print('来呀来呀')
2-6-2. 2.7.2 elif 条件
# 请实现一个功能:让用户输入性别,如果是 男,则输出:
再见;如果是 女:则输出 来呀来呀;如果是 人妖:找alex
去,他也是。否则:滚
gender = input("请输入性别:")
""" 如果是男生:打印再见 否则:打印来呀来呀 """
if gender == "男":
print('再见')
elif gender == '女':
print('来来来')
elif gender == '人妖':
print('找alex去,他也是')
else:
print('滚')
print('end')
# 第一题:让用户输入一个数字,猜:如果数字 > 50,则输
出:大了; 如果数字 <= 50 ,则输出:小了。
1
num = input('请输入一个数字')
number = int(num)
if number > 50:
print('大了')
else:
print('小了')
# 第二题:用户名密码登陆
username = input('请输入用户名:')
password = input('请输入密码:')
if username == 'alex' and password ==
"oldboy" :
print('欢迎登陆')
else:
print('用户名或密码错误')
2-7. 2.8 循环语句
2-7-1. 2.8.1 格式
while 条件语句:
执行语句
#打印1 2 3 4 5 6 8 9 10
""" count = 1 while count <= 10: if count != 7: print(count) count = count + 1"""
count = 1
while count <= 10:
if count == 7:
pass
else:
print(count)
count = count + 1
2-7-2. 2.8.2 关键字break
作用:终止当前循环.
while True:
print("你好")
while True:
print(666)
break
break
2-7-3. 2.8.2 关键字:continue
本次循环遇到continue,则不再继续往下走,返回条件语句继续判断.
count = 1
while count <=10:
print(count)
continue # 本次循环如果遇到continue,则不在继续往下走,而是回到while条件位置。
count = count + 1
# 示例:1234568910
count = 1
while count <=10:
if count == 7:
count = count + 1
continue
print(count)
count = count + 1
2-7-4. 2.8.3 while else 结构
""" count = 1 while count < 10: print(count) count = count + 1 else: # 不再满足while后的条件时,触发。 或 条件=False print('ELSE代码块') print('结束') """
""" count = 1 while True: print(count) if count == 10: break count = count + 1 else: # 不再满足while后的条件时,触发。 或 条件=False print('ELSE代码块') print('结束') """
2-7-5. 2.9 三元运算(三目运算)
v = 前面 if 条件 else 后面
if 条件:
v = '前面'
else:
v = '后面'
# 让用户输入值,如果值是整数,则转换成整数,否则赋值为None
data = input('>>>')
value = int(data) if data.isdecimal() else None
注意:先做出来,再思考如何简化。
3. 第三章 数据类型
3-1. 3.1 整型(int)
from __future__ import division
value = 3/2
print(value)
py2:有int和long,除法保留整数
py3只有int,结果保留所有
3-2. 3.2 布尔型(bool)
True
False
v1 = bool("hello")
v2 = bool("")
print(v1,v2)
转布尔型False: None 0 "" [] {} () set{}
3-3. 3.3 字符串(str)
字符串是写代码中最常见的,python内存中的字符串是按照:unicode 编码存储。对于字符串是不可变。
-
基本用法
-
加法拼接
a = '世界' b = '你好' print(a + b) # 结果:世界你好
-
单引号双引号三引号用法
s = """yinhaiping简写为'yhp'.""" print(s) #运行结果:yinhaiping简写为'yhp'.
-
乘法多次拼接连接
a = '坚强' print(a * 8) 结果:坚强坚强坚强坚强坚强坚强坚强坚强
-
常用方法
-
.upper() / .lower(): 将字母转换为大/小写
n='yinhaiping' na=n.upper() name=na.lower() print(na,name) #运行结果:YINHAIPING yinhaiping
v = 'ALEX'
v1 = v.upper()
print(v1)
v2 = v.isupper() # 判断是否全部是大写
print(v2)
v = 'alex'
v1 = v.lower()
print(v1)
v2 = v.islower() # 判断是否全部是小写
print(v2)
############ 了解即可
v = 'ß'
# 将字符串变小写(更牛逼)
v1 = v.casefold()
print(v1) # ss
v2 = v.lower()
print(v2)
-
.isdigit(): 判断字符串是不是数字
a='b' b="8" print(a.isdigit(),b.isdigit()) #运行结果:False True
v = 'alex' v1 = v.lower() print(v1) v2 = v.islower() # 判断是否全部是小写 print(v2) ############ 了解即可 v = 'ß' # 将字符串变小写(更牛逼) v1 = v.casefold() print(v1) # ss v2 = v.lower() print(v2)
-
.strip() / .lstrip() / .rstrip():去除字符串两端/左边/右边空格或换行
a=" >>>>>>\n" a=a.strip() b="YHP" print(a,b) #运行结果:>>>>>> YHP
v1 = "alex " print(v1.strip()) v2 = "alex\t" print(v2.strip()) v3 = "alex\n" print(v3.strip()) v1 = "alexa" print(v1.strip('al'))
-
.split():将字符串按指定格式分割为列表
s="yinhaiping" b=s.split("i") print(b) 运行结果:['y', 'nha', 'p', 'ng']
-
.replace("被替换的字符/子序列","要替换为的内容",1):替换字符
a="yinhaiping" b=a.replace(a[0:2],"YIN") c=a.replace("i","I",2) print(b,c) #运行结果:YINnhaiping yInhaIping
-
.startswith()/.endswith(): 判断是否以指定字符开头
a="yinhaiping" print(a.startswith("yin"),a.endswith("gn")) #运行结果:True False
-
.jion():循环字符串每个字符,按指定方式连接.例:"_".jion(str)
a="yinhaiping" b="-".join(a) print(b) #运行结果:y-i-n-h-a-i-p-i-n-g
-
.format():格式化赋值例:"你好{}".format(s)
a="你好{}".format("尹海平") print(a) #运行结果:你好尹海平
-
.encode():改变编码格式保存
a="尹海平" b=a.encode("gbk") c=b.decode("utf-8") print(a,b,c) #运行结果:尹海平 b'\xd2\xfc\xba\xa3\xc6\xbd' 尹海平
3-4. 3.4 列表(list)
-
基本格式:["str",int,bool]
-
特点:【有序,可变】
-
常用方法
-
.append(): 在列表最后追加元素
s=[1,2,3,"唱:","我爱北京"] s.append("天安门") print(s) #结果:[1, 2, 3, '唱:', '我爱北京', '天安门']
-
.insert(索引,"元素"): 在指定索引前加元素
s=[1,2,3,"唱:","我爱北京天安门"] s.insert(3,"预备") print(s) #结果:[1, 2, 3, '预备', '唱:', '我爱北京天安门']
-
.remove("需要删除的元素"): 直接删除指定元素
s=[1,2,3,"唱:","我爱北京天安门"] s.remove("唱:") print(s) #结果:[1, 2, 3, '我爱北京天安门']
-
.pop(索引): 删除索引的元素 ,可返回所删除元素值
s=[1,2,3,"唱:","我爱北京天安门"] b=s.pop(3) print(s,b) #结果:[1, 2, 3, '我爱北京天安门'] 唱:
-
.clear(): 清空所有元素
s=[1,2,3,"唱:","我爱北京天安门"] s.clear() print(s) #结果:[]
-
del:删除带索引的列表内容.例:del name[0]
s=[1,2,3,"唱:","我爱北京天安门"] del s[4] print(s) #结果:[1, 2, 3, '唱:']
-
.reverse():把列表反转
s=[1,2,3,4,5] s.reverse() print(s) #结果:[5, 4, 3, 2, 1]
-
.sort(): 排序,默认升序.降序:sort(reverse=True)
a=[5,8,6,99,81,] b=[5,8,6,99,81,] a.sort() b.sort(reverse=True) print(a,b) #结果:[5, 6, 8, 81, 99] [99, 81, 8, 6, 5]
-
.extend():批量追加另一个序列(str,list,tuple,dict(键),set)每个元素
s = "qwert" li = ["alex", "WuSir", "ritian", "barry", "wenzhou"] li.extend(s) print(li) # 输出:['alex', 'WuSir', 'ritian', 'barry', 'wenzhou', 'q', 'w', 'e', 'r', 't']
-
3-5. 3.5 元组(tuple)
-
基本格式:("str",int,bool)
-
特点:【有序,不可变】
-
自有方法【无】
注意:元素不可修改,嵌套的可变类型内元素可修改
3-6. 3.6 字典(dict)
-
基本格式:{键:值,键,值...}
-
特点:【键索引,可变】
-
常用方法
-
.keys(): 获取所有键
info = { "name":"尹海平","age":"保密","address":"北京","work":"码农" } info_keys = message.keys() for i in info_keys: print(i) #运行结果: name age address work
-
.values(): 获取所有值
info = { "name":"尹海平","age":"保密","address":"北京","work":"码农" } info_values = info.values() for i in info_values: print(i) #运行结果: 尹海平 保密 北京 码农
-
.items(): 获取所有键值对
info = { "name":"尹海平","age":"保密","address":"北京","work":"码农" } info_items = info.items() for i in info_items: print(i) #运行结果: ('name', '尹海平') ('age', '保密') ('address', '北京') ('work', '码农')
-
.get(键,返回值): 获取键对应的值,默认返回None
infos = { "name":"尹海平","age":"保密","address":"北京","work":"码农" } info = infos.get("name") info1=infos.get("addrss","不存在") print(info,info1) #运行结果: 尹海平 不存在
-
.pop(): 删除指定键值对
infos = { "name":"尹海平","age":"保密","address":"北京","work":"码农" } name=infos.pop("name") print(infos) #运行结果:{'age': '保密', 'address': '北京', 'work': '码农'}
-
.update(): 批量更新键值
infos = { "name":"尹海平","age":"保密","address":"北京","work":"码农" } info_new={"gender":"男","爱好":"女"} infos.update(info_new) print(infos) #运行结果:{'name': '尹海平', 'age': '保密', 'address': '北京', 'work': '码农', 'gender': '男', '爱好': '女'}
-
注意:字典中键是无序的,必须是可哈希数据类型(list/dict/set不能做键)
有序字典
from collections import OrderedDict
info = OrderedDict()
info['k1'] = 123
info['k2'] = 456
print(info.keys())
print(info.values())
print(info.items())
3-7. 3.7 集合(set)
-
基本格式:{str,int,bool,list...}空集合=set()
-
特点:【无序,可变,不重复】
-
常用方法
-
.add(): 添加元素
heros={"金克斯","盖伦","艾希"} heros.add("提莫") print(heros) #运行结果:{'提莫', '艾希', '盖伦', '金克斯'}
-
.update(): 批量添加
heros={"金克斯","盖伦","艾希"} new_heros={"塔姆","艾克","剑圣"} heros.update(new_heros) print(heros) #运行结果:{'艾希', '盖伦', '金克斯', '剑圣', '塔姆', '艾克'}
-
.discard(): 删除指定元素
heros={"金克斯","盖伦","艾希"} heros.discard("盖伦") print(heros) #运行结果:{'艾希', '金克斯'}
-
.intersection(): 取交集
heros={"金克斯","盖伦","艾希"} new_heros={"盖伦","剑圣","艾希"} nb_heros=heros.intersection(new_heros) print(nb_heros) #运行结果:{'艾希', '盖伦'}
-
.union(): 取并集
heros={"金克斯","盖伦","艾希"} new_heros={"盖伦","剑圣","艾希"} all_heros=heros.union(new_heros) print(all_heros) #运行结果:{'艾希', '剑圣', '金克斯', '盖伦'}
-
.difference(): 取差集
heros={"金克斯","盖伦","艾希"} new_heros={"盖伦","剑圣","艾希"} dft_heros=heros.difference(new_heros) dft1_heros=new_heros.difference(heros) print(dft_heros,dft1_heros) #运行结果:{'金克斯'} {'剑圣'}
-
.symmetric_difference():取对等差分集合,返回两个集合中不重复的元素集合
heros={"金克斯","盖伦","艾希"} new_heros={"盖伦","剑圣","艾希"} sym_heros=heros.difference(new_heros) print(sym_heros) #运行结果:{'金克斯'}
-
3-8. 3.8 公共方法
-
len(): 返回元素个数
可应用的数据类型有:str 字符串、list 列表、dict 字典、tuple 元组、set 集合
heros={"金克斯","盖伦","艾希"} num=len(heros) print(num) #y=运行结果:3
-
索引[num]: 左闭右开,左→右从0开始,从右→左从-1开始
可应用的数据类型有:str 字符串、list 列表、dict 字典、tuple 元组
heros=["金克斯","盖伦","艾希"] name=heros[1] name1=heros[-3] print(name,name1) #运行结果:盖伦 金克斯
-
切片[start:stop]: 左闭右开,反向加"-"
可应用的数据类型有:str 字符串、list 列表、tuple 元组
heros=["金克斯","盖伦","艾希","提莫","赵信"] name=heros[-4:-1] print(name) #运行结果:['盖伦', '艾希', '提莫']
-
步长[start:stop:step]: 默认为1,逆向取加"-"
可应用的数据类型有:str 字符串、list 列表、tuple 元组
heros=["金克斯","盖伦","艾希","提莫","赵信"] name=heros[-1:-4:-2] print(name) #运行结果:['赵信', '艾希']
-
del: 删除
可应用的数据类型有:list 列表、dict 字典
heros=["金克斯","盖伦","艾希","提莫","赵信"] del heros[3] print(heros) #运行结果:['金克斯', '盖伦', '艾希', '赵信']
-
.update(): 批量增加
可应用的数据类型有:list 列表、dict 字典、set集合
heros={"金克斯","盖伦","艾希"} new_heros={"塔姆","艾克","剑圣"} heros.update(new_heros) print(heros) #运行结果:{'艾希', '盖伦', '金克斯', '剑圣', '塔姆', '艾克'}
4. 第四章 文件操作
4-1. 4.1 文件基本操作
obj = open('路径',mode='模式',encoding='编码')
obj.write()
obj.read()
obj.close()
4-2. 4.2 打开模式
- r / w / a
- r+ / w+ / a+
- rb / wb / ab
- r+b / w+b / a+b
4-3. 4.3 操作
-
read() , 全部读到内存
-
read(1)
-
1表示一个字符
obj = open('a.txt',mode='r',encoding='utf-8') data = obj.read(1) # 1个字符 obj.close() print(data)
-
1表示一个字节
obj = open('a.txt',mode='rb') data = obj.read(3) # 1个字节 obj.close()
-
-
write(字符串)
obj = open('a.txt',mode='w',encoding='utf-8') obj.write('中午你') obj.close()
-
write(二进制)
obj = open('a.txt',mode='wb') # obj.write('中午你'.encode('utf-8')) v = '中午你'.encode('utf-8') obj.write(v) obj.close()
-
seek(光标字节位置),无论模式是否带b,都是按照字节进行处理。
obj = open('a.txt',mode='r',encoding='utf-8') obj.seek(3) # 跳转到指定字节位置 data = obj.read() obj.close() print(data) obj = open('a.txt',mode='rb') obj.seek(3) # 跳转到指定字节位置 data = obj.read() obj.close() print(data)
-
tell(), 获取光标当前所在的字节位置
obj = open('a.txt',mode='rb') # obj.seek(3) # 跳转到指定字节位置 obj.read() data = obj.tell() print(data) obj.close()
-
flush,强制将内存中的数据写入到硬盘
v = open('a.txt',mode='a',encoding='utf-8') while True: val = input('请输入:') v.write(val) v.flush() v.close()
4-4. 4.4 关闭文件
文艺青年
v = open('a.txt',mode='a',encoding='utf-8')
v.close()
二逼
with open('a.txt',mode='a',encoding='utf-8') as v:
data = v.read()
# 缩进中的代码执行完毕后,自动关闭文件
4-5. 4.5 文件内容的修改
with open('a.txt',mode='r',encoding='utf-8') as f1:
data = f1.read()
new_data = data.replace('飞洒','666')
with open('a.txt',mode='w',encoding='utf-8') as f1:
data = f1.write(new_data)
大文件修改
f1 = open('a.txt',mode='r',encoding='utf-8')
f2 = open('b.txt',mode='w',encoding='utf-8')
for line in f1:
new_line = line.replace('阿斯','死啊')
f2.write(new_line)
f1.close()
f2.close()
with open('a.txt',mode='r',encoding='utf-8') as f1, open('c.txt',mode='w',encoding='utf-8') as f2:
for line in f1:
new_line = line.replace('阿斯', '死啊')
f2.write(new_line)
5.
6. 第五章 函数
截至目前:面向过程编程。 【可读性差/可重用性差】。
写代码的方式:面向过程 --> 函数式编程(多) --> 面向对象编程。
对于函数编程:
- 本质:将N行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码并执行。
- 场景:
- 代码重复执行。
- 代码量特别多超过一屏,可以选择通过函数进行代码的分割。
6-1. 5.1函数的基本结构
# 函数的定义
def 函数名():
# 函数内容
pass
# 函数的执行
函数名()
def get_list_first_data():
v = [11,22,33,44]
print(v[0])
get_list_first_data()
# 注意:函数如果不被调用,则内部代码永远不会被执行。
# 假如:管理员/业务员/老板用的是同一个邮箱。
def send_email():
print('发送邮件成功,假设有10含代码')
user_input = input('请输入角色:')
if user_input == '管理员':
send_email()
elif user_input == '业务员':
send_email()
elif user_input == '老板':
send_email()
6-2. 5.2 参数
6-2-1. 5.2.1参数格式与种类
- 函数可以传递任意数据类型,任意个数的参数
def func(a1,a2,a3):# a1,a2,a3叫形式参数(形参)
print(a1,a2,a3)
func(1,"asdf",True)#调用时传递的参数叫实际参数(实参)
- 位置传参(调用函数语句)
def func(a1,a2):
print(a1,a2)
func(1,3)
- 关键字传参(调用函数语句)
def func(a1, a2):
print(a1, a2)
func(a2=99,a1=2)
# 关键字传参数和位置传参可以混合使用,位置传入的参数在前,关键字参数在后
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) # 错误
-
参数默认值
编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。
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)
函数的默认值慎用可变类型
# 如果要想给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]
面试题:
-
def func(a,b=[]) 有什么陷阱?
-
看代码写结果
def func(a,b=[]): b.append(a) return b l1 = func(1) l2 = func(2,[11,22]) l3 = func(3) # [1,3] [11,22,2] [1,3] print(l1,l2,l3)
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]
-
-
万能参数(打散)
-
*args
-
可以接受任意个数的位置参数,并将参数转换成元组。
- 调用函数无 *
def func(*args): print(args) func(1,2,3,4)
-
调用函数有 *
循环列表的每个元素传入函数
def func(*args): print(args) func(*(1,2,3,4)) func(*[1,2,3,4])
-
-
只能用位置传参
def func(*args): print(args) # func(1) # func(1,2) func(1,2) # args=(1, 2) func((11,22,33,44,55)) # args=((11,22,33,44,55),) func(*(11,22,33,44,55)) # args=(11,22,33,44,55)
-
**kwargs
-
可以接受任意个数的关键字参数,并将参数转换成字典。
-
调用函数无 **
def func(**kwargs): print(kwargs) func(k1=1,k2="alex")
-
调用函数有**
循环字典的每个键值对传入函数
def func(**kwargs): print(kwargs) func(**{'k1':'v2','k2':'v2'}) # kwargs={'k1':'v2','k2':'v2'}
-
-
只能用关键字传参
-
综合应用:无敌 + 无敌 => 真无敌
def func(*args,**kwargs): print(args,kwargs) # func(1,2,3,4,5,k1=2,k5=9,k19=999) func(*[1,2,3],k1=2,k5=9,k19=999) func(*[1,2,3],**{'k1':1,'k2':3}) func(111,222,*[1,2,3],k11='alex',**{'k1':1,'k2':3})
-
参数相关重点:
- 定义函数
def func1(a1,a2): pass def func2(a1,a2=None): pass def func3(*args,**kwargs): pass
- 调用函数
位置参数 > 关键字参数
-
6-2-2. 5.2.2 作用域
python中:
- py文件:全局作用域
- 函数:局部作用域
a = 1
def s1(): #注意:在调用之前选择参数值到底是多少.
x1 = 666
print(x1)
print(a)
print(b)
b = 2
print(a) #1
s1() #666\n 1\n2
a = 88888
def s2():
print(a,b)
s1()
s2() #88888 2 #666\n 88888\n2
总结:
-
一个函数是一个作用域
def func(): x = 9 print(x) func() print(x)
-
作用域中查找数据规则:优先在自己的作用域找数据,自己没有就去 "父级" -> "父级" -> 直到全局,全部么有就报错。注意:父级作用域中的值到底是什么?
x = 10 def func(): x = 9 print(x) func()
注意:函数参数取决于调用时的参数值而不是定义时的值
-
子作用域中只能 找到父级中的值 ,默认无法重新为父级的变量进行赋值。(global/nonlocal可以强制做)
# ##################### name = 'oldboy' def func(): name = 'alex' # 在自己作用域再创建一个这样的值。 print(name) func() print(name) # ##################### name = [1,2,43] def func(): name.append(999) print(name) func() print(name) # ###################### 如果非要对全局的变量进行赋值 # 示例一 name = ["老男孩",'alex'] def func(): global name name = '我' func() print(name) # 示例一 name = "老男孩" def func(): name = 'alex' def inner(): global name name = 999 inner() print(name) func() print(name) name = "老男孩" def func(): name = 'alex' def inner(): global name name = 999 inner() print(name) func() print(name) # ############################## nonlocal name = "老男孩" def func(): name = 'alex' def inner(): nonlocal name # 找到上一级的name name = 999 inner() print(name) func() print(name)
练习题
# 1. 请写一个函数,函数计算列表 info = [11,22,33,44,55] 中所有元素的和。
def get_sum():
info = [11,22,33,44,55]
data = 0
for item in info:
data += item
print(data)
get_sum()
# 2. 请写一个函数,函数计算列表中所有元素的和。
def get_list_sum(a1):
data = 0
for item in a1:
data += item
print(data)
get_list_sum([11,22,33])
get_list_sum([99,77,66])
v1 = [8712,123,123]
get_list_sum(v1)
# 3. 请写一个函数,函数将两个列表拼接起来。
def join_list(a1,a2):
result = []
result.extend(a1)
result.extend(a2)
print(result)
join_list([11,22,33],[55,66,77]
# 4. 计算一个列表的长度
def my_len(arg):
count = 0
for item in arg:
count += 1
print(count)
v = [11,22,33]
my_len(v)
len(v)
# 5. 发邮件的示例
def send_email(role,to):
template = "要给%s%s发送邮件" %(role,to,)
print(template)
user_input = input('请输入角色:')
if user_input == '管理员':
send_email('管理员','xxxx@qq.com')
elif user_input == '业务员':
send_email('业务员','xxxxo@qq.com')
elif user_input == '老板':
send_email('老板','xoxox@qq.com')
6-3. 5.3 返回值
def func(arg):
# ....
return 9 # 返回值为9 默认:return None
val = func('adsfadsf')
# 1. 让用户输入一段字符串,计算字符串中有多少A字符的个数。有多少个就在文件a.txt中写多少个“李邵奇”。
def get_char_count(data):
sum_counter = 0
for i in data:
if i == 'A':
sum_counter += 1
return sum_counter
def write_file(line):
if len(line) == 0:
return False # 函数执行过程中,一旦遇到return,则停止函数的执行。
with open('a.txt',mode='w',encoding='utf-8') as f:
f.write(line)
return True
content = input('请输入:')
counter = get_char_count(content)
write_data = "李邵奇" * counter
status = write_file(write_data)
if status:
print('写入成功')
else:
print('写入失败')
6-4. 5.4 上述总结
# 情况1
def f1():
pass
f1()
# 情况2
def f2(a1):
pass
f2(123)
# 情况3
def f3():
return 1
v1 = f3()
# 情况4
def f4(a1,a2):
# ...
return 999
v2 = f4(1,7)
6-5. 5.5 练习题
# 1. 写函数,计算一个列表中有多少个数字,打印: 列表中有%s个数字。
# 提示:type('x') == int 判断是否是数字。
""" # 方式一: def get_list_counter1(data_list): count = 0 for item in data_list: if type(item) == int: count += 1 msg = "列表中有%s个数字" %(count,) print(msg) get_list_counter1([1,22,3,'alex',8]) # 方式二: def get_list_counter2(data_list): count = 0 for item in data_list: if type(item) == int: count += 1 return count v = get_list_counter1([1,22,3,'alex',8]) msg = "列表中有%s个数字" %(v,) print(msg) """
# 2. 写函数,计算一个列表中偶数索引位置的数据构造成另外一个列表,并返回。
""" # 方式一: def get_data_list1(arg): v = arg[::2] return v data = get_data_list1([11,22,33,44,55,66]) # 方式二: def get_data_list2(arg): v = [] for i in range(0,len(arg)): if i % 2 == 0: v.append(arg[i]) return v data = get_data_list2([11,22,33,44,55,66]) """
# 3. 读取文件,将文件的内容构造成指定格式的数据,并返回。
""" a.log文件 alex|123|18 eric|uiuf|19 ... 目标结构: a. ["alex|123|18","eric|uiuf|19"] 并返回。 b. [['alex','123','18'],['eric','uiuf','19']] c. [ {'name':'alex','pwd':'123','age':'18'}, {'name':'eric','pwd':'uiuf','age':'19'}, ] """
def lst(f):
a = []
for line in f:
new_line = line.strip()
a.append(new_line)
return a
def list_lst(f):
b = []
f.seek(0)
for line in f:
new_line = line.strip()
li = new_line.split("|")
b.append(li)
return b
def dit(f):
c = []
f.seek(0)
for line in f:
dic = {}
new_line = line.strip()
li = new_line.split("|")
dic["name"] = li[0]
dic["pwd"] = li[1]
dic["age"] = li[2]
c.append(dic)
return c
with open('a.txt', mode='r', encoding='utf-8') as f:
a = lst(f)
b = list_lst(f)
c = dit(f)
print(a, "\n", b, "\n", c)
6-6. 5.6 函数变量
函数本身也是一种数据类型,函数名对应程序入口地址
6-6-1. 5.6.1 函数名当作变量来使用
def func():
print(123)
v1 = func #函数名可以赋值给其他变量,来指向函数
func()
v1() #函数加()才会执行
#123
#123
def func():
print(123)
func_list = [func, func, func]
for item in func_list:
v = item()
print(v)
6-6-2. 5.6.2 函数可以当作参数进行传递
def func(arg):
v1 = arg()
print(v1)
def show():
print(666)
func(show)
#666
#None
def func(arg):
v1 = arg()
print(v1)
def show():
print(666)
result = func(show)
print(result)
# 面试题
def func():
print('花费查询')
def bar():
print('语音沟通')
def base():
print('xxx')
def show():
print('xxx')
def test():
print('xxx')
info = {
'f1': func,
'f2': bar,
'f3':base,
'f4':show,
'f5':test
}
choice = input('请选择要选择功能:')
function_name = info.get(choice)
if function_name:
function_name()
else:
print('输入错误')
6-6-3. 5.6.3 函数可以做返回值
函数被调用,开辟一块内存空间执行,同时被调用开辟不同的内存空间,之间不会混乱,执行完毕后释放内存.
def func():
print(123)
def bar():
return func
v = bar()
v()
name = 'oldboy'
def func():
print(name)
def bar():
return func
v = bar()
v()
name = 'oldboy'
def bar(name):
def inner():
print(name)
return inner
v1 = bar('alex') # { name=alex, inner } # 闭包,为函数创建一块区域(内部变量供自己使用),为他以后执行提供数据。
v2 = bar('eric') # { name=eric, inner }
v1()
v2()
6-6-4. 5.6.4 闭包
闭包概念:为函数创建一块区域并为其维护自己数据,以后执行时方便调用。【应用场景:装饰器 / SQLAlchemy源码】
def func(name):
def inner():
print(name)
return inner
v1 = func('alex')
v1()
v2 = func('eric')
v2()
info = []
def func(i):
def inner():
print(i)
return inner
for item in range(10):
info.append(func(item))
info[0]()
info[1]()
info[4]()
def x(func):
def inner(a1,a2):
return func()
return inner
@x
def index():
pass
# func = 原来的index函数u
# index = inner
index(1,2)
- 关于返回值
def x1(func):
def inner(*args,**kwargs):
data = func(*args,**kwargs)
return data
return inner
@x1
def f1():
print(123)
return 666
v1 = f1()
print(v1)
def x1(func):
def inner(*args,**kwargs):
data = func(*args,**kwargs)
return inner
@x1
def f1():
print(123)
return 666
v1 = f1()
print(v1)
-
关于前后
def x1(func): def inner(*args,**kwargs): print('调用原函数之前') data = func(*args,**kwargs) # 执行原函数并获取返回值 print('调用员函数之后') return data return inner @x1 def index(): print(123) index()
-
带参数的装饰器(flask框架 + django缓存 + 写装饰器实现被装饰的函数要执行N次)
# 第一步:执行 ret = xxx(index) # 第二步:将返回值赋值给 index = ret @xxx def index(): pass # 第一步:执行 v1 = uuu(9) # 第二步:ret = v1(index) # 第三步:index = ret @uuu(9) def index(): pass
# 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,把每次结果添加到列表中,最终返回列表。 def xxx(counter): print('x函数') def wrapper(func): print('wrapper函数') def inner(*args,**kwargs): v = [] for i in range(counter): data = func(*args,**kwargs) # 执行原函数并获取返回值 v.append(data) return v return inner return wrapper @xxx(5) def index(): return 8 v = index() print(v)
6-7. 5.7 lambda表达式
用于表示简单的函数,也称作匿名函数。
# 三元运算,为了解决简单的if else的情况,如:
if 1 == 1:
a = 123
else:
a = 456
a = 123 if 1 == 1 else 456
# lambda表达式,为了解决简单函数的情况,如:
def func(a1,a2):
return a1 + 100
func = lambda a1,a2: a1+100
func1 = lambda : 100
func2 = lambda x1: x1 * 10
func3 = lambda *args,**kwargs: len(args) + len(kwargs)
总结:列表所有方法基本上都是返回None;字符串的所有方法基本上都是返回新值
6-8. 5.8 内置函数
-
输入输出
- input
-
强制转换
- int()
- bool()
- list()
- str()
- tuple()
- dict()
- set()
-
数学相关
-
abs() 绝对值
-
float() 转换成浮点数
-
max() 找到最大值
-
min() 找到最小值
-
sum() 求和
-
pow() 乘方
v = pow(2,3) print(v)# 2的3次方
-
round
v = round(1.127,2) print(v) #四舍五入保留几位小数
-
divmod() 两数相除的商和余数
a,b = divmod(1001,5) print(a,b)
# 练习题 请通过分页对数据进行展示 """ 要求: 每页显示10条数据 让用户输入要查看的页面:页码 """ USER_LIST = [] for i in range(1,836): temp = {'name':'你少妻-%s' %i,'email':'123%s@qq.com' %i } USER_LIST.append(temp) # 数据总条数 total_count = len(USER_LIST) # 每页显示10条 per_page_count= 10 # 总页码数 max_page_num,a = divmod(total_count,per_page_count) if a>0: max_page_num += 1 while True: pager = int(input('要查看第几页:')) if pager < 1 or pager > max_page_num: print('页码不合法,必须是 1 ~ %s' %max_page_num ) else: """ # 第1页:USER_LIST[0:10] -> 0123456789 # 第2页:USER_LIST[10:20] # 第3页:USER_LIST[20:30] ... """ start = (pager-1) * per_page_count end = pager * per_page_count data = USER_LIST[start:end] for item in data: print(item)
-
-
进制转换相关
-
bin,将十进制转化成二进制
num = 13 v1 = bin(num) print(v1)
-
oct,将十进制转换成八进制
num = 8 v1 = oct(num) print(v1)
-
int,将其他进制转化成十进制
# 二进制转化成十进制 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,将十进制转换成十六进制
num = 16 v1 = hex(num) print(v1)
-
面试题
# 1字节等于8位 # IP: 192.168.12.79 -> 001010010 . 001010010 . 001010010 . 001010010 # 1. 请将 ip = "192.168.12.79" 中的每个十进制数转换成二进制并通过,连接起来生成一个新的字符串。 ip = "192.168.12.79" ip_list = ip.split('.') # ['192','168','12','79'] result = [] for item in ip_list: result.append(bin(int(item))) print(','.join(result)) # 2. 请将 ip = "192.168.12.79" 中的每个十进制数转换成二进制: # 0010100100001010010001010010001010010 -> 十进制的值。 # 3232238671 ip='192.168.12.79' bit_str='' ip_list=ip.split(".") for i in ip_list: bit=bin(int(i))[2:] long=len(bit) if long<8: bit=(8-long)*"0"+bit bit_str+=''.join(bit) num=int(bit_str,base=2) print(num)
-
-
编码相关
-
chr,将十进制数字转换成 unicode 编码中的对应字符串。
v = chr(99) print(v)
-
ord,根据字符在unicode编码中找到其对应的十进制。
num = ord('中')
-
应用:random模块
import random def get_random_code(length=6): data = [] for i in range(length): v = random.randint(65,90) data.append(chr(v)) return ''.join(data) code = get_random_code() print(code)
import random # 导入一个模块 v = random.randint(起始,终止) # 得到一个随机数
-
-
高级一点的内置函数
-
map,循环每个元素(第二个参数),然后让每个元素执行函数(第一个参数),将每个函数执行的结果保存到新的列表中,并返回。map(批量操作函数,序列)
v1 = [11,22,33,44] result = map(lambda x:x+100,v1) print(list(result)) # 特殊
-
filter filter(判断条件,序列)
v1 = [11,22,33,'asd',44,'xf'] def func(x): if type(x) == int: return True return False result = filter(func,v1) # [11,] print(list(result)) result = filter(lambda x: True if type(x) == int else False ,v1) print(list(result)) result = filter(lambda x: type(x) == int ,v1) print(list(result))
-
reduce
import functools v1 = ['wo','hao','e'] def func(x,y): return x+y result = functools.reduce(func,v1) print(result) result = functools.reduce(lambda x,y:x+y,v1) print(result)
-
6-9. 5.10 装饰器
装饰器:在不改变原函数内部代码的基础上,在函数执行之前和之后自动执行某个功能。
def func(arg):
def inner():
v = arg()
return v
return inner
# 第一步:执行func函数并将下面的函数参数传递,相当于:func(index)
# 第二步:将func的返回值重新赋值给下面的函数名。 index = func(index)
@func
def index():
print(123)
return 666
print(index)
# ################## 普通装饰器 #####################
def wrapper(func):
def inner(*args,**kwargs):
print('调用原函数之前')
data = func(*args,**kwargs) # 执行原函数并获取返回值
print('调用员函数之后')
return data
return inner
@wrapper
def index():
pass
# ################## 带参数装饰器 #####################
def x(counter):
def wrapper(func):
def inner(*args,**kwargs):
data = func(*args,**kwargs) # 执行原函数并获取返回值
return data
return inner
return wrapper
@x(9)
def index():
pass
编写装饰器 和应用
# 装饰器的编写
def x(func):
def y():
# 前
ret = func()
# 后
return ret
return y
# 装饰器的应用
@x
def index():
return 10
@x
def manage():
pass
# 执行函数,自动触发装饰器了
v = index()
print(v)
-
应用场景:想要为函数扩展功能时,可以选择用装饰器。
-
记住:
-
装饰器建议编写格式
def 外层函数(参数): def 内层函数(*args,**kwargs): return 参数(*args,**kwargs) return 内层函数
-
装饰器应用格式
@外层函数 def index(): pass index()
-
问题:为什么要加 *args, **kwargs
-
6-10. 5.11 迭代器
自己不会写迭代器,只用。
任务:请展示列表中所有的数据。
-
while + 索引 + 计数器
-
迭代器,对 某种对象(str/list/tuple/dict/set类创建的对象)-可迭代对象 中的元素进行逐一获取,表象:具有
__next__
方法且每次调用都获取可迭代对象中的元素(从前到后一个一个获取)。-
列表转换成迭代器:
- v1 = iter([11,22,33,44])
v1 = [11,22,33,44].__iter__()
-
迭代器想要获取每个值:反复调用
val = v1.__next__()
v1 = [11,22,33,44] # 列表转换成迭代器 v2 = iter(v1) result1 = v2.__next__() print(result1) result2 = v2.__next__() print(result2) result3 = v2.__next__() print(result3) result4 = v2.__next__() print(result4) result5 = v2.__next__() print(result5) """ # v1 = "alex" # v2 = iter(v1) # while True: # try: # val = v2.__next__() # print(val) # except Exception as e: # break
-
直到报错:StopIteration错误,表示已经迭代完毕。
-
如何判别一个对象是否是迭代器:内部是否有
__next__方法
。
-
-
for循环
v1 = [11,22,33,44] # 1.内部会将v1转换成迭代器 # 2.内部反复执行 迭代器.__next__() # 3.取完不报错 for item in v1: print(item)
-
可迭代对象
- 内部具有
__iter__()
方法且返回一个迭代器。(*)
v1 = [11,22,33,44] result = v1.__iter__()
- 可以被for循环
- 内部具有
6-11. 5.12 生成器(函数的变异)
# 函数
def func():
return 123
func()
# 生成器函数(内部是否包含yield)
def func():
print('F1')
yield 1
print('F2')
yield 2
print('F3')
yield 100
print('F4')
# 函数内部代码不会执行,返回一个 生成器对象 。
v1 = func()
# 生成器是可以被for循环,一旦开始循环那么函数内部代码就会开始执行。
for item in v1:
print(item)
def func():
count = 1
while True:
yield count
count += 1
val = func()
for item in val:
print(item)
总结:函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部的代码才会执行,每次循环都会获取yield返回的值。
def func():
count = 1
while True:
yield count
count += 1
if count == 100:
return
val = func()
for item in val:
print(item)
示例:读文件
def func():
"""
分批去读取文件中的内容,将文件的内容返回给调用者。
:return:
"""
cursor = 0
while True:
f = open('db', 'r', encoding='utf-8')# 通过网络连接上redis
# 代指 redis[0:10]
f.seek(cursor)
data_list =[]
for i in range(10):
line = f.readline()
if not line:
return
data_list.append(line)
cursor = f.tell()
f.close() # 关闭与redis的连接
for row in data_list:
yield row
for item in func():
print(item)
其他知识:
- yeild from关键字【欠】
- 生成器推导式【欠】
6-12. 5.13 推导式
-
列表推导式
""" 目的:方便的生成一个列表。 格式: v1 = [i for i in 可迭代对象 ] v2 = [i for i in 可迭代对象 if 条件 ] # 条件为true才进行append """ v1 = [ i for i in 'alex' ] v2 = [i+100 for i in range(10)] v3 = [99 if i>5 else 66 for i in range(10)] def func(): return 100 v4 = [func for i in range(10)] v5 = [lambda : 100 for i in range(10)] result = v5[9]() def func(): return i v6 = [func for i in range(10)] result = v6[5]() v7 = [lambda :i for i in range(10)] result = v7[5]() 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] # ##################### 筛选 ######################### v9 = [i for i in range(10) if i > 5]
-
集合推导式
v1 = { i for i in 'alex' }
注意:重复值会被覆盖
-
字典推导式
v1 = { 'k'+str(i):i for i in range(10) }
注意:键值重复会被覆盖
6-13. 5.14 递归
函数自己调用自己。(效率低)
def func():
print(1)
func()
func()
def func(a,b):
print(b)
func(b,a+b)
func(0,1) #1 1 2 3 5
def func(a):
if a == 5:
return 100000 # 注意递归的返回值
result = func(a+1) + 10
return result
v = func(1) #100040
7. 第六章 模块(类库)
模块分类
-
内置模块-----python内部提供的功能
-
第三方模块-----下载/安装/使用
# 把pip.exe 所在的目录添加到环境变量中。 pip install 要安装的模块名称 # pip install xlrd #报错更新 python36 -m pip install --upgrade pip
-
自定义模块
7-1. 6.1 内置模块
7-1-1. 6.1.1 sys
python解释器相关的数据。
-
sys.getrefcount , 获取一个值的引用计数
a = [11,22,33] b = a print(sys.getrefcount(a))
-
sys.getrecursionlimit , python默认支持的递归数量
-
sys.stdout.write --> print
import time for i in range(1,101): msg = "%s%%\r" %i print(msg,end='') time.sleep(0.05)
import os # 1. 读取文件大小(字节) file_size = os.stat('20190409_192149.mp4').st_size # 2.一点一点的读取文件 read_size = 0 with open('20190409_192149.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='')
-
sys.argv(常用)
#!/usr/bin/env python # -*- coding:utf-8 -*- """ 让用户执行脚本传入要删除的文件路径,在内部帮助将目录删除。 C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py D:/test C:\Python36\python36.exe D:/code/s21day14/7.模块传参.py """ import sys # 获取用户执行脚本时,传入的参数。 # C:\Python36\python36.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)
-
sys.path ---默认Python去导入模块时,会按照sys.path中的路径挨个查找。
# import sys # sys.path.append('D:\\') # import oldboy
-
sys.exit(0)退出程序
7-1-2. 6.1.2 os
和操作系统相关的数据。
-
os.path.exists(path) , 如果path存在,返回True;如果path不存在,返回False
-
os.stat('20190409_192149.mp4').st_size , 获取文件大小
-
os.path.abspath() , 获取一个文件的绝对路径
path = '20190409_192149.mp4' # D:\code\s21day14\20190409_192149.mp4 import os v1 = os.path.abspath(path) print(v1)
-
os.path.dirname ,获取路径的上级目录
import os v = r"D:\code\s21day14\20190409_192149.mp4" print(os.path.dirname(v))
-
os.path.join ,路径的拼接
import os path = "D:\code\s21day14" # 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 , 查看一个目录下所有的文件【第一层】
import os result = os.listdir(r'D:\code\s21day14') for path in result: print(path)
-
os.walk , 查看一个目录下所有的文件【所有层】
import os result = os.walk(r'D:\code\s21day14') for a,b,c in result: # a,正在查看的目录 b,此目录下的文件夹 c,此目录下的文件 for item in c: path = os.path.join(a,item) print(path)
-
os.makedirs,创建目录和子目录
import os file_path = r'db\xx\xo\xxxxx.txt' file_folder = os.path.dirname(file_path) if not os.path.exists(file_folder): os.makedirs(file_folder) with open(file_path,mode='w',encoding='utf-8') as f: f.write('asdf')
-
os.rename,重命名
import os os.rename('db','sb')
-
补充:
-
转义
v1 = r"D:\code\s21day14\n1.mp4" (推荐) print(v1) v2 = "D:\\code\\s21day14\\n1.mp4" print(v2)
-
7-1-3. 6.1.3 shutil
import shutil
# 删除目录
# shutil.rmtree('test')
# 重命名
# shutil.move('test','ttt')
# 压缩文件
# shutil.make_archive('zzh','zip','D:\code\s21day16\lizhong')
# 解压文件
# shutil.unpack_archive('zzh.zip',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')
实例
import os
import shutil
from datetime import datetime
ctime = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
# 1.压缩lizhongwei文件夹 zip
# 2.放到到 code 目录(默认不存在)
# 3.将文件解压到D:\x1目录中。
if not os.path.exists('code'):
os.makedirs('code')
shutil.make_archive(os.path.join('code',ctime),'zip','D:\code\s21day16\lizhongwei')
file_path = os.path.join('code',ctime) + '.zip'
shutil.unpack_archive(file_path,r'D:\x1','zip')
7-1-4. 6.1.4 json★
json是一个特殊的字符串。 【长的像列表/字典/字符串/数字/真假】
- dumps序列化 & load反序列化
import json
# 序列化,将python的值转换为json格式的字符串。
# v = [12,3,4,{'k1':'v1'},True,'asdf']
# v1 = json.dumps(v)
# print(v1)
# 反序列化,将json格式的字符串转换成python的数据类型
# v2 = '["alex",123]'
# print(type(v2))
# v3 = json.loads(v2)
# print(v3,type(v3))
-
json.dumps 序列化时对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False:
v = {'k1':'alex','k2':'李杰'} import json val = json.dumps(v,ensure_ascii=False) print(val)
-
dump序列化并写入文件
import json v = {'k1':'alex','k2':'李杰'} f = open('x.txt',mode='w',encoding='utf-8') val = json.dump(v,f) print(val) f.close()
-
load从文件读取并反序列化
import json v = {'k1':'alex','k2':'李杰'} f = open('x.txt',mode='r',encoding='utf-8') data = json.load(f) f.close() print(data,type(data)
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
7-1-5. 6.1.5 pickle
-
json,优点:所有语言通用;缺点:只能序列化基本的数据类型 list/dict/int...
-
pickle,优点:python中所有的东西都能被他序列化(socket对象);缺点:序列化的内容只有python认识。
import pickle # #################### dumps/loads ###################### """ v = {1,2,3,4} val = pickle.dumps(v) print(val) data = pickle.loads(val) print(data,type(data)) """ """ def f1(): print('f1') v1 = pickle.dumps(f1) print(v1) v2 = pickle.loads(v1) v2() """ # #################### dump/load ###################### # v = {1,2,3,4} # f = open('x.txt',mode='wb') # val = pickle.dump(v,f) # f.close() # f = open('x.txt',mode='rb') # data = pickle.load(f) # f.close() # print(data)
7-1-6. 6.1.6 time&datetime
UTC/GMT:世界时间
本地时间:本地时区的时间。
-
time模块
- time.time() ,时间戳:1970-1-1 00:00
- time.sleep(10),等待秒数。
- time.timezone
-
datetime模块
#!/usr/bin/env python # -*- coding:utf-8 -*- import time from datetime import datetime,timezone,timedelta # ######################## 获取datetime格式时间 ############################## """ v1 = datetime.now() # 当前本地时间 print(v1) tz = timezone(timedelta(hours=7)) # 当前东7区时间 v2 = datetime.now(tz) print(v2) v3 = datetime.utcnow() # 当前UTC时间 print(v3) """ # ######################## 把datetime格式转换成字符串 ############################## # v1 = datetime.now() # print(v1,type(v1)) # val = v1.strftime("%Y-%m-%d %H:%M:%S") # print(val) # ######################## 字符串转成datetime ############################## # v1 = datetime.strptime('2011-11-11','%Y-%m-%d') # print(v1,type(v1)) # ######################## datetime时间的加减 ############################## # v1 = datetime.strptime('2011-11-11','%Y-%m-%d') # v2 = v1 - timedelta(days=140) # date = v2.strftime('%Y-%m-%d') # print(date) # ######################## 时间戳和datetime关系 ############################## # ctime = time.time() # print(ctime) # v1 = datetime.fromtimestamp(ctime) # print(v1) # v1 = datetime.now() # val = v1.timestamp() # print(val)
7-1-7. 6.1.7 hashlib
- 将指定的 “字符串” 进行加密。
import hashlib
def get_md5(data):
obj = hashlib.md5()
obj.update(data.encode('utf-8'))
result = obj.hexdigest()
return result
val = get_md5('123')
print(val)
加严
import hashlib
def get_md5(data):
obj = hashlib.md5("sidrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
obj.update(data.encode('utf-8'))
result = obj.hexdigest()
return result
val = get_md5('123')
print(val)
应用:
import hashlib
USER_LIST = []
def get_md5(data):
obj = hashlib.md5("12:;idrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
obj.update(data.encode('utf-8'))
result = obj.hexdigest()
return result
def register():
print('**************用户注册**************')
while True:
user = input('请输入用户名:')
if user == 'N':
return
pwd = input('请输入密码:')
temp = {'username':user,'password':get_md5(pwd)}
USER_LIST.append(temp)
def login():
print('**************用户登陆**************')
user = input('请输入用户名:')
pwd = input('请输入密码:')
for item in USER_LIST:
if item['username'] == user and item['password'] == get_md5(pwd):
return True
register()
result = login()
if result:
print('登陆成功')
else:
print('登陆失败')
7-1-8. 6.1.8 getpass
import getpass
#密码不显示(只能在终端运行)
pwd = getpass.getpass('请输入密码:')
if pwd == '123':
print('输入正确')
7-1-9. 6.1.9 random
import random # 导入一个模块
v = random.randint(起始,终止) # 得到一个随机数
7-1-10. 6.1.10 functools
-functools.reduce(func,v1)
7-2. 6.2 自定义模块
定义模块时可以把一个py文件或一个文件夹(包)当作一个模块,以方便于以后其他py文件的调用。
对于包的定义:
- py2:文件见中必须有 _ _init _ _.py 。
- py3:不需要 _ init _.py .
推荐大家以后写代码时,都要加上此文件。
导入模块方法:
- import 模块 模块.函数()
- from 模块 import 函数 函数() 【as起别名 / *表示全部】
- from 模块 import 函数 as 别名 别名()
- 模块和要执行的py文件在同一目录 且 需要 模块中的很多功能时,推荐用: import 模块 模块.函数()
- 其他推荐:from 模块 import 模块 模块.函数()
- 其他推荐:from 模块.模块 import 函数 函数()


7-3. 6.3 第三方模块
- requests
- xlrd
7-4. 6.4 异常处理
try:
val = input('请输入数字:')
num = int(val)
except Exception as e:
print('操作异常')
# import requests
#
# try:
# ret = requests.get('http://www.google.com')
# print(ret.text)
# except Exception as e:
# print('请求异常')
def func(a):
try:
return a.strip()
except Exception as e:
pass
return False
v = func('alex')
if not v:
print('函数执行失败')
else:
print('结果是',v)
# 1. 写函数,函数接受一个列表,请将列表中的元素每个都 +100
def func(arg):
result = []
for item in arg:
if item.isdecimal():
result.append(int(item) + 100)
return result
# 2. 写函数去,接受一个列表。列表中都是url,请访问每个地址并获取结果。
import requests
def func(url_list):
result = []
try:
for url in url_list:
response = requests.get(url)
result.append(response.text)
except Exception as e:
pass
return result
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
func(['http://www.baidu.com','http://www.google.com','http://www.bing.com'])
7-5. 6.5 正则表达式
到底什么是正则表达式(regex)?
在编写处理字符串的程序或网页时,经常有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。
7-5-1. 6.5.1 常用元字符
\d 表示所有的数字
\w 字母/数字/下划线
\s 空白(空格/换行符/制表符)
\t 匹配制表符 Tab
\n 匹配换行符
. 表示除了换行符之外的任意内容
\D 表示所有的非数字
\W 表示除 数字字母下划线之外的所有字符
\S 表示非空白
[] 字符组 :只要在中括号内的所有字符都是符合规则的字符
[^xyz] 非字符组 :只要在中括号内的所有字符都是不符合规则的字符
^ 表示一个字符的开始
$ 表示一个字符的结束
| 表示或,注意,如果两个规则有重叠部分,总是长的在前面,短的在后面
() 表示分组,给一部分正则规定为一组,|这个符号的作用域就可以缩小了
[\d\D] [\W\w] [\S\s] 匹配所有一切字符
7-5-2. 6.5.2 常用限定符(量词)
代码/语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
> 匹配一个整数或者小数 \d+.\d+ | \d+ \d+.?\d* \d+(.\d+)? |
# 以a开头,由至少一个字母组成的字符串
# ^a[a-zA-Z]+
# ^a[a-zA-Z]*
# 以1开头,中间3-5个数字,如果中间位置超过5个数字,则整个字符串不匹配
# ^1\d{3,5}$
7-5-3. 6.5.3 贪婪匹配
默认采用回溯算法,贪婪匹配,总是会在符合量词条件的范围内尽量多匹配.
adljdkjsljdlj<.+> 会匹配到整个字符串,而不是
惰性匹配
总是匹配符合条件范围内尽量小的字符串
格式: 元字符 量词 ? x
表示按照元字符规则在量词范围内匹配,一旦遇到x就停止
# 身份证号
# 15位 全数字 首位不为0
# 18位 前17位全数字 首位不为0 最后一位可能是x和数字
# [1-9](\d{14}|\d{16}(\d|x))
# [1-9](\d{16}[\dx]|\d{14})
# [1-9]\d{14}(\d{2}[\dx])?
7-5-4. 6.5.4 表达式中转义符
正则表达式中的转义符在python的字符串中也刚好有转义的作用,但是正则表达式中的转义符和字符串中的转义符并没关系,且还容易有冲突,为了避免这种冲突,我们所有的正则都以在工具中的测试结果为结果,然后只需要在正则和待匹配的字符串外面都加r即可.
- \d \s \w \t \n→python字符串中
- 匹配
()[]{}\d
等,需要加\转义
7-5-5. 6.5.5 ret正则模块
-
ret.findall('正则表达式',字符串)
匹配字符串中所有符合规则的项,并返回一个列表,如果未匹配到返回空列表 -
ret.search('正则表达式',字符串)
匹配字符串中满足条件的第一项,返回一个对象,用group方法取值;如果不能匹配上返回None,group方法会报错.
if ret:
print(ret.group()) # 如果是对象,那么这个对象内部实现了group,所以可以取值
# 如果是None,那么这个对象不可能实现了group方法,所以报错
-
ret.match('正则表达式',字符串)
会从头匹配字符串中取出从第一个字符开始是否符合规则,如果符合,就返回对象,用group取值,如果不符合,就返回None
match = search + ^正则
-
re.finditer('正则表达式',字符串)
返回一个迭代器,迭代出来的每一项都是一个对象,然后group取值
在查询的结果超过1个的情况下,能够有效的节省内存,降低空间复杂度,从而也降低了时间复杂度
-
re.compile('正则表达式')
正则表达式编译成python语言,供多次使用
ret = re.compile('\d3') r1=ret.search("djasjd5a646")
-
re.split()
re.split('\d\d','alex83wusir74taibai') #不保存被分割的内容 [,1]第几个分割 re.split('\d(\d)','alex83wusir74taibai') # 默认自动保留分组中的内容
-
re.sub('正则表达式',替换内容,字符串,[序号])
返回字符串 -
re.subn('正则表达式',替换内容,字符串,[序号])
返回元组(替换后字符串,替换个数)
7-5-6. 6.5.6 分组
-
分组命名
(?P<组名>正则) -
引用分组
(?P=组命) -
findall和分组
- 优先显示分组中的内容,其他内容内容返回空字符串
""
- (?:)取消这个分组的优先⭐ ,量词为了约定多个字符加括号,会产生此情况.
import re ret = re.findall('\d+(\.\d+)?','21.234+2') print(ret) #运行结果:['.234', '']
import re ret = re.findall('\d+(?:\.\d+)?','21.234+2') print(ret) #运行结果:['21.234', '2']
- 优先显示分组中的内容,其他内容内容返回空字符串
小技巧:有的时候我们想匹配的内容包含在不相匹配的内容当中,这个时候只需要把不想匹配的先匹配出来,再通过手段去掉.
import re
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret)
ret.remove('')
print(ret)
#运行结果:
#['1', '2', '60', '', '5', '4', '3']
#['1', '2', '60', '5', '4', '3']
- split和分组
会保留分组中本来应该被切割掉的内容 - search和分组
通过索引取 obj.group(1)
通过组名取 obj.group('组名')
# 1.找出<h1>123fh</h1><h2>hado</h2>中所有标签内的字符串 爬虫
import re
ret = re.findall('<.*?>(.*?)<.*?>','<h1>123fh</h1><h2>hado</h2>')
print(ret)
# 2.找出四则运算表达式中的第一个乘除法
# \d*\d|\d/\d
# \d+(\.\d+)?[*/]\d(\.\d+)?
# \d+(\.\d+)?[*/]-?\d(\.\d+)?
import re
ret = re.search('\d+(\.\d+)?[*/]-?\d(\.\d+)?', '2-3*-5/6')
print(ret.group())
# 3.检测用户输入的内容是否是一个合法的身份证号 网页的合法输入(手机号码 qq号码 银行卡号 邮箱地址)
# '^[1-9]\d{14}(\d{2}[\dx])?$'
import re
inp = input('>>>').strip()
re.match('[1-9]\d{14}(\d{2}[\dx])?$', inp) # 首选
re.search('^[1-9]\d{14}(\d{2}[\dx])?$', inp)
re.findall('^[1-9]\d{14}(\d{2}[\dx])?$', inp)
ret=re.findall(pattern,info,re.S) #允许.匹配下一行
8. 第七章 面向对象
8-1. 7.1 面向对象基本格式
# ###### 定义类 ######
class 类名:
def 方法名(self,name):
print(name)
return 123
# ###### 调用类中的方法 ######
# 1.创建该类的对象
obj = 类名()
# 2.通过对象调用方法
result = obj.方法名('alex')
print(result)
# 如果在python2中这样定义,则称其为:经典类
class Foo:
pass
# 如果在python2中这样定义,则称其为:新式类
class Foo(object):
pass
# 在python3中这俩的写法是一样,因为所有的类默认都会继承object类,全部都是新式类。
class Base(object):
pass
class Bar(Base):
pass
8-2. 7.2 面向对象的特性
封装,继承,多态.
8-2-1. 7.2.1封装
- 表现一:函数封装到类
class File:
def read(self):
pass
def write(self):
pass
- 表现二:数据封装到对象 *
class Person:
def __init__(sef,name,age):
self.name = name
self.age = age
p = Person('alex',19)
对象的作用:存储一些值,方便以后调用.
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__方法。
p1 = Person('李兆琪',19,'男')
p1.show()
p2 = Person('利奇航',19,'男')
p2.show()
如果写代码时,函数比较多比较乱。
- 可以将函数归类并放到同一个类中。
- 函数如果有一个反复使用的公共值,则可以放到对象中。
class Person:
def __init__(self,user,pwd,email):
self.username = user
self.password = pwd
self.email = email
def info(self):
return "我的名字:%s,密码:%s,邮箱%s" %(self.username,self.password,self.email,)
USER_LIST = []#对象(用户/密码/邮箱),对象(用户/密码/邮箱),对象(用户/密码/邮箱)
while True:
user = input('请输入用户名:')
pwd = input('请输入密码:')
email = input('请输入邮箱:')
p = Person(user,pwd,email)
USER_LIST.append(p)
for item in USER_LIST:
msg = item.info()
print(msg)
8-2-2. 7.2.2 继承
# 父类(基类)
class Base:
def f1(self):
pass
# 子类(派生类)
class Foo(Base):
def f2(self):
pass
# 创建了一个字类的对象
obj = Foo()
# 执行对象.方法时,优先在自己的类中找,如果没有就是父类中找。
obj.f2()
obj.f1()
# 创建了一个父类的对象
obj = Base()
obj.f1()
什么时候才能用到继承?多个类中如果有公共的方法,可以放到基类中避免重复编写。
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()
#foo.f2
#base.f1 注意self是谁
注意事项:
- self 到底是谁?
- self 是哪个类创建的,就从此类开始找,自己没有就找父类。
8-2-3. 7.2.3 多态-鸭子模型
# Python
def func(arg):
v = arg[-1] # arg.append(9)
print(v)
# java
def func(str arg):
v = arg[-1]
print(v)
什么是鸭子模型?
对于一个函数而言,Python对于参数的类型不会限制,那么传入参数时就可以是各种类型,在函数中如果有例如:arg.send方法,那么就是对于传入类型的一个限制(类型必须有send方法)。
这就是鸭子模型,类似于上述的函数我们认为只要能呱呱叫的就是鸭子(只有有send方法,就是我们要想的类型)
8-3. 7.3 成员
- 类
- 类变量
- 方法
- 绑定方法
- 类方法
- 静态方法
- 属性
- 实例(对象)
- 实例变量
8-3-1. 7.3.1 实例变量
实例自己封装的变量
class Foo:
def __init__(self,name):
self.name=name
def info(self):
pass
obj1 = Foo("alex")
obj2 = Foo('eric')
8-3-2. 7.3.2 类变量
-
定义:写在类的下一级和方法同一级。
-
访问:
类.类变量名称 (推荐) 对象.类变量名称
-
面试题
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)
总结:找变量优先找自己,自己没有找 类 或 基类;修改或赋值只能在自己的内部设置。
8-3-3. 7.3.3 绑定方法/普通方法
- 定义:至少有一个self参数
- 执行:先创建对象,由对象.方法()。
class Foo:
def func(self,a,b):
print(a,b)
obj = Foo()
obj.func(1,2)
# ###########################
class Foo:
def __init__(self):
self.name = 123
def func(self, a, b):
print(self.name, a, b)
obj = Foo()
obj.func(1, 2)
8-3-4. 7.3.4 静态方法
- 定义:
- @staticmethod装饰器
- 参数无限制
- 执行:
- 类.静态方法名 ()
- 对象.静态方法() (不推荐)
class Foo:
def __init__(self):
self.name = 123
def func(self, a, b):
print(self.name, a, b)
@staticmethod
def f1():
print(123)
obj = Foo()
obj.func(1, 2)
Foo.f1()
obj.f1() # 不推荐
8-3-5. 7.3.5 类方法
- 定义:
- @classmethod装饰器
- 至少有cls参数,当前类。
- 执行:
- 类.类方法()
- 对象.类方法() (不推荐)
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)
# 问题: @classmethod和@staticmethod的区别?
"""
一个是类方法一个静态方法。
定义:
类方法:用@classmethod做装饰器且至少有一个cls参数。
静态方法:用staticmethod做装饰器且参数无限制。
调用:
类.方法直接调用。
对象.方法也可以调用。
"""
8-3-6. 7.3.6 属性
- 定义:
- @property装饰器
- 只有一个self参数
- 执行:
- 对象.方法 不用加括号。
class Foo:
@property
def func(self):
print(123)
return 666
obj = Foo()
result = obj.func
print(result)
# 属性的应用
class Page:
def __init__(self, total_count, current_page, per_page_count=10):
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 * self.per_page_count
USER_LIST = []
for i in range(321):
USER_LIST.append('alex-%s' % (i,))
# 请实现分页展示:
current_page = int(input('请输入要查看的页码:'))
p = Page(321, current_page)
data_list = USER_LIST[p.start_index:p.end_index]
for item in data_list:
print(item)
8-4. 7.4 成员修饰符
- 公有,所有地方都能访问到。
- 私有,只有自己可以访问到。
class Foo:
def __init__(self, name):
self.__name = name
def func(self):
print(self.__name)
obj = Foo('alex')
# print(obj.__name)
obj.func()
class Foo:
__x = 1
@staticmethod
def func():
print(Foo.__x)
# print(Foo.__x)
Foo.func()
class Foo:
def __fun(self):
print('msg')
def show(self):
self.__fun()
obj = Foo()
# obj.__fun()
obj.show()
# 强制访问私有成员
class Foo:
def __init__(self,name):
self.__x = name
obj = Foo('alex')
print(obj._Foo__x) # 强制访问私有实例变量
8-5. 7.4 嵌套
嵌套表现形式:
- 函数: 参数可以是任意类型
- 字典: 对象和类都可以做字典的key和value
- 继承的查找关系
class StarkConfig(object):
pass
class AdminSite(object):
def __init__(self):
self.data_list = []
def register(self,arg):
self.data_list.append(arg)
site = AdminSite()
obj = StarkConfig()
site.register(obj) #将对象嵌入另一类的对象的列表中
class StarkConfig(object):
def __init__(self,name,age):
self.name = name
self.age = age
class AdminSite(object):
def __init__(self):
self.data_list = []
self.sk = None
def set_sk(self,arg):
self.sk = arg
site = AdminSite() # data_list = [] sk = StarkConfig
site.set_sk(StarkConfig)
site.sk('alex',19) #StarkConfig('alex',19)
8-6. 7.5 特殊成员
8-6-1. 7.5.1 __init__
class Foo:
""" 类是干啥的。。。。 """
def __init__(self,a1):
""" 初始化方法 :param a1: """
self.a1 = a1
obj = Foo('alex')
8-6-2. 7.5.2__new__
class Foo(object):
def __init__(self):
""" 用于给对象中赋值,初始化方法 """
self.x = 123
def __new__(cls, *args, **kwargs):
""" 用于创建空对象,构造方法 :param args: :param kwargs: :return: """
return object.__new__(cls)
obj = Foo()
8-6-3. 7.5.3 __call__
class Foo(object):
def __call__(self, *args, **kwargs):
print('执行call方法')
# obj = Foo()
# obj()
Foo()()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from wsgiref.simple_server import make_server
def func(environ,start_response):
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
return ['你好'.encode("utf-8") ]
class Foo(object):
def __call__(self, environ,start_response):
start_response("200 OK", [('Content-Type', 'text/html; charset=utf-8')])
return ['你<h1 style="color:red;">不好</h1>'.encode("utf-8")]
# 作用:写一个网站,用户只要来方法,就自动找到第三个参数并执行。
server = make_server('127.0.0.1', 8000, Foo())
server.serve_forever()
8-6-4. 7.5.4 __getitem__
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__ 方法
8-6-5. 7.4.5 __str__
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__ 方法
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)
8-6-6. 7.4.6__dict__
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)
8-6-7. 7.4.7 上下文管理
class Foo(object):
def __enter__(self):
self.x = open('a.txt',mode='a',encoding='utf-8')
return self.x
def __exit__(self, exc_type, exc_val, exc_tb):
self.x.close()
with Foo() as ff:
ff.write('alex')
ff.write('alex')
ff.write('alex')
ff.write('alex')
# class Context:
# def __enter__(self):
# print('进入')
# return self
#
# def __exit__(self, exc_type, exc_val, exc_tb):
# print('推出')
#
# def do_something(self):
# print('内部执行')
#
# with Context() as ctx:
# print('内部执行')
# ctx.do_something()
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()
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)
8-6-8. 7.4.8 对象相加
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)
8-7. 7.5 内置函数(补充)
8-7-1. 7.5.1 type,查看类型
class Foo:
pass
obj = Foo()
if type(obj) == Foo:
print('obj是Foo类的对象')
8-7-2. 7.5.2 issubclass
class Base:
pass
class Base1(Base):
pass
class Foo(Base1):
pass
class Bar:
pass
print(issubclass(Bar,Base))
print(issubclass(Foo,Base))
8-7-3. 7.5.3 isinstance
class Base(object):
pass
class Foo(Base):
pass
obj = Foo()
print(isinstance(obj,Foo)) # 判断obj是否是Foo类或其基类的实例(对象)
print(isinstance(obj,Base)) # 判断obj是否是Foo类或其基类的实例(对象)
8-8. 7.6 super
class Base(object):
def func(self):
print('base.func')
return 123
class Foo(Base):
def func(self):
v1 = super().func()
print('foo.func',v1)
obj = Foo()
obj.func()
# super().func() 去父类中找func方法并执行
class Bar(object):
def func(self):
print('bar.func')
return 123
class Base(Bar):
pass
class Foo(Base):
def func(self):
v1 = super().func()
print('foo.func',v1)
obj = Foo()
obj.func()
# super().func() 根据类的继承关系,按照顺序挨个找func方法并执行(找到第一个就不在找了)
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方法并执行(找到第一个就不在找了)
8-9. 7.7 异常处理
8-9-1. 7.7.1 基本格式
try:
pass
except Exception as e:
pass
try:
v = []
v[11111] # IndexError
except ValueError as e:
pass
except IndexError as e:
pass
except Exception as e:
print(e) # e是Exception类的对象,中有一个错误信息。
try:
int('asdf')
except Exception as e:
print(e) # e是Exception类的对象,中有一个错误信息。
finally:
print('最后无论对错都会执行')
# #################### 特殊情况 #########################
def func():
try:
# v = 1
# return 123
int('asdf')
except Exception as e:
print(e) # e是Exception类的对象,中有一个错误信息。
return 123
finally:
print('最后')
func()
8-9-2. 7.7.2 主动触发异常
try:
int('123')
raise Exception('阿萨大大是阿斯蒂') # 代码中主动抛出异常
except Exception as e:
print(e)
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
8-9-3. 7.7.3 自定义异常
class MyException(Exception):
pass
try:
raise MyException('asdf')
except MyException as e:
print(e)
class MyException(Exception):
def __init__(self,message):
super().__init__()
self.message = message
try:
raise MyException('asdf')
except MyException as e:
print(e.message)
8-10. 7.8 可迭代对象
表象:可以被for循环对象就可以称为是可迭代对象:字符串,列表,字典...
- 如何让一个对象变成可迭代对象?
在类中实现
__iter__
方法且返回一个迭代器(生成器)
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()
记住:只要能被for循环就是去看他内部的iter方法。
8-11. 7.9 约束
# 约束字类中必须写send方法,如果不写,则调用时候就报抛出 NotImplementedError
class Interface(object):
def send(self):
raise NotImplementedError()
class Message(Interface):
def send(self):
print('发送短信')
class Email(Interface):
def send(self):
print('发送邮件')
8-12. 7.10反射
根据字符串的形式去某个对象中 操作 他的成员。
-
getattr(对象,"字符串") 根据字符串的形式去某个对象中 获取 对象的成员.
class Foo(object): def __init__(self,name): self.name = name obj = Foo('alex') # 获取变量 v1 = getattr(obj,'name') # 获取方法 method_name = getattr(obj,'login') method_name()
-
hasattr(对象,'字符串') 根据字符串的形式去某个对象中判断是否有该成员。
#!/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(对象,'变量','值') 根据字符串的形式去某个对象中设置成员。
class Foo: pass obj = Foo() obj.k1 = 999 setattr(obj,'k1',123) # obj.k1 = 123 print(obj.k1)
-
delattr(对象,'变量') 根据字符串的形式去某个对象中删除成员。
class Foo: pass obj = Foo() obj.k1 = 999 delattr(obj,'k1') print(obj.k1)
python一切皆对象
- py文件
- 包
- 类
- 对象
python一切皆对象,所以以后想要通过字符串的形式操作其内部成员都可以通过反射的机制实现。
8-13. 7.11.单例模式
无论实例化多少次,永远用的都是第一次实例化出的对象。
class Foo:
pass
# 多例,每实例化一次就创建一个新的对象。
obj1 = Foo() # 实例,对象
obj2 = Foo() # 实例,对象
# 单例,无论实例化多少次,都用第一次创建的那个对象。
obj1 = Foo()
obj2 = Foo()
单例模式标准
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()
# 不是最终,加锁。
文件的连接池
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__(cls)
return cls.instance
obj1 = FileHelper('x')
obj2 = FileHelper('x')
- 模块多次导入重新加载
import jd # 第一次加载:会加载一遍jd中所有的内容。
import jd # 由已经加载过,就不在加载。
print(456)
import importlib
import jd
importlib.reload(jd)
print(456)
通过模块导入的特性也可以实现单例模式:
# jd.py
class Foo(object):
pass
obj = Foo()
# app.py
import jd # 加载jd.py,加载最后会实例化一个Foo对象并赋值给obj
print(jd.obj)
8-14. 7.12日志
-
logging基本应用
-
日志处理本质:Logger/FileHandler/Formatter
-
推荐处理日志方式
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('你好')
-
推荐处理日志方式 + 日志分割
import time import logging from logging import handlers # file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',) file_handler = handlers.TimedRotatingFileHandler(filename='x3.log', when='s', interval=5, 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 ) for i in range(1,100000): time.sleep(1) logging.error(str(i))
注意事项:
# 在应用日志时,如果想要保留异常的堆栈信息。 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: requests.get('http://www.xxx.com') except Exception as e: msg = str(e) # 调用e.__str__方法 logging.error(msg,exc_info=True)
8-15. 7.13项目结构目录



9. 第八章 网络编程
10. 第九章 并发编程
11. 第十章 数据库
12. 第十一章 前端开发
13. 第十二章 Django框架
14. 附录 常见错误和单词
14-1. py2&py3区别
- py2:
xrange,不会在内存中立即创建,而是在循环时。边循环边创建。
range ,在内存立即把所有的值都创建。
py3:
range ,不会在内存中立即创建,而是在循环时。边循环边创建。
list(range(10))
14-2. 单词
upper | 大写 | ... |
---|---|---|
14-3. 错误记录
14-3-1.
14-4. 面试题
-
线上操作系统:centos
-
py2和py3的区别?
-
每种数据类型,列举你了解的方法。
-
3 or 9 and 8
-
字符串的反转
-
is 和 == 的区别?
-
v1 = (1) / v2 = 1
-
深浅拷贝
-
文件操作,大文件如何读取内容 [ 50G的日志文件 ]
v = open(....) for line in v: print(line) v.close()
-
一行写出:9*9乘法表【不会】
-
git流程【不会】
-
global和nonlocal区别
-
需求分析
-
诚实
-
知识边界分析,对比
