参考资料备用:
python ABC
3.8.2Documentation
python cookbook 3rd
pip安装超时解决办法
vscode小技巧
- 打开命令窗口:Ctrl+`
- 注释:单行 – Ctrl+/,多行 – Shift+Alt+A
- cmd:
cls
清屏 - Ctrl + Shift + O:快速定位函数
目录速查
Python入门导学
Python基本类型:数字,字符串
组:列表,元组,集合,字典
变量与运算符
分支、循环、条件和枚举
包、模块、类
函数
面向对象:类,实例,方法,继承
正则表达式和JSON
枚举类型,闭包
匿名函数、高阶函数、装饰器
爬虫实战
Python杂记
Python入门导学
特点
- 简洁;丰富的标准库和第三方库(电子邮件、GUI);面向对象+函数式编程;易于上手,难于精通;既有动态脚本的特性,又有面向对象的特性。
- 豆瓣、知乎
- Simple is better than complex.
Now is better than never. Although never is often better than an right now. - 缺点:慢
编译型语言(C、C++)–运行效率
解释型语言(Javascript,Python)–开发效率
一个经典误区:编程 = web编程?
- 世界上不是只有网站,还有很多问题需要编程来解决。
- web是基础–爬虫、数据服务提供、数据分析。
- 互联网时代,有网络的地方就需要web。
- web编程确实是最好的语言实践–业务逻辑思考能力、宽广的知识面。
Python能做什么
- 爬虫
- 大数据与数据分析(Spark)
- 自动化运维与自动化测试
- web开发:Flask,Django
- 机器学习:Tensor Flow(谷歌)
- 胶水语言:能够把其他语言制作的各种模块(尤其是C/C++)轻松地联结在一起
正确打开方式:遇到问题时,随手拿起Python写个工具
什么是写代码&Python的基本类型
什么是代码,什么是写代码
- 代码: 现实世界事物在计算机世界中的映射
- 写代码: 将现实世界中的事物用计算机语言来描述
数字
整型与浮点型
- 整数:
int
其他语言有short
,int
,long
- 浮点数:
float
其他语言有单双精度之分,Python没有
type(2/2)
是float
(1.0),type(2//2)
是int
(1)
*双斜杠是“整除”
10、2、8、16进制&表示&转换
- 其他进制:60s = 1min
- 2进制:0b10,直接在IDLE回车就会返回2
8进制:0o10 = 8
16进制:0x10 = 16 bin()
:将其他进制转换成2进制
oct()
:将其他进制转换成8进制
hex()
:将其他进制转换成16进制
int()
:将其他进制转换成10进制
布尔类型和复数(属于数字分类)
bool
:表示真、假
True/False
,要大写
只要非 0/空串/空列表/None
,就都是True
complex
:复数(36j
)
抓大放小,抓住重点深入
字符串str
单双引号
- 单引号和双引号–成对出现
"let's go"
,'let\'s go'
多行字符串
- 一行79,回车字符\n会读进字符串中
'''
hello world
hello world
'''
"""
hello world
hello world
"""
- IDLE写
'\n'
输出还是'\n'
,不换行
print("""hello world\nhello world\n""")
会输出换行 - 单引号换行:
'hello\
world'
输出'helloworld'
转义字符–特殊的字符
- 表示无法“看见”的字符
- 与本身语法有冲突的字符
\n
换行
\r
回车:光标回到本行首位置,不会换行
\t
横向制表符:TAB
\'
单引号
原始字符串
- 字符串前加
r
/R
,原始字符串–所看即所得。 'let's go'
无法通过加r解决–引号要成对出现
字符串运算
- +:拼接
*数字:重复数字倍 - 获取单个字符:“字符串”[i],负数从后往前数
获取一段字符:步长
'hello world'[0:4]
输出'hell'
,要读到字符下一位
'hello world'[0:-1]
输出'hello worl'
- 怎么输出world?
"hello world"[6:]
,默认取字符串最后一位
"hello world"[-5:]
,后往前数第5位,到末尾
“组”的概念与定义
列表list
定义
列表内部可以存放不同类型元素
列表内部可以嵌套列表
基本操作
- 取元素
["新月打击","苍白之瀑","月之降临","月神冲刺"][0]
'新月打击' #返回的是元素
["新月打击","苍白之瀑","月之降临","月神冲刺"][-1:]
['月神冲刺'] #返回的是列表
- 合并列表:
+
*3
:把列表内元素重复三次
元组tuple
- 同列表
type(('hello'))
返回值str
:为什么只有一个元素的元组是元素的类型?
答:()内只有一个元素,python优先认为()是数学运算符,返回数学运(比如(1))。
表示只有一个元素的元组:(1,)
表示一个元素都没有的空元组:()
type([1])
返回值是list
序列总结
- 序号
- 切片
"hello world"[0:8:2]
返回'hlow
–在0-7的切片内隔1取元素? +
,*
- 元素是否在序列中:
in
,not in
,返回bool值
3 in [1,2,3,4,5]
返回True
len()
,max()
,min()
:返回序列长度、最大值、最小值
max、min不支持不同类型元素比较ord()
返回单个字符的ASC码(字符串不行)
集合set
- 最大的特点——无序
{1,2,3,4,5}
不支持序号、切片 - 不重复
{1,1,1,2,2,3,4,5}
返回{1,2,3,4,5}
len()
in
、not in
{1,2,3,4,5,6} - {3,4}
:两个集合取差集
{1,2,3,4,5,6} & {3,4}
:两个集合取交集
{1,2,3,4,5,6} | {3,4,7}
:两个集合取并集- 怎么定义空的集合?
type({})
返回dict
类型 – 不可用
type(set())
返回set
类型 – 正确操作
字典dict
- 很多的
key
和value
,set
的延生而不是序列的
{key1:value, key2:value, ……}
- 最常用操作:通过key得到/访问value
- key值不可重复
{
'Q':"新月打击",'W':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}['Q']
'新月打击'
{
'Q':"新月打击",'Q':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}['Q']
'苍白之瀑'
{
'Q':"新月打击",'Q':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}
{
'Q':"苍白之瀑",'E':"月之降临",'R':"月神冲刺"}
value
类型无限制,可以也是一个字典
key
必须是不可变的类型 – 字符串和元组不可变,列表可变
变量与运算符
变量
什么是变量
- 名字:起名字要有意义 – 命名可读性要强,多查单词
=
:赋值符号
命名规则
- 字母、数字、下划线
- 首位不能是数字
- 系统关键字(保留关键字)不能用在变量名中
非保留的也尽量不要用,血和泪的教训。
type = 1
type(1) #报错,此时等价于1(1)
值类型与引用类型
a = 1
b = a
a = 3 #a指向了新的int(3)
print(b) #1
a = [1,2,3,4,5]
b = a
a[0] = '1' #a没有指向新的list,而是改变原来的list
print(b) #['1',2,3,4,5]
- 值类型:不可改变
int
、str
、tuple
引用类型:可改变
list
、set
、dict
#str不可变,id()得到地址,发现前后地址变了,说明不是在原地址上修改
b = 'hello'
b = b + 'python' #生成新的字符串,再赋值给b
print(b) #hellopython
list
和tuple
:
元组不可修改,能用元组就用元组 – 代码稳定性考虑
a = (1,2,3,[1,2,['a','b','c']])
a[2] = '3' #不可改变,报错
a[3][2][1] = '4' #可以改变,变为(1,2,3,[1,2,['a','4','c']])
运算符
算术运算符
+
,-
,*
,/
,//
整除,%
,**
指数(2**5 = 32
)
赋值运算符
- 先做运算再赋值
- python中没有自增自减运算
比较运算符
- 返回一个
bool
值
逻辑运算符
- 与、或、非
int
,float
中0
被认为是False
字符串中空字符串""
是False
列表中空的列表[]
被认为是Falseand
和or
的返回值 – 最后一个读到的内容
1 and 2
返回2,2 and 1
返回1 – 读到第二个数字才能判断
1 or 2
返回1 – 读到第一个1的时候就能判断了
成员运算符
in
,not in
- 字典类型判断的是
key
身份运算符
is
,is not
– 两个变量的身份是否相等
a = 1
b = 1.0
a == b #True
a is b #False
id()
查看他们的地址,地址相同身份相同 –is
比较的是地址
a = {
1,2,3}
b = {
2,1,3}
a == b #True, set无序
a is b #False, 地址不同
判断变量的值、身份、类型 – 对象3特征
==
值
is
身份
isinstance(a, int)
类型isinstance(a, (int, str, float))
a是否是元组里三个类型中的一个,是返回True,否返回False
位运算符
b = 3
bin(b) #'0b11',3
bin(~b) #'-0b100',前面取负末位+1,-4
a = 2
bin(a) #'0b10'
bin(a<<1) #'0b100'
bin(a>>3) #'0b0'
分支、循环、条件和枚举
表达式
什么是表达式
表达式是运算符和操作数组成的序列
表达式优先级
- 一般右结合,出现
=
左结合,与运算符优先级无关 - 运算符优先级最高,然后是比较,逻辑运算符最低:
not > and > or
- 加辅助括号可以改变运算顺序
流程控制语句
条件控制
if d:
a = input() #读入的是字符串
pass #空语句,占位语句
elif:
pass
else:
pass
pylint规范
- python中实际没有常量,用大写
- 每个模块开头一段注释,说明
- tab 四个空格、切换到下一个代码编辑区域
- python没有
switch
elif
代替,或者字典处理 - a,b不同时为False:
a or b
循环
while的循环场景
- 递归
counter = 1
while counter <= 10:
counter += 1
print(counter)
else:
print('EOF') #循环结束的时候执行else
for
for target_list in expression_list:
pass
else:
pass #列表全部打完以后执行else,强制break结束时不会执行else
range
for x in range(0, 10, 2): #范围,步长
pass
for x in range(10, 0, -2):
printf(x, end=' | ')
一定要用for吗?
a = [1,2,3,4,5,6,7,8]
for i in range(0, len(a), 2):
print(a[i], end=' | ')
b = a[0:len(a):2]
print(b)
python的组织结构-包、模块、类
- 包(文件夹,包含
__init__.py
),模块,类(用类把函数、变量组织起来)
包.模块seven.c4
,子包 __init__.py
的模块名就是包的名字
导入
import c7 #同级,导入模块
print(c7.a)
import t.c7 #子包中
print(t.c7.a)
from t.c7 import a, def #导入变量、函数
print(a)
from t import c7 #导入模块
print(c7.a)
from t.c7 import * #导入所有变量和函数,能不用就不用
__all__ = ['a', 'c']
#在模块开头,改变*关于全部的定义
#模块的内置属性
#末尾加反斜杠可以换行, ()也可以换行
from c7 import a, b\
c
from c7 import (a, b
c)
init.py
- 导入包时自动运行:
无论是导入包还是导入包下面的模块,都会自动运行__init__.py
- 在
__init__.py
内设置__all__
可以控制*
时导入的包内模块 - 批量导入包
- 注意点:
① 包和模块不会被重复导入
② 避免循环导入
③ python导入模块时会执行所导入模块的代码
模块内置变量
dir()
返回当前模块的变量列表
dir(sys)
返回指定模块sys
的变量列表- 错误信息:堆栈信息(路径)+详细信息(原因)
__doc__
存放模块注释信息
__file__
存放文件路径
入口文件和普通模块内置变量的区别
print('package: ' + (__package__ or 当前模块不属于任何包)) #当前模块不属于任何包
print('name: ' + __name__) #__main__
print('doc: ' + (__package__ or 当前模块没有文档注释))
print('file: ' + __file__) #文件名c9.py
__name__的经典应用
if __name == '__main__':
pass #作为可执行文件时才会执行
#Make a script both importable and executabl
python -m seven.c15
把c15按模块执行,命名空间(?)
python seven\c15.py
路径方式
相对导入和绝对导入
- 决定顶级包的是可执行文件
package2.package4
,demo不是顶级包 - 绝对导入必须从顶级包开始
- 相对路径:
.表示当前目录
…表示上层目录
…表示上上层目录 - 入口文件不能使用相对路径
因为入口文件的__name__
被设置成__main__
无法作为路径使用
一定要在路口文件使用相对路径:
回到demo的上一级,python -m demo.main
,此时相对导入可用,输出demo.package2.package4
- 相对导入
from .m3 import m
from ...m5 import m
# attempted relative import beyond top-level package
Python 函数
函数
round(a, 2)
保留小数点后两位,同时四舍五入help(round)
查看内置函数import this
打印python之禅- 特点:功能性、隐藏细节、避免编写重复的代码
函数的定义和运行特点
def funcname(parameter_list):
pass
#1. 参数列表可以没有
#2. return value None
[Previous line repeated 995 more times]
递归超过995次
import sys
sys.setrecursionlimit(100)
#设置最大递归层数
#[Previous line repeated 95 more times]
返回多个结果
def damage(skill1, skill2):
damage1 = skill1 * 3
damage2 = skill2 * 2
return damage1, damage2
skill1_damage, skill2_damage = damage(3, 4)
#用两个变量(有意义的变量名)存放两个返回值
#序列解包
序列解包
d = 1, 2, 3
print(type(d)) #tuple
a, b, c = d #序列解包
a, b = [1, 2, 3] #报错,用两个变量接收三个值
a=b=c=1 #连续赋值√
参数
必须参数与关键字参数
- 必须参数:
c = add(3, 2)
- 关键字参数:
c = add(y=3, x=2)
,不用固定实参的输入顺序 - 备注:
① 二者的差别在函数的调用上,不在定义上
② 定义了多少形参就要传入多少实参
默认参数
- 定义的时候给形参默认值
- 调用时正常传递实参即可按顺序覆盖,没有默认值的形参必须传入实参
- 必须传入的参数必须放在默认参数前面
print_student('lxxx', age=17)
可以不按参数列表顺序传入改变默认值- 默认值参数和必须参数不能混着调用
print_student('lxxx', gender='nv', 17, college='xx')
可变参数/形参列表可变
def demo(*param):
print(param)
print(type(param)) #tuple
demo(1,2,3,4,5,6)
a = (1,2,3,4,5)
demo(a) #报错,传递进入的是一个元组
demo(*a) #√ 类似解包,传入的是可变参数
def demo(param1, param2=2, *param):
print(param1)
print(param2)
print(param)
demo('a', 1,2,3)
#a
#1 默认值参数在前,读完才读可变参数
#(2,3)
def demo(param1, *param, param2=2):
print(param1)
print(param2)
print(param)
demo('a', 1,2,3, 'param')
#a
#(1,2,3,'param') 可变参数会把剩余全部传入可变
#2
demo('a', 1,