python表示两个概念=语法+运行时
语法:程序表达形式的规范,不遵守语法的结果就是运行时看不懂,解读不出来程序员表达的意思,会报错
运行时:解读”代码“的另一个程序(Cpython是python的一种实现方式,它使用c语言程序来解读python语法)
一、python介绍
1、为啥学python
- 运维、测试可以实现自动化
- 爬虫
- 实现可视化以及便捷高效的数据分析
- 机器学习相关研究
2、python有啥特点
它是一条90后的大蟒蛇,哈哈哈哈,你悄悄知道就行
- 解释型语言,无编译——python语言是解释执行的
- 交互式语言——>>>提示符之后,直接输入python语句&回车,就有相应的操作。(解释型的特点让它可以一令一动)
- 一切皆对象——在java中哪些基本类型数据,也是以对象形式存储
- 强大的基础库
二、输出与输入
任何语言学习,最最基础的两个api,先知为妙
1、输出函数print()
1)输出位置
-
可以输出在控制台
-
可以输出到文件
- print()中第二个参数必须是
file=表示文件的变量名
,否则无法将内容写如到文件中 - open()函数介绍
- 参数=文件绝对路径+文件操作权限/模式
- 文件操作权限具体列表
- 参数=文件绝对路径+文件操作权限/模式
- print()中第二个参数必须是
2)是否换行
- 正常情况下,print是表示换行输出
- 如果进行不换行输出,只需要将输出项在print函数中以逗号隔开罗列
3)是否让转义字符生效
- 如果想让字符串中的转义字符不生效,可以在字符串前加
r/R
2、输入函数input()
三、注释
1、单行注释
# 注释内容
2、多行注释
“”“ 注释内容 ”“”
四、数据类型
1、分类
1)”基本类型“——4个
-
整型 int
- 十进制:15
- 二进制:
0b
101 - 八进制:
0o
567 - 十六进制:
0x
1A9
-
浮点型 float
- 浮点数的计算无法精确表示,这是因为计算机底层都是用二进制数表示的,如果想要精确表示可以借助Decimal
Decimal不是精确计算吗,第二个例子为什么不精确?
浮点数在传入进去的时候就不是精确的1.1和2.2,所以其计算结果是以实际传入的数值来进行计算的,因而导致结果不是3.3。Decimal传入为整数或字符串就可以实现精确计算 - 浮点数的计算无法精确表示,这是因为计算机底层都是用二进制数表示的,如果想要精确表示可以借助Decimal
-
布尔 bool
- True=1
- False=0
-
字符串 str
- 1)有四种表示形式
- 单引号
'apple'
:字符串只能写在一行 - 双引号
"apple"
:字符串只能写在一行 - 三引号:字符串可以写在多行
- 三个单引号
'''apple'''
- 三个双引号
"""apple"""
- 三个单引号
- 单引号
- 1)有四种表示形式
-
2)字符串have to know
- 2.1)驻留池:java中的常量池类似(相同的内容只存一份)
- 为啥要有?
- 避免频繁的对象创建和销毁——提升处理性能
- 节约内存——高效利用内存
- 哪些会存在驻留池中?(python并不是所有不可变序列都会存储在驻留池中)
- 长度为0或1的字符串
- 符合标识符命名规则的字符串(仅由数字+字母+下划线组成)
- [-5,256]的整数
- 当使用乘法拼接字符串的时候,会驻留,与字符串长度无关(在cmd下输入python可跳转到python交互式窗口模式 ),+和join拼接为运行时,所以不驻留
- !!Pycharm做了优化,不符合标识符的字符串也驻留
- 启动驻留机制的时机——编译会驻留,运行时不会驻留
- 如何强制启动驻留——
str1=sys.intern(str2)
让两个字符串指向同一份内存,即使不满足上述驻留规则 - 实现驻留的原理
- 系统维护了一个interned字典,每次创建字符串的时候都会先看字典中是否已存在,如果存在就直接引用,不存在就分配内存并将其加入字典
- 为啥要有?
- 2.2)常用操作
-
获取字符串中第一个查找字符串的索引
index(查找str)/find(查找str)
find找不到返回-1,index报错 -
获取字符串中最后一个查找字符串的索引
rindex(查找str)/rfind(查找str)
-
全部大写
upper()
-
全部小写
lower()
-
大写变小写,小写变大写
swapcase()
-
首个单词首字母大写,其余全部小写
capitalize()
-
每个单词都是首字母大写其余小写
title()
-
居中、左对齐、右对齐
center/ljust/rjust(长度,填充符(默认是空格))
-
右对齐,零填充
zfill()
-
正向分割列表、逆向分割列表
split/rsplit(sep=分隔符(默认空格),maxsplit=最大分割几份(默认从头分到尾))
-
判断是否是合法标识符
isidentifier()
-
判断是否全是空格
isspace()
-
判断是否全是字母
isalpha()
-
判断是否全是阿拉伯数字
isdecimal()
-
判断是否是数字,包括任何一种语言表示的数字
isnumeric()
-
判断是否仅由数字和字母组成
isalnum()
-
替换
replace(替换str,使用谁替换,替换几个)
-
拼接
‘拼接符’.join(str/list)
如果是str则拼接单个字符 -
比较大小
>、<、>=、<=、==、!=
ord(字符)获取字符ascii值 -
也可以切片
字符串名[start:stop:step]
step可以为负数 -
格式化字符串——3种方式
-
字符和字节的转换
- 字符转字节,编码过程
字符串.encode(encoding='GBK')
- 字节转字符,解码过程
字节.decode(encoding='GBK')
- 字符转字节,编码过程
-
- 2.1)驻留池:java中的常量池类似(相同的内容只存一份)
2)“复杂类型”——4个
- 列表 list:等价于其它语言中的数组,如等价于java中的ArrayList< Object>
-
内存结构
-
特点
- 元素有序、可重复、元素类型可以不相同
- 存储元素的空间可自动伸缩(有动态扩容和缩容机制,有动态垃圾回收和内存分配机制)
- 元素索引有两种标志方式:正向(0 ~ length-1)和逆向(-length ~ -1)
-
操作
-
python中的范围start&stop,都是左闭右开
-
创建
- 方式1:
[ 元素1,元素2,...]
- 方式2:内置函数
lsit([ 元素1,元素2,...])
- 列表生成式
列表名=[i*2 for i in range(1,10) 还可以加if或嵌套for语句]
- i表示一次为1到9的值
- 存入列表的值为列表元素的表达式i*2
- 方式1:
-
拷贝
copy()
-
统计某个元素的个数
count(元素值)
-
获取元素索引
index(元素)
:查询元素索引index(start,stop,元素)
:从[start,stop)索引范围内查询元素的索引
-
添加——元素可以是任何类型,包括复杂类型
append(元素)
:表示添加一个元素,无论元素是基本类型还是复杂类型,都当作一个元素添加到列表的最后extend(元素)
:表示至少添加一个元素,如果元素为复杂类型,会将元素中的每一个元素当作单独的元素一次插入列表insert(index,元素)
:表示添加到指定位置
-
删除
remove(元素)
:删除指定的一个元素(有重复只删除第一个)pop()/pop(index)
:删除最后一个/删除指定index位置元素clear()
:清空所有列表中所有元素,该列表成空列表del 列表名
:删除列表,该列表在内存中不存在了
-
修改
列表名[index]=值
-
排序
sort()/sort(reverse=True)
:从大到小排序/从小到大排序sorted(列表名)/sorted(列表名,reverse=True)
:从大到小排序/从小到大排序,这是内置函数
-
切片/获取子列表
-
这种方式可以对列表进行删除+添加的组合操作
-
与前面方法不同点在于,原列表不会变化,但是切片是创建的一个新列表
-
表示方式:
列表名[start:stop:step]
- 创建了一个新列表,即分配了新的内存空间
- 将原列表中从[start,stop)索引范围内,按照step步长读元素,存一份在切片中/新列表中
- 每一项都可以省略,默认从最开始,默认到最后,默认步长为1
- step可以为负数,表示反向取
-
使用:
-
新列表名=原列表名[start:stop:step]
:表示获取子列表
-
原列表名[start:stop]=列表
:表示将原列表中对应[start,stop)位置替换为右侧列表内容
-
-
-
-
- 元组:特殊的列表
-
内存结构
-
特点
- 元素有序、可重复、元素类型可以不相同
- 多个操作时,不需要加锁
- 初始化之后不可更改,即为不可变序列,(如果元素是复合类型的,则元素的元素可以修改)
-
不可变序列没有增删改操作,只有创建操作
-
操作:
- 创建
(元素1,元素2,...)
tuple((元素1,元素2,...))
- 当元组中只有一个元素时,元素后面的逗号必须保留
- 没有“元组”生成式
- 创建
-
- 字典:等价于HashMap
-
内存结构
-
特点
- 每个元素都是以k-v键值对的形式存储,k各不相同,v可以相同
- 元素无序,因为其实际存储位置由
hash(key)
计算所得 - k必须是不可变对象,如数和字符串,不可变对象是指值变了,内存位置一定改变
- 自动伸缩内存大小
- 比较浪费空间
-
操作
- 创建
{'k1':v1,'k2':v2,...}
dict({'k1':v1,'k2':v2,...})
- 字典生成式
字典名={itemK:itemV for itemK,intemV in zip(itemKs,itemVs)}
- itemKs和itemVs分别是表示字典中k和v的列表
- zip是打包函数,打包后使得k-v按顺序一一对应,并且当数量不一致时,以少的为基准
- 添加和修改
字典名['k']=value
:有则改之,无则加之
- 获取
字典名['k']
字典名.get('k')/字典名.get('k',默认值)
:当k不存在时返回默认值
- 删除
clear()
del 字典名
- 视图操作
- 获取所有k
keys()
- 获取所有v
values()
- 获取所有键值对k-v
items()
- 获取所有k
- 创建
-
- 集合:没有v的字典
-
内存结构
-
特点
- 每个元素都是以k的形式存储,k各不相同
- 元素无序,因为其实际存储位置由
hash(key)
计算所得 - k必须是不可变对象,如数和字符串,不可变对象是指值变了,内存位置一定改变
- 自动伸缩内存大小
- 比较浪费空间
-
操作
- 创建
{'k1','k2',...}
这种方式不能创建集合,查看类型是字典set({'k1‘,'k2',...})
- set中参数还可以是列表、元组、字符串,同时会做去重操作
- 集合生成式
集合名={item for item in range(9)}
同列表,只不过要换成大括号
- 添加
add()
加一个update()
加多个
- 删除
remove(元素)
不存在会报错clear()
全删pop()
随意的删除一个dicard(元素)
不存在不报错
- 集合操作
- 集合是否相等
set1==set2 set1!=set2
- 子集关系
sonSet.issubset(superSet)
- 超(“父”)集关系
superSet.issuperset(sonSet)
- 是否有交集
set1.isdisjoint(set2)
- 交集
set1.intersection(set2) 或 set1&set2
- 并集
set1.union(set2) 或 set1|set2
- 差集
set1.difference(set2) 或 set1-set2
- 对称差集
set1.symmetric_diffrence(set2) 或 set1^set2
- 集合是否相等
- 创建
-
2、类型转换
- 三个转换函数
int()
、str()
和float()
- 要转换成谁,就调用类型同名的函数
- 转换规则(不能自动类型转换,需要手动转换。+连接的字符串,每一部分都必须是字符串类型)
-
变成int
-
str:只有样子本来是整数的才可以转成功,否则报错
-
float:小数点后直接截断
-
-
变成float
- int:补充
xx.0
- str:只有样子本来是浮点数的才可以转成功,否则报错
- int:补充
-
变成str
- 没啥讲究
-
五、变量和标识符
1、变量
- 分类
- 全局:在模块中定义
- 局部:在方法或函数体中定义,如果加上
global
修饰,可以将局部变全局
- 变量中实际的值存储的都是对象的内存地址,id就是内存地址
- 当重新复制,变量中存储的值会变化
- 变量中地址指向的对象中由一些对象信息和对象实际存储值组成:id+type+bool+…+value
- 哪些对象的
bool()
为False呢?——其实就是任何数据类型的空值形式- False布尔值
- none
- 数值0、0.0
- 空字符串
- 空列表:[] 、list()
- 空元组:()、tuple()
- 空字典:{}、dist()
- 空集合:set()
- 哪些对象的
id是真实地内存地址吗?还是只是跟内存地址有映射关系?
2、标识符
要求:
- 不能是保留字
- 只能是数字、字母、英文下划线
- 数字不能开头
- 严格区分大小写
四、运算符
优先级:
算数 > 位 > 比较 > 逻辑 > 赋值
1、算数运算
- 加、减、乘、除
- 幂等
2**3=2的三次方
- 求商
9//4=2
:精确结果向下取整(如,9//-4=-3,因为9除以-4为-2.25,向下取整为-3) - 求余数
9%4=1
:余数=被除数-除数*商(如,9%-4=-3,因为9-负4乘以负3=-3)
2、比较运算
- > 、<、>=、<=、==、!=:比较变量的value
- is 和 is not:比较变量的id
3、逻辑运算
- and、or、not
- in、not in : 如,
'w' in 'world'
4、位运算
&
:11得1,否则为0|
:00得0,否则为1<<
:左移,低位补0,高位溢出截断>>
:右移,高位补0,低位截断
5、赋值
- 支持链式赋值
a=b=c=1
- 支持系列解包赋值
a,b,c=1,2,3
等价于a=1 b=2 c=3
五、控制语句
1、顺序执行
没啥好说的,跟其它语言语法一样
2、条件执行
- 条件之后
:
结束 - 没有大括号,通过缩进来判断代码体范围
- 三个保留字:
if
、elif
、else
- 可以嵌套使用
#一般的表示形式
if 条件:
执行语句
执行语句
elif 条件:
执行语句
执行语句
else:
执行语句
执行语句
其它执行语句
#简化的条件表达式
if条件满足的执行语句 if 条件 else else中执行语句
其它执行语句
3、pass语句
- 它只是一个占位符,标志此处有代码块,使得语法不报错
- 使用场景:程序员还没有想好具体写什么代码,但是这一部分应该有代码逻辑
4、循环语句
1)循环语句中经常搭配使用的一个函数range()
- 三种重载形式
- range(stop):[0,stop)步长为1
- range(start,stop):[start,stop)步长为1
- range(start,stop,step):[start,stop)步长为step
- 函数特点
- 返回值是一个range对象,每一个range对象占用内存空间大小是相等的,因为它实际存储的不是每一个数,而是三个参数值:起始值+终止值+步长
- 可以使用
in
和not in
来判断其是否在范围中
2)、循环语句
2.1)两种表示方式
while
while 条件:
循环体
其它执行语句
for-in
for-in 一个变量名 in 一个范围对象/集合...:
循环体
其它执行语句
2.2)中断循环的方式
没啥好说的,还是break
和continue
2.3)循环可以和else
一起使用
表示如果没有使用break来结束循环,即正常全部循环完毕后必须执行的代码逻辑
while/for-in 正常该怎么表示怎么表示:
循环体
else:
循环正常结束后需要执行的内容
其它执行语句
5、异常捕获处理语句
try:
可能会发生异常的语句
except 异常名 [as 别名]:
发生异常后的处理语句
[else:]
没有发生异常的执行语句
[finally:]
无论是否发生异常都会执行的语句
常见的异常
异常名 | 异常表征 |
---|---|
SyntaxError | 语法 |
IndexError | 索引 |
NameError | 未声明或未初始化 |
ValueError | 无效传参 |
KeyError | 无效关键字 |
ZeroDivisionError | 除以0 |
打印异常错误信息的模块import traceback
六、函数
1、函数定义
def 函数名(参数列表):
函数体
[return语句]
- 参数列表
- 可以为空
- 参数分类
- 位置参数
add(10,20)
:通过位置一一赋值 - 关键字参数
add(b=20,a=10)
:通过形参名赋值
- 位置参数
- 参数列表可包含参数亚子
-
正常
def fun(a,b,c)
-
包含不确定个数的位置形参
def fun(*args)
一个参数列表只能包含一个这样的参数,其存储形式为元组 -
包含不确定个数的关键字形参
def fun(**args)
一个参数列表只能包含一个这样的参数,其存储形式为字典
-
!!!上面三种形式参数可以被同时包含
-
第四种方式
def fun(a,b,*,c,d)
==a和b表示位置参数,c和d表示位置参数
-
- 返回语句
- 如果没有返回值,return可以省略不写
- 可以同时返回多个值,值会以元组的形式返回
2、调用
可以将参数列表以字典、列表形式传入,字典前加**
,列表前加*
如果超出参数列表传参个数,会报错
七、模块和包
1、模块
- 一个
XXX.py
文件就是一个模块 - 优势
- 解决命名冲突问题
- 方便协作开发
- 提高代码可维护性和可复用性
- 模块中可以包含的内容
- 函数>=0
- 类>=0
- 语句>=0
- 分类
- 第三方:需要安装(下载)
pip install 模块名
,安装后才可以引用 - 内置:不需要安装,直接引用即可
- 第三方:需要安装(下载)
- 引用方式
- 全模块引用
import 模块名 [as 别名]
- 可引用模块中部分内容
from 模块名 import 函数/类/变量
- 全模块引用
- 模块中有可执行语句时,不想在引用时调用,可以为其添加主程序调用模式。如下,表示只有该模块以主程序运行时,if体内的语句才会执行
常用内置模块
模块名 | 功能 |
---|---|
sys | 解释器相关 |
os | 操作系统相关 |
time | 时间 |
calendar | 日期 |
urllib | 网络操作相关 |
json | 序列化和反序列化 |
re | 正则 |
math | 数学运算 |
decimal | 精确计算 |
logging | 日志 |
2、包
- 打包模块,与java中package一样
- 包与目录区别:多了一个文件
__init__.py
八、类与对象
1、类定义
class 类名:
类属性 #相当于java类中静态变量,所有类共享
#对象分配内存方法(java中new关键字),可以不重写,相当于直接继承父类中的new方法
def __new__(cls,参数列表):
方法体
#对象初始化方法(java中构造函数),可以不重写,相当于直接继承父类中的init方法
def __init__(self,参数列表):
self.属性名=参数名 #相当于java类中非静态属性,单独属于对象
self.__attri=参数名 #参数前加两个下划线可以让其“私有化”
#实例方法(java非静态方法)
def 实例方法名(self,参数列表):
方法体
#静态方法
@staticmethod
def 静态方法名(参数列表):
方法体
#类方法(java静态方法)
@classmethod
def 类方法名(cls,参数列表):
方法体
- 查看对象可用的所有方法和属性
dir(对象名)
- 类中代码块
- 实例方法:
对象.方法名()/类名.方法名(对象)
通过类或对象调用,需要传一个对象 - 静态方法:相当于类中定义了一个函数,函数体中使用类中的方法属性时,必须要显示指明
- 类方法:通过类或对象调用,需要传一个类
- 实例方法:
- 为啥说
__init__(self)
中加__属性可以假私有化- python没有私有化权限的限定符
- 说不可使用,本质上是对 __属性名 加了处理,变成 _类名__属性名, 导致调用时不存在
- def定义的代码块,在类中叫方法,在类外叫函数
2、创建对象
#创建对象的方式
对象名=类名(init对应的参数列表)
#动态添加对象属性
对象名.对象特有attr
#动态添加对象方法
def 函数名():
函数体
对象名.方法名=函数名
- python是一种动态语言,它可以让同一个类创建的对象拥有不同的属性和方法
3、对象和类的类型
- 对象的类型
<class '__main__.类名'>
- 类的类型
<class 'type'>
4、继承
class Son(Father1,Father2):
pass
- python支持多继承,如果不显示表示,则表示其父类为
Object
- 子类可以通过
super().父类方法名
来调用父类方法 - 子类init方法中必须先显示调用父类的init方法
5、封装
都一样,没啥好说的
6、多态
python中的多态与继承没有那么大的关系,只要该对象有同名方法,就可以实现多态
class A:
def dance():
print('A dances')
class B:
def dance():
print('B dances')
class C:
def dance():
print('C dances')
class D(C)
def dance():
print('D dances')
def fun(obj):
obj.dance()
#可以呈现多态
a=A()
b=B()
c=C()
d=D()
fun(a) # A dances
fun(b) # B dances
fun(c) # C dances
fun(d) # D dances
7、深拷贝和浅拷贝
- 概念没啥可说的,跟其它语言一样,python一般都是浅拷贝
- 需要使用的模块
import copy
- 深拷贝
copy.deepcopy()
- 浅拷贝
copy.copy()
- 深拷贝
8、需要特殊关注的方法和属性
__str__()
等价于java中toString()__add__()
重写之后可以使得对象可以用+
计算__dict__
记录方法属性的字典__class__
对象类型__bases__
类的父类们__base__
类的第一个父类__subclasses__
类的子类们
九、文件操作
1、文件的操作流程
#打开文件
file=open()
#文件操作
file.read() #读全部
file.readline() #读一行
file.readlines() #读多行
file.seek() #移动文件中指针
file.tell() #返回文件指针当前所在位置
#关闭文件
file。close()
2、with语句
with 上下文管理器 [as target]:
with执行语句
- 上下文管理器都遵寻上下文管理协议
- 需要重写
__enter__()
和方法__exits__()
- 需要重写
- 作用
- 无论程序是否正常关闭,都可以正常关闭上下文,释放资源
十、os和os.path模块
1、os
getcwd()
查看当前所在路径listdir(path)
列举path目录下的所有文件remove(path)
删除path指定的文件rmdir(path)
删除path指定的目录mkdir(path)
创建path指定的目录remove()
删除文件rename()
重命名文件makedirs()
创建多层目录removedirs()
删除多层目录
2、os.path
abspath(path)
返回当前文件位置的绝对路径split(path)
将指定文件的路径分解为(文件夹路径, 文件名),返回的数据类型是元组类型isfile()
是否为文件basename()
去掉目录路径,返回文件名dirname()
去掉文件名,返回目录路径