Python语法基数

  1. 前置知识
    1. print函数
    2. 注释
    3. 转义字符
    4. 二进制与字符编码 (不重要)
    5. python 中的保留字与标识符(不重要,用多了就知道了)
  2. 变量与数据类型
    1. 变量的定义与使用
      1. 变量由三个部分组成
      2. 多次赋值后,变量名会指向一个新的空间
    2. 数据类型
      1. 常用的数据类型
      2. 数据类型转换
  3. 运算符
    1. input 函数
    2. python中的运算符
    3. 运算符的优先级(加括号就行)
  4. 程序的组织结构
    1. 顺序结构(略)
    2. 选择结构(if)
      1. 对象的布尔值
      2. 单分支结构:如果…就…
      3. 双分支结构:如果…不满足…就…
      4. 多分支结构
      5. 嵌套if(略)
      6. 条件表达式:if-else 的简写
    3. pass 语句
    4. 循环结构(while/for-in)
      1. rang( ) 函数
      2. while
    5. for-in
      1. 流程控制语句:break与continue
      2. else
      3. 嵌套循环
  5. 列表(数组)
    1. 列表的创建:
    2. 列表的特点
    3. 列表元素的查询操作
    4. 列表元素的增加操作
    5. 列表元素的删除操作
    6. 列表元素的修改操作
    7. 列表元素的排序操作
    8. 列表生成式
  6. 字典
    1. 什么是字典
    2. 字典的创建
    3. 字典元素的获取
    4. 字典元素的增删改
    5. 获取字典视图
    6. 字典元素的遍历
    7. 字典元素的特点
    8. 字典生成式
  7. 元组
    1. 什么是元组
    2. 元组的创建
    3. 为什么要将元组设计成不可变序列
    4. 元组中存储的是对象的引用
    5. 元组的遍历
  8. 集合
    1. 什么是集合
    2. 集合的创建方式
    3. 集合的相关操作
      1. 判断操作:in或not in
      2. 新增操作
      3. 修改操作
    4. 集合间的关系
    5. 集合的数据操作
    6. 集合生成式
  9. 列表、字典、元组、结合总结
  10. 字符串
    1. 字符串的驻留机制
    2. 字符串的常用操作
      1. 查询操作
      2. 字符串的大小写转换操作
      3. 字符串内容对齐操作
      4. 字符串劈分操作
      5. 判断字符串操作的方法
      6. 字符串的操作的其他方法
      7. 字符串的比较操作
      8. 字符串的切片操作
      9. 格式化字符串
      10. 字符串的编码转换
  11. 函数
    1. 函数的创建:
    2. 函数的参数传递
      1. 函数调用的参数传递内存分析:传递的是地址值
    3. 函数的返回值
    4. 函数的参数定义
    5. 变量的作用域
    6. 递归函数
  12. 异常
    1. 异常的处理机制
    2. python常见的异常类型
    3. traceback模块
  13. 对象
    1. 两大编程思想
    2. 类和对象的创建
      1. 数据类型与对象:
      2. 类的创建
      3. 对象的创建
    3. 类对象和类属性
      1. 类属性-类方法-静态方法的使用
    4. 动态绑定属性和方法
    5. 对象的三大特性之封装
    6. 对象的三大特性之继承
    7. 方法重写
    8. object类
    9. 对象的三大特性之多态
    10. 特殊方法和特殊属性
    11. 类的浅拷贝与深拷贝
  14. 模块
  15. 文件
    1. 编码格式
    2. 文件的读写原理
    3. 文件读写操作
    4. 光标操作
    5. 文件对象常用的方法
    6. 目录操作
参考资料:https://www.bilibili.com/video/BV1wD4y1o7AS

前置知识

print函数

print 函数的输出内容:数字、字符串、含有运算符的表达式
print 函数输出的地方:显示器、文件
print 函数输出的形式:换行与不换行

注释

单行注释:# 注释内容
多行注释:’’’ 注释内容 ‘’’
  使用jupetr需要在后面加代码才能识别为多行注释
编码格式声明注释:
   #coding:gbk —> 文件以gbk模式存储
   #coding:utf-8 —> 文件以utf-8存储
python3 默认格式为utf-8

# 数字
print(1.2)
# 字符串
print('nihao')
# 含有运算符的表达式
# 3和1 为运算数, +-*/=等等为运算符。运算数+运算符的式子称为表达式
print(3+1)
1.2
nihao
4
# 输出到文件当中
# open('文件路径',‘选择那种方式打开文件’)
# a+ 表示在该路径下,有文件就以读写的方式打开文件并在文件后面继续追加内容,没文件就创建文件
fp=open('/Users/xieshaolin/workpalce/python/nihao.txt','a+')
print("nihao",file=fp)
fp.close()
# 用“,”进行分隔在一行进行输出
print('ni')
print('hao')
print('ni','hao')
# print函数默认end=\n(换行符),end=','表示以','结尾 end=‘ ’ 表示以空格结尾
print('bu',end=' ')
print('hao',end=' ')
ni
hao
ni hao
bu hao 

转义字符

\n —> 换行符 \t —> 制表符
\—> 反斜杠 '—> 单引号
不重要,遇到查一下就好

二进制与字符编码 (不重要)

python 中的保留字与标识符(不重要,用多了就知道了)

保留字:如break,continue等(用多了就知道了)
标识符:严格区分大小写,不能以数字开头,字母数字和下划线

变量与数据类型

变量的定义与使用

变量由三个部分组成

如 name = ‘玛丽亚’
标识:上面的name,表示对象所存储的内存地址,id(obj)可以获取
类型:表示对象的数据类型,上面‘’表示该对象为字符串类型,type(obj)可以获取
值:表示对象所存储的具体数据,print(obj)可以获取
上面的 = 为赋值运算
name = ‘玛丽亚’ 含义: 把一个字符串类型,值为玛丽亚的一个数据,赋值给name(内存地址)所代表的内存村空间

多次赋值后,变量名会指向一个新的空间

name = '玛丽亚'
print('值=',name,';name的内存地址=',id(name),';name的类型=',type(name))
name = '玛丽亚'
print('值=',name,';name的内存地址=',id(name),';name的类型=',type(name))
name = '玛丽亚'
print('值=',name,';name的内存地址=',id(name),';name的类型=',type(name))
# 以上三次赋值,内存地址都变了,表示3次赋值指向了不同的内存空间
值= 玛丽亚 ;name的内存地址= 4348995024 ;name的类型= <class 'str'>
值= 玛丽亚 ;name的内存地址= 4367296144 ;name的类型= <class 'str'>
值= 玛丽亚 ;name的内存地址= 4367295280 ;name的类型= <class 'str'>

数据类型

常用的数据类型

  • 整数类型 –> int –> 100
  • 服点数类型 –> float –> 3.1415926
  • 布尔类型 –> bool –> true/false
  • 字符串类型–> str –> ‘人生苦短‘
# 整数类型的进制问题 
print('默认十进制=',16)
print('0b开头表示二进制=',0b10000)
print('0o开头表示八进制',0o20)
print('0x开头表示十六进制',0x1)
# print默认输出的是十进制,所以print内部做出了转换,把其他进制都转换成了十进制
默认十进制= 16
0b开头表示二进制= 16
0o开头表示八进制 16
0x开头表示十六进制 1
# 浮点数存储不精确
print('1.1+2.2=%s'%(1.1+2.2))
# 浮点数之间的计算需要使用:decimal
from decimal import Decimal
print('1.1+2.2=',(Decimal('1.1')+Decimal('2.2')))
# 并不是所有的浮点数相加都不准确,这和二进制的底层相关
print('1.1+1.2=%s'%(1.1+1.2))
1.1+2.2=3.3000000000000003
1.1+2.2= 3.3
1.1+1.2=2.3
# 布尔值和整数可以相互转换
# True = 1 False = 0    注意首字母大写
print(True+1,False+1)
2 1
# 字符串又被称为不可变大夫序列
str1='使用单引号表示'
str2="使用双引号表示"
str3="""使用三引号,
可以换行"""
str4='''使用三引号,
可以换行'''
print(str1,type(str1))
print(str2,type(str2))
print(str3,type(str3))
print(str4,type(str4))
使用单引号表示 <class 'str'>
使用双引号表示 <class 'str'>
使用三引号,
可以换行 <class 'str'>
使用三引号,
可以换行 <class 'str'>

数据类型转换

str –> int ===> int( )
int –> str ===> str( )
str –> float ===> float( )
float –> str ===> str( )
int –> float ===> float( )
float –> int ===> int( )

print('------------------int float bool --> str----------------------')
a = 9
b = 9.8
c = True
d = False
print(a,type(a),'===>',str(a),type(str(a)))
print(b,type(b),'===>',str(b),type(str(b)))
print(c,type(c),'===>',str(c),type(str(c)))
print(d,type(d),'===>',str(d),type(str(d)))
print('------------------str float bool --> int----------------------')
a1='9'
a2='9.8'
a3='nihao'
b1=10.7
c1=True
c2=False
# 只能把整数的字符窜转换为整数,小数或者文字的字符串都会报错
print(a1,type(a1),'===>',int(a1),type(int(a1)))
#print(a2,type(a2),'===>',int(a2),type(int(a2)))
#print(a3,type(a3),'===>',str(a3),type(str(a3)))
# 直接截取整数部分
print(b1,type(b1),'===>',int(b1),type(int(b1)))
# True=1 False=0
print(c1,type(c1),'===>',int(c1),type(int(c1)))
print(c2,type(c2),'===>',int(c2),type(int(c2)))
print('------------------str int bool --> float----------------------')
x='9'
y='9.8'
z='nihao'
u=9
v=True
w=False
#整数和小数可以转,字符不能
print(x,type(x),'===>',float(x),type(float(x)))
print(y,type(y),'===>',float(y),type(float(y)))
#print(z,type(z),'===>',int(z),type(int(z)))
print(u,type(u),'===>',float(u),type(float(u)))
print(v,type(v),'===>',float(v),type(float(v)))
print(w,type(w),'===>',float(w),type(float(w)))
------------------int float bool --> str----------------------
9 <class 'int'> ===> 9 <class 'str'>
9.8 <class 'float'> ===> 9.8 <class 'str'>
True <class 'bool'> ===> True <class 'str'>
False <class 'bool'> ===> False <class 'str'>
------------------str float bool --> int----------------------
9 <class 'str'> ===> 9 <class 'int'>
10.7 <class 'float'> ===> 10 <class 'int'>
True <class 'bool'> ===> 1 <class 'int'>
False <class 'bool'> ===> 0 <class 'int'>
------------------str int bool --> float----------------------
9 <class 'str'> ===> 9.0 <class 'float'>
9.8 <class 'str'> ===> 9.8 <class 'float'>
9 <class 'int'> ===> 9.0 <class 'float'>
True <class 'bool'> ===> 1.0 <class 'float'>
False <class 'bool'> ===> 0.0 <class 'float'>

运算符

input 函数

present=input(str)
str –> 打印在控制台的语句
present –> str类型,是我们输入的语句

python中的运算符

  • 算术运算符
    • ‘+’ 加法运算符
    • ‘-’ 减法运算符
    • ‘*’ 乘法运算符
    • ‘/’ 除法运算符
    • ‘//’ 整除运算符
    • ‘%’ 取余运算
    • ‘**’ 幂运算符
  • 赋值运算符
    • =赋值运算符,从右执行到左
    • 链式赋值: a=b=c=20;a、b、c三个指向同一个地址值
    • 参数赋值: +=、-=、*=、/=、//=、%=
      • a+=2相当于 a=a+2,其他类似
    • 解包赋值: a,b,c=20,30,40 ===> a=20,b=30,c=40,顺序和个数要一致
      • 解包赋值常用于变量交换
        • 没有解包赋值交换a和b: temp=a;a=b;b=temp
        • 有解包赋值一行搞定: a,b=b,a
  • 比较运算符
    • 比较运算符返回的是bool(False/True)
    • 比较对象的value:>,<,>=,<=,!=,==
    • 比较对象的id(地址值):is,is not
    • 与java不同,java==比较的是地址值
  • 布尔运算符
    • and 且
    • or 或
    • not 非
    • in 在…里面
    • not in 不在…里面
  • 位运算符(难但用的少
    • 位与&: 对应数位都是1(true),结果才是1(true),否则位0(false)
    • 位或|: 对应数位都是0(false),结果才是0(false),否则位1(true)
    • 左移位运算符<<: 高位溢出舍弃,低位补0
    • 右移位运算符>>: 低位溢出舍弃,高位补0

运算符的优先级(加括号就行)

present=input('你几岁?')
print(present,type(present))
你几岁?1
1 <class 'str'>
print('5/3=',5/3)
print('5//3=',5//3)
print('5%3=',5%3)
print('2的3次方=',2**3)
print('3的2次方=',3**2)
print('---------------------算术运算符:正负号问题----------------------------')
# 取整//:一正一负向下取整
print('-5//-3=',-5//-3)
print('-5//3=',-5//3)
print('5//-3=',5//-3)
# 取余% : 余数=被除数-除数*商, 其中 商遵循 一正一负上下整
print('-5%-3=',-5%-3) # -5-(-3*1)= -2 ---> -3 + -2 = -5
print('-5%3=',-5%3) # -5-(3*-2)= 1 ---> 3*(-2) + 1 = -5
print('5%-3=',5%-3) # 5-(-3*-2)= -1 ---> -3*(-2) - 1 = 5
5/3= 1.6666666666666667
5//3= 1
5%3= 2
2的3次方= 8
3的2次方= 9
---------------------算术运算符:正负号问题----------------------------
-5//-3= 1
-5//3= -2
5//-3= -2
-5%-3= -2
-5%3= 1
5%-3= -1
# a 与 b 的地址值相同是因为常量在内存空间的地址是固定的,即内存中有专门的一个区域来存储常量
a=10
b=10
print('a==b为',a==b)
print('a is b为',a is b)
print('a的ID为',id(a))
print('b的ID为',id(b))
list1=[10,11]
list2=[10,11]
print('list1==list2为',list1==list2)
print('list1 is list2为',list1 is list2)
print('list1的ID为',id(list1))
print('list2的ID为',id(list2))
a==b为 True
a is b为 True
a的ID为 4303518736
b的ID为 4303518736
list1==list2为 True
list1 is list2为 False
list1的ID为 4368027328
list2的ID为 4368027520
s = 'nihao'
print('n' in s)
print('b' not in s)
l = [10,20]
print(10 in l)
print(30 not in l)
True
True
True
True

程序的组织结构

顺序结构(略)

选择结构(if)

对象的布尔值

  • 获取对象的布尔值:bool()
  • 以下对象的布尔值都是False
    • False
    • 数值0
    • None
    • 空字符串
    • 空列表
    • 空数组
    • 空字典
    • 空集合

单分支结构:如果…就…

语法结构:
if 条件表达式:
  条件执行体

双分支结构:如果…不满足…就…

语法结构:
if 条件表达式:
  条件执行体1
else:
  条件执行体2

多分支结构

语法结构:
if 条件表达式:
  条件执行体1
elif:
  条件执行体2
elif:
  条件执行体N
[elif:]
  条件执行体N+1

嵌套if(略)

条件表达式:if-else 的简写

语法结构:x if 判断条件 else y
运算规则:如果判断条件为ture,则执行x并返回x的结果;为false则执行y并返回y的结果

pass 语句

是什么:语句什么都不做,只是一个占位符,用在语法上需要语句的地方
何时用:在搭建语法结构,但还没想好怎么写代码的时候
用在哪:
- if语句的条件执行体
- for-in语句的循环体
- 定义函数时的函数体

类似java的todo

# 单分支结构
money=1000
m=int(input('请输入取款金额'))
if money>=m: # 和java不一样,java是(),这里是:
    money-=m # 执行的语句要缩紧
    print('取款成功,余额为:',money)
请输入取款金额500
取款成功,余额为: 500
# 双分支结构
num=int(input("请输入一个整数:"))
if num%2==0:
    print("您输入的是一个偶数")
else:
    print("您输入的是一个奇数")
请输入一个整数:23
您输入的是一个奇数
# 多分支结构
score = int(input("请输入一个成绩:"))
if(score>=90 and score<=100): # 加()也不影响
    print("A")
elif score<90 and score>=80:
    print("B")
elif score<80 and score>=70:
    print("C")
elif score<70 and score>=60:
    print("D")
elif score<60 and score>=0:
    print("E")
else:
    print("非法数据")
    
请输入一个成绩:-1
非法数据
# 条件表达式
a = int(input("请输入第一个数字:"))
b = int(input("请输入第二个数字:"))
print(a,'>=',b) if a>=b else print(a,'<',b) 
请输入第一个数字:2
请输入第二个数字:3
2 < 3
# pass语句
a= int(input('请输入一个整数'))
if a>0:
    pass # 有时候这部分的代码没有想好,但是如果没想好就放在这里,运行程序的时候会报错
else:
    pass # 在java中if后面不写语句也是不会报错的
if a>10:{# 如果这里加{}后程序也不报错了
    
}
请输入一个整数1

循环结构(while/for-in)

rang( ) 函数

  • 用于生成一个整数序列
  • 创建range()对象的三种方式
    • range(stop):创建一个【0,stop)之间的整数序列,步长为1
    • range(star,stop):创建一个【start,stop)之间的整数序列,步长为1
    • range(star,stop,step):创建一个【start,stop)之间的整数序列,步长为step
    • 步长就是相邻的两个数之间的差距
  • 返回值是一个迭代器对象,不是列表
  • range类型的优点:不管range对象表示的整数序列有多长,所有range对象占用的内存空间都是相同的。
    因为仅仅需求存储start,stop和step,只有当用到range对象时,才会去计算序列中的相关元素
  • in语not in 判断整数序列是否存在(不存在)制定的整数
# range(stop)
r=range(10);# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(r) # range(0, 10)---> 迭代器对象
print(list(r))# 用于查看range对象中的整数序列 ---> list是列表的意思
range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# range(start,stop)
r=range(1,10);# [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(r))# 用于查看range对象中的整数序列 ---> list是列表的意思
[1, 2, 3, 4, 5, 6, 7, 8, 9]
# range(start,stop,step)
r=range(1,10,2);# [1, 3, 5, 7, 9]
print(list(r))# 用于查看range对象中的整数序列 ---> list是列表的意思
[1, 3, 5, 7, 9]
r=range(1,10,2)# [1, 3, 5, 7, 9]
print(1 in r)
print(2 in r)
True
False

while

while 条件表达式:
  循环体
条件表达式为true,会一直执行循环体

a = 1
sum=0
while(a<=10):
    sum+=a
    a+=1
print('sum=',sum)
sum= 55

for-in

for 自定义的变量 in 可迭代的对象:
   循环体

  • 循环体内不需要访问自定义变量,可以将自定义变量替代为下划线
# 遍历字符串
for item in 'Python':
    print(item,end=',')
P,y,t,h,o,n,
# 遍历range
sum=0
for i in range(1,11):
    sum+=i
print('sum=',sum)
sum= 55
# 如果循环体中用不到自定义变量,可以 _ 代替
for _ in range(5):
    print('人生苦短,我用python')
人生苦短,我用python
人生苦短,我用python
人生苦短,我用python
人生苦短,我用python
人生苦短,我用python
# 水仙花数:abc=a*a*a+b*b*b+c*c*c
for item in range(100,1000):
    a=item//100
    b=(item//10)%10
    c=item%10
    if(item-a**3-b**3-c**3==0):
        print(item,end=',')
153,370,371,407,

流程控制语句:break与continue

  • break:结束循环
  • continue:结束当前循环
  • 对于二重循环,break与continue用于控制本层循环

else

  • if+else:条件表达式不成立,执行else语句
  • while+else:没遇得到break,执行else语句
  • for-in+else:没遇得到break,执行else语句
# 使用else
for item in range(3):
    pwd=int(input("请输入密码:"))
    if(pwd==8888):
        print('密码正确')
        break
    else:
        print("密码不正确")
else:
    print("对不起,三次密码均错误!")
请输入密码:8888
密码正确
# 不使用else要先判断item才能达到上面的效果
for item in range(3):
    pwd=int(input("请输入密码:"))
    if(pwd==8888):
        print('密码正确')
        break
    else:
        print("密码不正确")
    if(item==2):
        print("对不起,三次密码均错误!") 
请输入密码:3
密码不正确
请输入密码:3
密码不正确
请输入密码:3
密码不正确
对不起,三次密码均错误!

嵌套循环

# 99乘法表 
for a in range(1,10):
    for b in range(1,a+1):
        print(b,'x',a,'=',b*a,end='\t')
    print()
1 x 1 = 1	
1 x 2 = 2	2 x 2 = 4	
1 x 3 = 3	2 x 3 = 6	3 x 3 = 9	
1 x 4 = 4	2 x 4 = 8	3 x 4 = 12	4 x 4 = 16	
1 x 5 = 5	2 x 5 = 10	3 x 5 = 15	4 x 5 = 20	5 x 5 = 25	
1 x 6 = 6	2 x 6 = 12	3 x 6 = 18	4 x 6 = 24	5 x 6 = 30	6 x 6 = 36	
1 x 7 = 7	2 x 7 = 14	3 x 7 = 21	4 x 7 = 28	5 x 7 = 35	6 x 7 = 42	7 x 7 = 49	
1 x 8 = 8	2 x 8 = 16	3 x 8 = 24	4 x 8 = 32	5 x 8 = 40	6 x 8 = 48	7 x 8 = 56	8 x 8 = 64	
1 x 9 = 9	2 x 9 = 18	3 x 9 = 27	4 x 9 = 36	5 x 9 = 45	6 x 9 = 54	7 x 9 = 63	8 x 9 = 72	9 x 9 = 81	

列表(数组)

列表相当于其他语言的数组

列表的创建:

- [ ]
- 内置函数 list()
list1 = ['hello','o',98,98.3]
print(list1)
list2 = list(['hello',98])
print(list2)
['hello', 'o', 98, 98.3]
['hello', 98]

列表的特点

  • 列表元素按顺序有序排列
  • 索引映射唯一一个数据
    • 正数表示正序,重0开始;负数表示倒叙,重-1开始
  • 列表可以存储重复数据,也就是列表不去重
  • 任意数据类型混存
  • 根据需要动态分配和回收内存,也就是不需要担心元素太多,列表会存不下,会根据数据的多少,动态分配内存
list1=[1,'2',3.0,'four',1]
print(list1[2],list1[-2])
3.0 four

列表元素的查询操作

  • index():获取列表指定元素的索引
    • 如果列表中存在N个相同元素,值返回相同元素中的第一个元素的索引
    • 如果查询的元素在列表中国呢不存在,则会抛出ValueError
    • 还可以在指定的start和stop之间进行查找
  • 获取列表中的单个元素
    • 正向索引0到N-1
    • 逆向索引-N到-1
    • 指定索引不存在,抛出indexError
  • 获取类别中的多个元素
    • 语法格式:列表名[start:stop:step]
    • 切片的结果:原列表片段的拷贝,一个新的类别对象
    • 切片的范围:start-stop,不包含stop
    • step步长:
      • 默认为1,简写[start,stop]
      • step为正数:从start开始往后计算切片
      • step为负数:从start开始往前计算切片
  • 判断指定元素在列表中是否存在:
    • 元素 in 列表名
    • 元素 not in 列表名
  • 列表元素遍历
      for 迭代变量 in 列表名:
       操作
l = ['a',2,'c',4,'a',2]
# index
print(l.index(2,1,5))# 不包含5
s=[10,20,30,40,50,60,70,80]
'''
10,20,30,40,50,60,70,80
 0  1  2  3  4  5  6  7  正
 -8 -7 -6 -5 -4 -3 -2 -1 负
'''
s2=s[0:7]
print(s2)# 不包含最后一个
print(id(s),id(s2))# 不同的对象
print(s[::-1])# 逆排序
'''
取数的步骤:
1-根据正负号判断取数的方向
2-根据start判断从里面开始数
s[1: : 1]的含义:从20(start=1)开始取数,因为step为正数,所以从右边取,又因为stop没写,所以sotp=最后一个元素=80(向右数)
s[1: :-1]的含义:从20开始取,因为step为付数,所以从左边取,又因为stop没写,所以sotp=最后一个元素=10(向左数)
s[7:0:-1]的含义:从80开始取,因为step为付数,所以从左边取,又因为stop=10(不包含10)
s[1:7:-1]的含义:从20开始取,因为step为付数,所以从左边取,又因为stop=60(不包含60),从左边数,数到10,就为止了,数不到60,矛盾
'''
print('s[1: : 1]=',s[1::1])# [20, 30, 40, 50, 60, 70, 80] # 包含最后一个
print('s[1: :-1]=',s[1::-1])# [20, 10]
print('s[7:0:-1]=',s[7:0:-1])# [80, 70, 60, 50, 40, 30, 20, 10]
print('s[1:7:-1]=',s[1:7:-1])# []
1
[10, 20, 30, 40, 50, 60, 70]
4425176896 4530576512
[80, 70, 60, 50, 40, 30, 20, 10]
s[1: : 1]= [20, 30, 40, 50, 60, 70, 80]
s[1: :-1]= [20, 10]
s[7:0:-1]= [80, 70, 60, 50, 40, 30, 20]
s[1:7:-1]= []

列表元素的增加操作

  • append():在列表的末尾添加一个元素,不会创建新对象
  • extend():在列表的末尾至少添加一个元素
  • insert():在列表的任意位置添加一个元素
  • 切片: 在列表的任意位置至少添加一个元素
# append
l=[1,2,3]
print(l,id(l))
l.append(4)
print(l,id(l))
# extend
l2=['a','b']
l.append(l2)
print(l,id(l))
l.extend(l2) 
print(l,id(l))
# insert
l.insert(1,'c')
print(l,id(l))
[1, 2, 3] 4530576512
[1, 2, 3, 4] 4530576512
[1, 2, 3, 4, ['a', 'b']] 4530576512
[1, 2, 3, 4, ['a', 'b'], 'a', 'b'] 4530576512
[1, 'c', 2, 3, 4, ['a', 'b'], 'a', 'b'] 4530576512
[1, 'a', 'b'] 4530576512
# 切片
l=[1,2,3]
print(l,id(l))
l2=['a','b']
'''
l[1:]=l2
相当于把l从index=1(包含)到位置处切掉:[1]
接着再拼接+['a','b']
'''
l[1:]=l2
print(l,id(l))
'''
l[1:1] 没有切蛋在index=1的位置处+[8,9]
'''
l[1:1]=[8,9]
print(l,id(l))
[1, 2, 3] 4424952768
[1, 'a', 'b'] 4424952768
[1, 8, 9, 'a', 'b'] 4424952768

列表元素的删除操作

  • remove():
    • 一次删除一个元素
    • 重复元素只删除第一个
    • 元素不存在抛出ValueError
  • pop():
    • 删除一个指定索引位置上的元素
    • 指定索引不存在抛出IndexError
    • 不指定索引,删除列表中最后一个元素
  • 切片:一次至少删除一个元素,产生一个新的列表对象
  • clear():清空列表
  • del:删除列表
# remove
l=[1,1,2,3,4,5,5]
l.remove(1)
print(l)
# pop
l.pop()
print(l)
l.pop(2)
print(l)
[1, 2, 3, 4, 5, 5]
[1, 2, 3, 4, 5]
[1, 2, 4, 5]
# 切片:产生新的对象--元素的查找
l=[1,2,3,4,5]
l2=l[0:3]
print(l,id(l))
print(l2,id(l2))
# 切片:不产生新的对象--元素的切片增加
l[3:]=[]
print(l,id(l))
[1, 2, 3, 4, 5] 4530576256
[1, 2, 3] 4530510464
[1, 2, 3] 4530576256
# clear
l=[1,2,3,4,5]
l.clear()
print(l)
del l
# print(l) # 已经没有这个对象,再打印就报错了
[]

列表元素的修改操作

  • 为指定索引的元素赋予新的值,变化的是地址值
  • 为指定的切片赋予新的值
l = [1,2,3,4]
l[0]=10
print(l)
l[1:3]=[20,30] # 把1-3(不包括3)的位置的元素替换成[20,30]
print(l)
[10, 2, 3, 4]
[10, 20, 30, 4]

列表元素的排序操作

  • sort( )
    默认元素按照从小到大进行升序排列;指定reverse=true,进行降序排列
  • sorted( )
    为内置函数。默认升序;指定reverse=true,进行降序排列
    与sort的区别:sorted会生成一个新的对象,原列表不发生任何改变
l=[3,4,2,1,6,5]
print(l,id(l))
l.sort()
print(l,id(l))
l.sort(reverse=True)
print(l,id(l))
[3, 4, 2, 1, 6, 5] 4539524736
[1, 2, 3, 4, 5, 6] 4539524736
[6, 5, 4, 3, 2, 1] 4539524736
l=[3,4,2,1,6,5]
print(l,id(l))
l2=sorted(l)
print(l2,id(l2))
l3=sorted(l,reverse=True)
print(l3,id(l3))
[3, 4, 2, 1, 6, 5] 4541143808
[1, 2, 3, 4, 5, 6] 4539489408
[6, 5, 4, 3, 2, 1] 4538265728

列表生成式

语法格式:
  list=[f(i) for i in 可迭代对象 ]
i:属于自定义变量,来自于可迭代对象里面的元素
f(i): 列表元素表达式,生成list的每一个元素,不能是赋值操作
list:生成的新的列表

l1=[i for i in range(5)]
print(l1)
a=2
l2=[a*i for i in range(5)]
print(l2)
ls=[-1,-2,-3,-4,-5,-6]
#l2=[ls[i]=i for i in range(5)]# 不能是赋值操作
l2=[ls[i] for i in range(5)]
print(l2)
l3=[2 for i in range(5)]# 可以和i无关
print(l3)
l3=[-1*i for i in ls]# 不一定要是range
print(l3)
[0, 1, 2, 3, 4]
[0, 2, 4, 6, 8]
[-1, -2, -3, -4, -5]
[2, 2, 2, 2, 2]
[1, 2, 3, 4, 5, 6]

字典

什么是字典

  • python内置的数据结构之一,与列表一样是一个可变序列
  • 以键值对的方式存储数据,字典是一个无序的序列
  • 与java中的map类似

字典的创建

  • 使用花括号{ }
  • 使用dist()
a={"张三":100,"wang":20}
print(a,type(a))
s=dict(name='jack',age=20)
print(s,type(s))
{'张三': 100, 'wang': 20} <class 'dict'>
{'name': 'jack', 'age': 20} <class 'dict'>

字典元素的获取

  • [ ]: 如果没有对应的key会报错——keyError
  • get()方法:没有key的时候不会报错,会返回None,也可以设置默认值
a={'a':1,'b':2}
print(a['a'])
#print(a['c'])#KeyError: 'c'
print(a.get('a'))
print(a.get('c'))
print(a.get('c',0))# 0 - 设置的默认值
1
1
None
0

字典元素的增删改

  • key的判断
    • in:存在为true
    • not in: 不存在为true
  • 删除 del 字典[key]
  • 清空 clear
  • 新增与修改 字典[key]=值
a={'a':1,'b':2,'c':3}
print('a'in a,'a' not in a)
del a['a']
print(a)
a.clear()
print(a)
a['d']=4
print(a)
a['d']=5
print(a)
True False
{'b': 2, 'c': 3}
{}
{'d': 4}
{'d': 5}

获取字典视图

  • keys():获取字典的所有key
  • values():获取字典的所有value
  • items(): 获取字典的所有键值对
a={'a':1,'b':2,'c':3}
keys=a.keys()
print(type(keys),keys)
print(list(keys))# 可以通过list函数把dict_keys类型转换成列表
<class 'dict_keys'> dict_keys(['a', 'b', 'c'])
['a', 'b', 'c']
a={'a':1,'b':2,'c':3}
values=a.values()
print(type(values),values)
print(list(values))# 可以通过list函数把dict_values类型转换成列表
<class 'dict_values'> dict_values([1, 2, 3])
[1, 2, 3]
a={'a':1,'b':2,'c':3}
items=a.items()
print(type(items),items)
print(list(items))# 可以通过list函数把dict_values类型转换成列表 其中( ) 称为元组
<class 'dict_items'> dict_items([('a', 1), ('b', 2), ('c', 3)])
[('a', 1), ('b', 2), ('c', 3)]

字典元素的遍历

a={'a':1,'b':2,'c':3}
for item in a: # 获取的是字典元素的key
    print(item,a[item],a.get(item))
a 1 1
b 2 2
c 3 3

字典元素的特点

  • key不允许重复,value可以重复
  • 字典只能够的元素是无序的
  • 字典中的key必须是不可变对象
  • 字典也可以根据需要动态地伸缩,不需要考虑存不了的情况
  • 字典会浪费较大的内存,是一种用空间换时间的数据结构

字典生成式

  • 内置函数zip():可以将迭代的对象打包成一个元组,然后返回由这些元组组成的列表
  • 字典生成式:{ key:value for key, value in zip(迭代对象1,迭代对象2}
    • key对应迭代对象1的元素;value对应迭代对象2的元素
items=['fruits','books','others']
price=[96,78,85]
lst1= zip(items,price)
lst2= zip(price,items)
print(lst1,type(lst1))# 返回的是一个迭代器对象,只能遍历一次
print(lst2,type(lst2))
print(list(lst1))
print(list(lst2))
print(list(lst1))# list 内部是有遍历的,上面用了一次,这次在用就为{}
<zip object at 0x10eb28dc0> <class 'zip'>
<zip object at 0x10e72ae40> <class 'zip'>
[('fruits', 96), ('books', 78), ('others', 85)]
[(96, 'fruits'), (78, 'books'), (85, 'others')]
[]
items=['fruits','books','others']
price=[96,78,85]
lst= zip(items,price)
dct={key:value+10 for key,value in lst}
print(dct)
{'fruits': 106, 'books': 88, 'others': 95}

元组

什么是元组

  • python内置的数据结构之一,是一个不可变序列
  • 不可变序列与可变序列
    • 不可变序列:没有增删改操作,如字符串和元组
    • 可变序列:对元素可以执行增删改操作,对象地址值不发生更改,如列表和字典

元组的创建

  • 使用小括号 ()
  • 使用内置函数tuple
  • 小括号也可以省略
  • 但如果元组中只有一个元素,小括号和逗号都不能省略
  • 空元组:()和tuple()
t = (10,"tt")
print(t,type(t))
d = tuple((10,"tt"))
print(d,type(d))
t2 = "t2",12,32.3
print(t2,type(t2))
#t3 = tuple("t3",20) # 这个不行
#print(t3,type(t3))
t4 = ("t4")
print(t4,type(t4))# 被认为是字符串
t5 = ("t5",)
print(t5,type(t5))
t6=()
print(t6,type(t6))
t7=tuple()
print(t7,type(t7))
(10, 'tt') <class 'tuple'>
(10, 'tt') <class 'tuple'>
('t2', 12, 32.3) <class 'tuple'>
t4 <class 'str'>
('t5',) <class 'tuple'>
() <class 'tuple'>
() <class 'tuple'>

为什么要将元组设计成不可变序列

  • 一旦创建不可变序列,数据就不可修改,避免因修改数据而造成错误
  • 在多任务多的环境下,同时操作对象时就不需要加锁

元组中存储的是对象的引用

所以在元组中,不变的是对象的引用。但是我们可以改变改引用多指向的值。

t = (1,[2,3],4)
print(t,type(t[1]),id(t[1]))
#t(0) = 5# 会报错
t[1].append(5)
print(t,type(t[1]),id(t[1]))
t[1][0]=6
print(t,type(t[1]),id(t[1]))
(1, [2, 3], 4) <class 'list'> 4541580672
(1, [2, 3, 5], 4) <class 'list'> 4541580672
(1, [6, 3, 5], 4) <class 'list'> 4541580672

元组的遍历

t = (1,[2,3],4)
for item in t:
    print(item,end="-->")
1-->[2, 3]-->4-->

集合

什么是集合

  • 是python的内置数据结构
  • 可变序列
  • 集合是没有value的字典
  • 特点:去重于无序

集合的创建方式

  • {}
  • set()
    • 把序列range转为集合
    • 把列表转为集合
    • 把元组转为集合
    • 把字符串序列转为集合
    • 把集合转成新的集合
  • 空集合:只能使用set(),使用{}得到的是一个字典
s = {1,1,2,3,4,5,5}# 不允许重复
print(s)
s2=set(range(6))
print(s2,type(s2))
l=[1,2,2,3,3]
s3=set(l)
print("l=",l)
print("s3=",s3)# 去重
t=(56,45,9,100)
print(t)
print(set(t))# 集合是无序的
print(set("python"))# 集合是无序的
print(set(set("python")))
{1, 2, 3, 4, 5}
{0, 1, 2, 3, 4, 5} <class 'set'>
l= [1, 2, 2, 3, 3]
s3= {1, 2, 3}
(56, 45, 9, 100)
{56, 9, 100, 45}
{'t', 'n', 'h', 'p', 'o', 'y'}
{'t', 'n', 'h', 'p', 'o', 'y'}
s={}
print(s,type(s))
s2 = set()
print(s2,type(s2))
{} <class 'dict'>
set() <class 'set'>

集合的相关操作

判断操作:in或not in

新增操作

  • add:一次添加一个元素
  • update:至少添加一个元素

修改操作

  • remove:一次删一个指定元素,如果指定元素不存在,抛keyerro
  • discard:一次删一个指定元素,如果指定元素不存在,不抛异常
  • pop:一次删除任意一个元素,无参
  • clear:清空集合
s = {"1",1,3,4}
print(s)
s.add("t")
print(s)
s.update({5,6})# 集合
s.update([7,8])# 列表
s.update((9,10))# 元组
print(s)
s.remove(1)
s.discard(1)
print(s)
s.pop()
print(s)
s.clear()
print(s)
{'1', 3, 4, 1}
{'1', 1, 3, 4, 't'}
{'1', 1, 3, 4, 5, 6, 7, 8, 9, 10, 't'}
{'1', 3, 4, 5, 6, 7, 8, 9, 10, 't'}
{3, 4, 5, 6, 7, 8, 9, 10, 't'}
set()

集合间的关系

  • 两个集合是否相等:==/!=(判断元素是否相等)
  • 一个集合是否是另一个集合的子集:issubset
    • A.issubset(B):A是B的子集么?A包含于B么?
  • 一个集合是否是另外一个集合的超集:issuperset
    • A.issuperset(B):A是B的超集么?A包含B么?
  • 两个集合是否有交集:isdisjoint- 是否没有交集
s1={1,2,3}
s2={1,2,3,4}
s3={4,5,6}
print(s1==s2)
print(s1!=s2)
print(s1.issubset(s2))
print(s2.issuperset(s1))
print(s2.isdisjoint(s1))# false - 有交集
print(s2.isdisjoint(s3))# false - 有交集
False
True
True
True
False
False

集合的数据操作

  • 交集操作:intersection和&
  • 并集操作:union和|
  • 差集操作:difference和-
  • 对称差集操作:symmetry_difference和^
s1 = {1,2,3}
s2 = {2,3,4}
si1=s1.intersection(s2)
si2=s1&s2
print("交集:",si1,si2)
su1=s1.union(s2)
su2=s1|s2
print("并集",su1,su2)
sd1=s1.difference(s2)
sd2=s1-s2
print("s1-s2的差集:",sd1,sd2)
ssd1=s1.symmetric_difference(s2)
ssd2=s1^s2
print("s1和s2的对称差集:",ssd1,ssd2)
交集: {2, 3} {2, 3}
并集 {1, 2, 3, 4} {1, 2, 3, 4}
s1-s2的差集: {1} {1}
s1和s2的对称差集: {1, 4} {1, 4}

集合生成式

# 列表生成式
ls=[i*i for i in range(10)]
print(ls)
# 集合生成式
st={i*i for i in range(10)}
print(st)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}

列表、字典、元组、结合总结


数据结构 是否可变 是否重复 是否有序 定义符号
列表list 可变 可重复 有序 [  ]
字典dist 可变 key不可重复
value可重复
无序 {key:value}
元组tuple 不可变 可重复 有序 (  )
集合set 可变 不可重复 无序 {  }

字符串

字符串的驻留机制

  • 字符串是python的基本数据类型,是一个不可变的字符序列
  • 什么叫字符串驻留机制
    仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同的字符串时,不会开辟新的内存空间,而是把该字符串的地址赋给新创建的变量
  • 驻留机制的几种情况
    • 字符串的长度为1或0时
    • 字符串符合标识符的规则:数字、字母、下划线
    • 字符串只在编译时驻留,而非运行时
    • [-5,256]之间的整数数字
  • sys中的intern方法强制2个字符串指向同一个对象
  • PyCharm对字符串进行了优化处理
  • 字符串驻留机制的优缺点
    • 当需要值相同的字符串时,可以之间从字符串池中拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串时会比较影响性能。
    • 在需要进行字符串拼接时建议使用str类型的join方法,而非+,首先字符串为不可变序列,每一个新的字符串都会生成一个新的对象。
      a+b+c:a+b生成一个对象,接着+c又生成一个对象
      而””.join(a,b,c)会计算出所有字符的长度,然后在拷贝,只new一次对象,效率比+要高
a = 'abc'
b = "abc"
c = '''abc'''
print(id(a))
print(id(b))
print(id(c))
4384582768
4384582768
4384582768
# 字符串的长度为1或0时
a=''
b=''
print(a is b)
c='w'
d='w'
print(c is d)
True
True
# 字符串符合标识符的规则
a='1_a'
b='1_a'
print(a is b)
c='1_a%'
d='1_a%'
print(c is d)
True
False
# 字符串只在编译时驻留,而非运行时
a = 'abc'
b = 'a'+'bc'
c = 'a'
d =c.join('bc')
print(a,id(a))
print(b,id(b))
print(c,id(c))# id不同
print(d,id(d))# id不同
abc 4384582768
abc 4384582768
a 4384821936
bac 4538639984
import sys
a = 'abc%'
b = 'abc%'
print(a is b)
c = sys.intern(a)# 把a的地址给c
print(a is c)
False
True

字符串的常用操作

查询操作

  • index:找到字串中第一次出现的位置,从前面开始找,找不到valueError,返回int
  • rindex:找到字串中最后一次出现的位置,从后面开始找,找不到valueError,返回int
  • find:找到字串中第一次出现的位置,从前面开始找,找不到不报错,返回int,找不到返回-1
  • rfind:找到字串中最后一次出现的位置,从后面开始找,找不到不报错,返回int,找不到返回-1
'''
p y t h o n , p y t  h o  n
0 1 2 3 4 5 6 7 8 9 10 11 12
'''
str='python,python'
a=str.index("on")
print(a,type(a))
b=str.rindex("on")
print(b,type(b))
#a=str.index("onn")#ValueError: substring not found
#a=str.rindex("onn")#ValueError: substring not found
c=str.find("on")
print(c,type(c))
d=str.find("onn")
print(d,type(d))
e=str.rfind("on")
print(e,type(e))
e=str.rfind("onn")
print(e,type(e))
4 <class 'int'>
11 <class 'int'>
4 <class 'int'>
-1 <class 'int'>
11 <class 'int'>
-1 <class 'int'>

字符串的大小写转换操作

  • upper:把字符串中所有字符转成大写
  • lower:把字符串中所有字符转成小写
  • swapcase:大写转小写,小写转大写
  • capitalize:第一个字符串大写,后面小写
  • title:每个单词的首字母大写,其余的字符串为小写
str = 'heLLo,woRLD'
a=str.upper()
print(a,type(a))
b=str.lower()
print(b,type(b))
c=str.swapcase()
print(c,type(c))
d=str.capitalize()
print(d,type(d))
e=str.title()
print(e,type(e))
HELLO,WORLD <class 'str'>
hello,world <class 'str'>
HEllO,WOrld <class 'str'>
Hello,world <class 'str'>
Hello,World <class 'str'>

字符串内容对齐操作

  • center:
    • 居中对齐
    • 第1个参数:指定宽度
    • 第2个参数:指定填充,可选,默认为空格
    • 如果设置宽度小于实际宽度,返回原字符串
  • ljust:
    • 左对齐
    • 第1个参数:指定宽度
    • 第2个参数:指定填充,可选,默认为空格
    • 如果设置宽度小于实际宽度,返回原字符串
  • rjust:
    • 右对齐
    • 第1个参数:指定宽度
    • 第2个参数:指定填充,可选,默认为空格
    • 如果设置宽度小于实际宽度,返回原字符串
  • zfill:
    • 右对齐
    • 左边用0填充
    • 只接受一个参数,用于指定字符串的宽度
    • 如果设置宽度小于实际宽度,返回原字符串
str='hello'
a=str.center(10)
print(a,type(a))
a=str.center(10,'*')
print(a,type(a))
b=str.ljust(10,'*')
print(b,type(b))
c=str.rjust(10,'*')
print(c,type(c))
d=str.zfill(10)
print(d,type(d))
  hello    <class 'str'>
**hello*** <class 'str'>
hello***** <class 'str'>
*****hello <class 'str'>
00000hello <class 'str'>

字符串劈分操作

  • split:
    • 从字符串的左边开始劈分,默认的劈分字符是空字符串,返回的值都是一个列表
    • 以通过参数sep指定劈分字符串的劈分符
    • maxsplit指定字符串时的最大劈分次数,在经过最大劈分之后,剩余的字串会单独作为一部分
  • rsplit:
    • 从字符串的右边开始劈分,默认的劈分字符串是空哥字符串,返回的值都是一个列表
    • 以通过参数sep指定劈分字符串的劈分符
    • maxsplit指定字符串时的最大劈分次数,在经过最大劈分之后,剩余的字串会单独作为一部分
str='h-e-l-l-o'
ls=str.split("-")#默认sep
print(ls,type(ls))
ls=str.split(sep="-")
print(ls,type(ls))
ls=str.split("-",maxsplit=3)# 切3次
print(ls,type(ls))
['h', 'e', 'l', 'l', 'o'] <class 'list'>
['h', 'e', 'l', 'l', 'o'] <class 'list'>
['h', 'e', 'l', 'l-o'] <class 'list'>

判断字符串操作的方法

  • isidentifier:判断是不是合法标识符
    • 标识符有字母、数字、下划线组成。
    • 所有标识符可以包括英文、数字以及下划线(_),但不能以数字开头。
    • 以下划线开头的标识符是有特殊意义的。以单下划线开头(_foo)的代表不能直接访问的类属性,需通 过类提供的接口进行访问,不能用”from xxx import *”而导入;
    • 以双下划线开头的(__foo)代表类的私有成员;以双下划线开头和结尾的(__foo__)代表python里 特殊方法专用的标识,如__init__()代表类的构造函数。
  • isspace:判断字符串是否全部由空白字符组成:回车、换行、水平制表符,有就为False,没有就为True
  • isalpha:判断字符串是否全部由字母字串
  • isdecimal:判断指定字符串是否全部由十进制的数字组成
  • isnumeric:判断指定的字符串是否全部由数字组成
  • isalnum:判断指定字符串是否由字母和数字组成
print("1_x","1_x".isidentifier())
print("张三","张三".isidentifier())# 汉字也可以为标识符
print("a%","a%".isidentifier())
print("\t","\t".isspace())# True
print("a\t","a\t".isspace())# False,不是全部由空字符串组成
print("aSDb","aSDb".isalpha())
print("aSDb!","aSDb!".isalpha())
print("100","100".isdecimal())
print("001","001".isdecimal())# 001-也是true
print("00四","00四".isdecimal())# False 
print("00四","00四".isnumeric())# True
print("ab12","ab12".isalnum())# True
print("ab12章","ab12章".isalnum())# True
print("ab12!","ab12!".isalnum())# False
1_x False
张三 True
a% False
     True
a	 False
aSDb True
aSDb! False
100 True
001 True
00四 False
00四 True
ab12 True
ab12章 True
ab12! False

字符串的操作的其他方法

  • replace:
    • 第1个参数:被替换的字串
    • 第2个参数:指定替换字串的字符串
    • 第3个参数:最大替换次数
    • 返回:替换后得到的字符串
  • join:将列表或元组的字符串合并成一个字符串
str="helloll"
s=str.replace("l","z")
print(s)
s=str.replace("l","z",3)
print(s)
ls=['1','sd','cd']
s=''.join(ls)
print(s)
s='-'.join(ls)# 链接
print(s)
# 必须要全为字符串,否则会报错
#tp=("a",2,"c")#TypeError: sequence item 1: expected str instance, int found
tp=("a","2","c")
t='-'.join(tp)
print(t)
hezzozz
hezzozl
1sdcd
1-sd-cd
a-2-c

字符串的比较操作

  • 运算符:>,>=,<,<=,==,!=
  • 比较规则:一个一个字符串进行比较
  • 比较原理:比较的oridnal value(原始值),即Unicode值,其中Unicode的前128位数ASCII码
  • 调用内置函数ord可以得到指定字符的ordinal value
  • 调用内置函数chr时指定ordinal value 可以得到其对应的字符
print("apple">"app")
print("apple"<="app")
print("apple"!="app")
# 获取原始值
print(ord("a"),ord('b'))
print(ord("章"),ord('张'))
# == 比较的是value;is比较的是id
a=b='app'
c='app'
print(a==c,a is c)# True True 都相等时因为字符串的驻留机制
True
False
True
97 98
31456 24352
True True

字符串的切片操作

  • s[:5]:从头开始到5结束,不包含5
  • s[6:]:从6开始到尾结束,包含6
  • s[:5:-1]:负数的开头是最右边,从最右边开始,到index=5的地方结束,不包含5
  • s[6::-1]:负数的结束是最左边,从index=6的地方开始(包含6)直到结束
  • s[:-5:-1]:负数的开头是最右边,从最右边开始,到index=-5的地方结束,不包含5
  • s[-6::-1]:负数的结束是最左边,从index=-6的地方开始(包含6)直到结束
#    -9 -8 -7 -6 -5 -4 -3 -2 -1
#.   零 一 二  三 四 五  六 七 八
str='零一二三四五六七八'
a=str[:5]
b=str[6:]
print(a)
print(b)
print('------------------')
c=str[:5:-1]
d=str[6::-1]
print(c)
print(d)
print('------------------')
e=str[:-5:-1]
f=str[-6::-1]
print(e)
print(f)
零一二三四
六七八
------------------
八七六
六五四三二一零
------------------
八七六五
三二一零

格式化字符串

  • %作占位符:
    • %s:字符串
    • %i或%d:整数
    • %f:浮点数
    • 参数值是依次对应的
  • {}作占位符:
    • {num}:num是第几个参数,从0开始
    • {pramName}+f:pramName:变量参数名,f是固定格式
  • 宽度和精确度
    • %
      • %10d:表示宽度是10
      • %.3f:表示精度是小数点后3位
      • %10.3f:表示宽度为10,精度是小数点后3位
    • {}
      • {0:.3}:表示一共是3位数,四舍五入
      • {0:.3f}:表示保留小数点3,四舍五入
      • {0:10.3f}:宽度为10,保留小数点3,四舍五入
str1="我叫%s,今年%d岁,高考考了%f分"
# 这里的 % 是固定符号
print(str1%("张三",20,675.5))
str2="我叫{1},今年{0}岁,高考考了{2}分"
print(str2.format(20,'张三',675.5))
# f-固定格式
str3=f"我叫{name},今年{age}岁,高考考了{score}分"
name='张三'
age=20
score=675.5
print(str3.format(age,name,score))
我叫张三,今年20岁,高考考了675.500000分
我叫张三,今年20岁,高考考了675.5分
我叫张三,今年20岁,高考考了675.5分
print('----------')
print('%10d'%10)
print('%10s'%"ni")
print('%10.3f'%675.55555)#会四舍五入
print('%10.3d'%10)#不够补0
print('%10.3s'%"ni")#精度不起作用
----------
        10
        ni
   675.556
       010
        ni
print('----------')
print('{0:.3}'.format(7.4566))
#ValueError: Precision not allowed in integer format specifier
#print('{0:.3}'.format(7585))整数不能用.3的格式
#print('{0:.3}'.format(56))
print('{0:.3}'.format(7451.4566))#7.45e+03=7450:整数位数>=3会用科学记数法
print('{:.3f}'.format(7.4566))#一个参数,0可以省略
print('{:10.3f}'.format(7.4566))
----------
7.46
7.45e+03
7.457
     7.457

字符串的编码转换

  • 为什么需要字符串的编码转换:计算机之间是通过byte字节传输
  • 编码与解码:
    • 编码:字符串转换为二进制数据(bytes)—— encode
    • 解码:将bytes类型的数据转换为字符串类型 —— decode
s="天涯共此时"
# 用GBK编码
a=s.encode(encoding='GBK')
print(a,type(a))
b=a.decode(encoding='GBK')
print(b,type(b))
#使用不同的格式去解码会报错
#c=a.decode(encoding='UTF-8')#UnicodeDecodeError
b'\xcc\xec\xd1\xc4\xb9\xb2\xb4\xcb\xca\xb1' <class 'bytes'>
天涯共此时 <class 'str'>

函数

函数的创建:

def 函数名(参数):  
    函数体
    「return xxx」
def sub(a,b):
    c=a-b;
    return c
res=sub(10,1)
print(res)
9

函数的参数传递

  • 位置实参:根据参数的位置进行实参传递
  • 关键字实参:根据形参名称进行实参传递
def sub(a,b):
    c=a-b;
    return c
res=sub(b=10,a=1)
print(res)
-9

函数调用的参数传递内存分析:传递的是地址值

def fun(arg1,arg2):
    print('----------------------------------')
    print('arg1=',arg1,'id(arg1)=',id(arg1));
    print('arg2=',arg2,'id(arg2)=',id(arg2));
    arg1=100;
    arg2.append(100)
    print('arg1=',arg1,'id(arg1)=',id(arg1));
    print('arg2=',arg2,'id(arg2)=',id(arg2));
    print('----------------------------------')

a=10
b=[10,20]
print('a=',a,'id(a)=',id(a));
print('b=',b,'id(b)=',id(b));
fun(a,b)
print('a=',a,'id(a)=',id(a));
print('b=',b,'id(b)=',id(b));
a= 10 id(a)= 4382432272
b= [10, 20] id(b)= 4546440192
----------------------------------
arg1= 10 id(arg1)= 4382432272
arg2= [10, 20] id(arg2)= 4546440192
arg1= 100 id(arg1)= 4382435152
arg2= [10, 20, 100] id(arg2)= 4546440192
----------------------------------
a= 10 id(a)= 4382432272
b= [10, 20, 100] id(b)= 4546440192

fun之前:
  a的地址值:2272->10;
  b的地址值:0192->[10, 20];
调用fun,传入的是地址值
  arg1=a->2272
  arg2=b->0192
arg1=100:
  100在是一个新的内存空间,arg1这个变量等于是换了一个地址:5152
arg2.append(100):
  这个操作操作的仍是0192这个内存空间的数据
调用之后:
  a= 10:因为fuc这个函数没有对2272这个内存空间的数据进行任何操作,所以不变
  b= [10, 20, 100]:因为arg2.append(100)对0192这个内存的数据进行了操作,所以变了

函数的返回值

  • 如果函数没有返回值,retrun可以省略不写
  • 可以直接使用return结束方法
  • 返回一个参数时,返回的是该返回值类型
  • 返回多个值时,结构为元组
# 原例子中这里写的是num,我一开始以为是填一个数,但往后看代码才发现应该填一个list
# 这反映了弱类型语言的劣势,如果参数名字不见名知意,我就不知道要传什么类型的参数
def fun(numList):
    odd=[]#存奇数
    even=[]#存偶数
    for i in numList:
        if i%2:#i%2==0 0和True可以相互转换,C的特点
            even.append(i)
        else:
            odd.append(i)
    return odd,even
num=[10,23,24,4,12,33,3]
res=fun(num)
print(res,type(res))
([10, 24, 4, 12], [23, 33, 3]) <class 'tuple'>

函数的参数定义

  • 默认值参数:print的end的参数的默认值为:\t
  • 个数可变的位置参数:
    • 定义函数时,可能无法事先确定传递的位置参数的个数,这时可以使用可变的位置参数
    • 使用*定义个数可变的位置参数
    • 结果为一个元组
    • 只能有一个可变位置参数
  • 个数可变的关键字形参
    • 定义函数时,无法事先确定传递的关键字实参的个数,这时可以使用可变的关键字形参
    • 使用**丁个数可变的关键字形参
    • 结果为一个字典
    • 只能有一个可变关键字参数
  • 实参与形参
    • 在函数定义时,定义的是形参
    • 在函数调用时,传入的是实参
  • 函数调用时使用*:把序列中的每一个元素转换为位置实参
  • 函数调用时使用**:把字典中的每一个键值对转换为关键字实参
  • def fun(a,b,,c,d):表示之后的参数只能采用关键字传参
# 默认值设置
def fun(a,b=0):
    print(a,b)

fun(10)
fun(11,12)
10 0
11 12
#个数可变的位置参数
#def fun(*args,*a):过不了编译
def fun(*args):
    print(args,type(args))
fun(10)
fun(10,'ab',12)
print('---------------------')
# 可变位置参数+另一个形参时,需要使用关键字传参,否则会报错
# TypeError: fun() missing 1 required keyword-only argument: 'a'
def fun1(*args,a):
    print(args,type(args),'a=',a)
fun1(10,a=0)
fun1(10,'ab',12,a=0)
(10,) <class 'tuple'>
(10, 'ab', 12) <class 'tuple'>
---------------------
(10,) <class 'tuple'> a= 0
(10, 'ab', 12) <class 'tuple'> a= 0
# 个数可变的关键字形参
#def fun(**args,**a):过不了编译
def fun(**args):
    print(args,type(args))
# 必须使用关键字穿参,否则报错
# TypeError: fun() takes 0 positional arguments but 3 were given
# fun(10,20,30)
fun(a=10,b=20,c=30)
# 不能这么定义:def fun2(**args,a),否则会报语法错误
def fun2(a,**args):
    print(args,type(args),'a=',a)
#fun2(d=10,b=20,c=30)必须传入a,否则会报错:
#TypeError: fun2() missing 1 required positional argument: 'a'
fun2(a=10,b=20,c=30)
{'a': 10, 'b': 20, 'c': 30} <class 'dict'>
{'b': 20, 'c': 30} <class 'dict'> a= 10
# 可变位置参数+可变关键字参数
#def fun(**args,*arg):没有这种形式
def fun(*args1,**args2):
    print(args1,type(args1))
    print(args2,type(args2))
    print('------------------------')

fun()
fun(10,11)
fun(a=10,b=11)
# fun(10,a=20,30,b=40)SyntaxError: positional argument follows keyword argument
fun(10,20,a=30,b=40)
# 如果位置参数和关键字参数都要传,位置参数必须在前面
# fun(a=1,b=2,"s","b")SyntaxError: positional argument follows keyword argument
fun("s","b",a=1,b=2)
() <class 'tuple'>
{} <class 'dict'>
------------------------
(10, 11) <class 'tuple'>
{} <class 'dict'>
------------------------
() <class 'tuple'>
{'a': 10, 'b': 11} <class 'dict'>
------------------------
(10, 20) <class 'tuple'>
{'a': 30, 'b': 40} <class 'dict'>
------------------------
('s', 'b') <class 'tuple'>
{'a': 1, 'b': 2} <class 'dict'>
------------------------
# 多个位置实参
def fun(a,b,c):
    print(a,b,c)
fun(1,2,3)
ls=[1,2,3]
fun(*ls)
print('---------')
def fun2(*arg):
    print(arg)
fun2(ls)#([1, 2, 3],) 把ls作为一个参数
fun2(*ls)
'''
少了会报错:TypeError: fun() missing 1 required positional argument: 'c'
ls2=[1,2]
fun(*ls2)
'''
print('---------')
1 2 3
1 2 3
---------
([1, 2, 3],)
(1, 2, 3)
---------
# 多个关键字传参
def fun(a,b,c):
    print(a,b,c)
    print('---------')
fun(a=1,b=2,c=3)
dis={"a":1,'b':2,'c':3}
fun(**dis)
1 2 3
---------
1 2 3
---------
# 指定关键字传参
def fun(a,b,*,c,d):
    print(a,b,c,d)
#fun(10,20,30,40)#TypeError: fun() takes 2 positional arguments but 4 were given
fun(10,20,c='a',d='c')
10 20 a c

变量的作用域

  • 局部变量:函数内定义的
  • 全局变量:
    • 函数外定义的
    • global修饰的
a=1;
def fun (param):
    b=10
    global d
    d=20
    c=param+a# 全局变量可以在函数内使用
    return c
#TypeError: unsupported operand type(s) for +: 'int' and 'list'
'''b是局部变量,不能在函数外用'''
#res=fun(5)+b
res=fun(5)+d# d是全局变量,可以拿出来用
print(res)
26

递归函数

  • 什么是递归:函数自己调自己
  • 递归的组成部分:递归的调用与递归的终止条件
  • 递归的调用过程:
    • 每递归调用一次函数,都会在栈内存分配一个栈帧
    • 每执行完一次函数,都会释放相应的空间
  • 递归的优缺点:
    • 缺点:占用内存多,效率低下
    • 优点:思路和代码简单
# 阶乘
def fun(n):
    if(n==1):
        return 1
    return fun(n-1)*n

print(fun(5))
120
# 斐波那契数列
# 1,1,2,3,5,8...
# a1=1;a2=1 f(n)=f(n-1)+f(n-2)
def fun(n):
    if(n==1 or n==2):
        return 1
    return fun(n-1)+fun(n-2)
    
print(fun(6))
8

异常

异常的处理机制

  • try-except
  • try-except-except-…-except
    • 捕获顺序:先子类后父类(由小到大)
    • BaseException 数最大的异常
  • try-except-else
    • 没遇到异常就执行else
  • try-except-else-finally
    • finally:无论是否遇到异常都会执行

python常见的异常类型

  • ZeroDivisionError:除(或取模)零
  • IndexError:序列中没有此索引
  • KeyError:映射中没有这个键
  • NameError:未声明/初始化对象(没有属性)
  • SyntaxError:语法错误
  • ValueError:传入无效参数

traceback模块

使用traceback模块打印异常信息
# try-except
try:
    n1=int(input("请输入第一个数:"))
    n2=int(input("请输入第二个数:"))
    res=n1/n2
    print('结果为:{0:0.2}'.format(res))
except ZeroDivisionError:
    print("除数不能为0")
print("程序结束")
请输入第一个数:1
请输入第二个数:0
除数不能为0
程序结束
# try-except-except-...-except
try:
    n1=int(input("请输入第一个数:"))
    n2=int(input("请输入第二个数:"))
    res=n1/n2
    print('结果为:{0:0.2}'.format(res))
except ZeroDivisionError:
    print("除数不能为0")
except ValueError:
    print("您输入的不是数字")
except BaseException as e:# BaseException
    print(e)
print("程序结束")
请输入第一个数:-
您输入的不是数字
程序结束
# try-except-else
try:
    n1=int(input("请输入第一个数:"))
    n2=int(input("请输入第二个数:"))
    res=n1/n2
except ZeroDivisionError:
    print("除数不能为0")
except ValueError:
    print("您输入的不是数字")
except BaseException as e:# BaseException
    print(e)
else:
    print('结果为:{0:0.2}'.format(res))
print("程序结束")
请输入第一个数:1
请输入第二个数:2
结果为:0.5
程序结束
# try-except-else-finally
try:
    n1=int(input("请输入第一个数:"))
    n2=int(input("请输入第二个数:"))
    res=n1/n2
except ZeroDivisionError:
    print("除数不能为0")
except ValueError:
    print("您输入的不是数字")
except BaseException as e:# BaseException
    print(e)
else:
    print('结果为:{0:0.2}'.format(res))
finally:
    print("程序结束")
请输入第一个数:-
您输入的不是数字
程序结束
import traceback
try:
    print('-----1-------')
    num=1/0
except: # 不写,发生异常就直接走这段代码
    traceback.print_exc()
-----1-------


Traceback (most recent call last):
  File "/var/folders/06/0p7d3_4x4xsgmjl7lb00hvg80000gn/T/ipykernel_3338/1999639933.py", line 4, in <module>
    num=1/0
ZeroDivisionError: division by zero

对象

两大编程思想

  • 面向过程
  • 面向对象

类和对象的创建

数据类型与对象:

不同的数据类型属于不同的类。如100、99、520都是int类的不同实例,即对象
像int、list、dict等都是类,其具体的value就是一个个实例

类的创建

  • 创建语法:
      class Student:
        属性/方法等
  • 类的组成:
    • 类属性
    • 实例方法
    • 静态方法:@staticmethod
    • 类方法:@classmethod
    • 初始化方法:_ init _

对象的创建

  • 对象的创建又称类的实例化
  • 语法:实例名=类名()
# 创建类
class Student:
    pass
'''
    当我们定义Student类的时候,也会在内存中开辟空间,Student是一个类对象
'''
print(id(Student))
print(type(Student))
print(Student)
140205459718400
<class 'type'>
<class '__main__.Student'>
'''-------------------------------------类的定义-----------------------------------------'''
class Student:
    #类属性
    native_place='深圳'# 类里面定义的变量称为类属性
    
    #初始化方法:用于初始化对象,类似java的构造器
    def __init__(self,name,age):
        '''
        self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
        这里也可以是self.a=name,但是这样就不见名知意了
        '''
        self.name=name 
        self.age=age
    
    # 实例方法,定义在类之后的称为函数
    def eat(self):#只是习惯用self,写a也可以
        print('学生吃饭')
        
    #静态方法
    @staticmethod
    def smethod(): 
        print("----静态方法-----")
    
    #类方法
    @classmethod
    def claMethod(cls):#同self
        print('----类方法-------')
'''----------------------------------------对象的创建和使用-----------------------------'''
# 创建对象
print('----------实例对象------------')
jack=Student('jack',20)
print(jack)
print(id(jack))# 地址值:十进制-4547494336  十六进制-0x10f0d41c0
print(type(jack))
print('----------类对象------------')
print(Student)
print(id(Student))
print(type(Student))
print('----------访问实例属性------------')
print(jack.name)#对象名.实例属性名
print(jack.age)
print('----------调用实例方法------------')
jack.eat()# 对象名.方法名
Student.eat(jack)# 类名.方法名(类的实例)-->实际上就是方法定义处的self
----------实例对象------------
<__main__.Student object at 0x10ee4f730>
4544853808
<class '__main__.Student'>
----------类对象------------
<class '__main__.Student'>
140205437441424
<class 'type'>
----------访问实例属性------------
jack
20
----------调用实例方法------------
学生吃饭
学生吃饭

类对象和类属性

类属性-类方法-静态方法的使用

  • 类属性的访问:实例对象公用一个类属性
    • 实例对象名.类属性名
    • 类名.实类属性名
  • 类方法:类名.类方法名
  • 静态方法:类名.静态方法
class Student:
    #类属性
    native_place='深圳'# 类里面定义的变量称为类属性
    
    #初始化方法:用于初始化对象,类似java的构造器
    def __init__(self,name,age):
        '''
        self.name称为实例属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
        这里也可以是self.a=name,但是这样就不见名知意了
        '''
        self.name=name 
        self.age=age
    
    # 实例方法,定义在类之后的称为函数
    def eat(self):#只是习惯用self,写a也可以
        print('学生吃饭')
        
    #静态方法
    @staticmethod
    def smethod(): 
        print("----静态方法-----")
    
    #类方法
    @classmethod
    def claMethod(cls):#同self
        print('----类方法-------')
'''-------------------------------类对象-类属性-静态方法-----------------------------'''
print('--------类属性的使用---------')
print(Student.native_place)
stu1=Student('张三',20)
stu2=Student('李四',23)
print(stu1.native_place)
print(stu2.native_place)
Student.native_place='广州'
print(stu1.native_place)
print(stu2.native_place)
'''
stu1和sut2共用native_place这个类属性
但是stu1.native_place='南昌'这个操作,相当于往stu1这个实例对象里面动态绑定了一个native_place的实例属性
于是stu1.native_place优先会访问实例对象的native_place属性
'''
stu1.native_place='南昌'
print(stu1.native_place)# 只改了stu1的值
print(stu2.native_place)
Student.native_place='北京'
print(stu1.native_place)# stu1回不去了
print(stu2.native_place)
print('--------类方法的使用---------')
Student.claMethod()#类方法有默认参数
print('--------静态方法的使用---------')
Student.smethod()#静态方法没有默认参数
--------类属性的使用---------
深圳
深圳
深圳
广州
广州
南昌
广州
南昌
北京
--------类方法的使用---------
----类方法-------
--------静态方法的使用---------
----静态方法-----

类属性的内存分析
类属性

动态绑定属性和方法

动态绑定属性和方法的内存分析图
动态绑定

# 绑定动态
stu1=Student('李四',30)
stu2=Student('张三',20)
#绑定属性
stu1.gender='女'
print(stu1.name,stu1.age,stu1.gender)
#stu2没有gender属性,访问了会报错
#AttributeError: 'Student' object has no attribute 'gender'
#print(stu2.name,stu2.age,stu2.gender)
def show():
    print('-----show-----')
#绑定方法
stu1.show=show
stu1.show()
#stu2没有show方法,调用会报错
#AttributeError: 'Student' object has no attribute 'show'
#stu2.show()
李四 30 女
-----show-----

对象的三大特性之封装

  • 设置私有属性:属性两边使用‘__‘
  • 但私有属性还是可以访问的,python的封装完全是靠程序员的自觉
class Student:
    def __init__(self,name,age):
        self.name=name
        self.__age=age#age不希望在类的外部被使用,所以加了两个_
    def show(self):
        print(self.name,self.__age)
    
stu=Student('jerry',20)
stu.show()
print(stu.name)
#直接访问__age会报错
#AttributeError: 'Student' object has no attribute '__age'
#print(stu.__age)
print('stu的属性和方法有:',dir(stu))
# stu里面有'name', 'show'还有一个'_Student__age',通过这个可以去访问
print(stu._Student__age)
jerry 20
jerry
stu的属性和方法有: ['_Student__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'show']
20

对象的三大特性之继承

  • class 子类(要继承的父类):
  • 如果一个类没有继承任何类,则默认继承object,即所有类都继承了object
  • python支持多继承:class 子类(父类1,父类2)
  • 定义子类时,必须在其构造函数中调用父类的构造函数
  • 子类可以使用父类的属性和方法

方法重写

  • 如果子类对继承自父类的某个属性或方法不满意,可以在其子类中对其(方法体)进行重新编写
  • 子类重写后的方法中可以通过super().xxx()调用父类中的方法
class Person(object):#不写object也可以
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def info(self):
        print(self.name,self.age)
    def eat(self):
        print('----eat-----')
class Student(Person):
    def __init__(self,name,age,stu_no):
        # 这个super()应该类似于java的super,返回的是父类的实例对象
        super().__init__(name,age)
        self.stu_no=stu_no
    #重写父类方法
    def info(self):
        #再使用父类的info方法
        super().info()
        print(self.stu_no)
class Teacher(Person):
    def __init__(self,name,age,teach_year):
        # 这个super()应该类似于java的super,返回的是父类的实例对象
        super().__init__(name,age)
        self.teach_year=teach_year
        #重写父类方法
    def info(self):
        #再使用父类的info方法
        super().info()
        print(self.teach_year)
#这样就是多继承
class A (Student,Teacher):
    pass

stu=Student('张三',20,'1001')
tec=Teacher('李四',34,10)
stu.info()#调用重写的方法
tec.info()#调用重写的方法
stu.eat()#可以使用父类的方法
tec.eat()#可以使用父类的方法
张三 20
1001
李四 34
10
----eat-----
----eat-----

object类

  • object类是所有类的父类,因此所有类都有object的属性和方法
  • 内置函数dir()可以查看知道对象所有属性
  • Object有一个__str__()方法,用于返回“对象的描述”(类似java的toString)
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):
        return '我的名字是{0},今年{1}岁'.format(self.name,self.age)
stu=Student('jerry',20)
'''
没有重写object的__str__方法前:
    print(stu)输出的是:<__main__.Student object at 0x10a88af40>
重写object的__str__方法后:
    print(stu)输出的是:我的名字是jerry,今年20岁
'''
print(stu)
'''
print(stu)方法内部调用了stu的__str__()方法
'''
st=stu.__str__()
print(st,type(st))
我的名字是jerry,今年20岁
我的名字是jerry,今年20岁 <class 'str'>

对象的三大特性之多态

  • 在java中的多态是这样的:父类的引用指向子类的对象
    如:Person person = new Student(),如果我们调用person.eat(),实际上调用的是Student(子类)的方法
  • 在Python中的多态是这样体现的:只要有同名方法就可以调用,而不需要关注对象
class Animal(object):
    def eat(self):
        print("Animal:eat")
class Dog(Animal):
    def eat(self):
        print("Dog:eat")
class Cat(Animal):
    def eat(self):
        print("Cat:eat") 
class Person(object):
    def eat(self):
        print("Person:eat") 
def fun(obj):
    obj.eat()
fun(Cat())
fun(Dog())
'''
没有任何继承关系的也可以调用,只要方法名字相同就好
这个与其弱类型语言的特征有关
个人觉得好用,但是危险。你永远无法知道你队友的水平是怎样的
'''
fun(Person())
Cat:eat
Dog:eat
Person:eat

特殊方法和特殊属性

  • 特殊属性:
    • __dict_ _:获得类对象或者实例对象所绑定的所有属性和方法的字典
    • __class__:对象的类型
    • 其他:__bases__,__base__,__mro__
  • 特殊方法
    • __len__( ):通过重写__len__( )方法,让内置函数len()的参数可以是自定义的类型
    • __add__( ):通过重写__add__( )方法,可以使自定义的对象具有‘+’功能
    • __new__( ):用于创建对象
    • __init__( ):对创建的对象进行实例化
class A:
    pass
class B:
    pass
class C(A,B):
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat():
        print('C:eat')
class D(A):
    pass
c=C('jack',20)
print(c.__dict__)#实例对象的属性字典
print(C.__dict__)#类对象的属性和方法的字典
print(c.__class__)#输出对象的类型
print(C.__class__)#输出对象的类型
print(C.__bases__)#输出父类类型的元组:C-AB,实例对象不能调用
print(C.__base__)#输出离得最近的父类类型,如果class C(B,A)就会输出B的类型  实例对象不能调用
print(C.__mro__)#类的层次结构 实例对象不能调用
print(A.__subclasses__())# 子类的列表
{'name': 'jack', 'age': 20}
{'__module__': '__main__', '__init__': <function C.__init__ at 0x10a908e50>, 'eat': <function C.eat at 0x10a806670>, '__doc__': None}
<class '__main__.C'>
<class 'type'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>, <class '__main__.D'>]
a=20
b=100
c=a+b
print(c)
'''
两个整数通过‘+’符号进行相加,底层调用的是__add__方法
'''
d=a.__add__(b)
print(d)
class Student:
    def __init__(self,name):
        self.name=name
    '''
        重写__add__方法后,Student类也可以通过‘+’调用add方法进行相加
    '''
    def __add__(self,other):
        return self.name+other.name
    def __len__(self):
        return len(self.name)
stu1=Student('张三')
stu2=Student('李四')
print(stu1+stu2)
'''---------------------------------------------------------------------------------'''
lst=[1,2,3,4]
# len是内置函数,可以计算list的长度
print(len(lst))
'''
len()实际上调用的是__len__()方法
对于任意一个对象我们都可以重写__len__()方法来实现自定义的长度的计算
'''
print(lst.__len__())
print('stu1的长度=',len(stu1))
120
120
张三李四
4
4
stu1的长度= 2
'''
    init-new顺序:先通过new方法创建对象(1568),再通过init方法对对象(1568)进行赋值
        object对象(9520)--->类对象Person(3712)
        --->new传入的cls(3712)-->调用父类的new方法得到的obj对象(1568)
        --->init的self(1568)
        --->最后的实例对象(1568)
        p1=Person('张三',20):把Person(3712)传给了__new__的cls
        obj=super().__new__(cls):把Person传给了object的__new__方法,创建对象obj(1568)
        return obj:返回给__init__的self(1568)
        self初始化完成之后又给了p1(1568)
        
'''
class Person(object):

    def __init__(self,name,age):
        print('__init__被调用了,self的id值为{0}'.format(id(self)))
        self.name=name
        self.age=age

    def __new__(cls,*args,**kwargs):
        print('__new__被调用执行了,cls的id值为{0}'.format(id(cls)))
        obj=super().__new__(cls)
        print('创建的对象的id为:{0}'.format(id(obj)))
        return obj

print('object这个类对象的id为:{0}'.format(id(object)))
print('Person这个类对象的id为:{0}'.format(id(Person)))

p1=Person('张三',20)
print('p1这个Person类的实例对象的id:{0}'.format(id(p1)))
object这个类对象的id为:4411189520
Person这个类对象的id为:140462607923712
__new__被调用执行了,cls的id值为140462607923712
创建的对象的id为:4469041568
__init__被调用了,self的id值为4469041568
p1这个Person类的实例对象的id:4469041568

类的浅拷贝与深拷贝

  • 变量的赋值操作:只是形成两个变量,实际上还是指向同一个对象
  • 浅拷贝:
    python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象
  • 深拷贝:
    使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
class CPU:
    pass
class Disk:
    pass
class Computer:
    def __init__(self,cpu,disk):
        self.cpu=cpu
        self.disk=disk
print('''-----------------赋值操作------------------------''')
cpu1=CPU()
cpu2=cpu1
print(cpu1)#0x10a941700 同一个内存地址
print(cpu2)#0x10a941700 同一个内存地址
print('''-----------------浅拷贝操作------------------------''')
import copy
disk=Disk()
computer=Computer(cpu1,disk)
'''
computer1和computer2是两个不同的对象,有不同的地址值
但里面的子对象是相同的有相同的地址值
'''
computer2=copy.copy(computer)
print(computer,computer.cpu,computer.disk)
print(computer2,computer2.cpu,computer2.disk)
print('''-----------------深拷贝操作------------------------''')
'''
    深拷贝的子对象的地址都不相同,深拷贝会再产生内存空间来存储子对象
'''
computer3=copy.deepcopy(computer)
print(computer,computer.cpu,computer.disk)
print(computer3,computer3.cpu,computer3.disk)
-----------------赋值操作------------------------
<__main__.CPU object at 0x10a941700>
<__main__.CPU object at 0x10a941700>
-----------------浅拷贝操作------------------------
<__main__.Computer object at 0x10a888430> <__main__.CPU object at 0x10a941700> <__main__.Disk object at 0x10a941c70>
<__main__.Computer object at 0x10a941b20> <__main__.CPU object at 0x10a941700> <__main__.Disk object at 0x10a941c70>
-----------------深拷贝操作------------------------
<__main__.Computer object at 0x10a888430> <__main__.CPU object at 0x10a941700> <__main__.Disk object at 0x10a941c70>
<__main__.Computer object at 0x10a941dc0> <__main__.CPU object at 0x10a8b1910> <__main__.Disk object at 0x10a8b1640>

模块

  • 什么叫模块

    • 一个.py的文件就是一个模块
    • 一个模块包含函数、类、语句
  • 自定义模块

    • 创建模块:新建一个.py文件,名称尽量不用与Python自带的标准模块名称相同
    • 导入模块
      • import 模块名称 as 别名
      • from 模块名称 import 函数/变量/类
    • 导入的模块也是一个对象,有内存地址,类型(module)等
    • 再pycharm中导入自定义的模块报错:右键对应的包—>Mark Directory as—>Sources Root
  • 以主程序的形式执行
    if __name__ == '__main__':
               代码B
    意思是:在一个模块中我定义了代码A,同时又定义了代码B,如果另一个文件导入这个模块,A代码和B代码会同时执行。但是如果加上上诉代码,只有当改模块称为主程序的时候才会执行代码B,导入该模块的文件只会执行A代码。

  • python中的包

    • 包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下
    • 包的作用
      • 代码规范
      • 避免模块名称冲突
    • 包的导入:
      • import 包名.模块名 as 别名
      • from 包名 import 模块名
      • from 包名.模块名 import 函数/变量/类
    • 目录与包
      • 包在pycharm中是Python Package,会有一个init的py文件
      • 目录是Directory,没有init文件
  • 常用模块:

    • sys:与Python解释器及其环境操作相关的标准库
    • time:提高与时间相关的各种函数的标准库
    • os:提供访问操作系统服务功能的标准库
    • calendar:提供与日期相关的各种函数的标准库
    • urllib:用于读取来自网上(服务器)的数据标准库
    • json:用于石油Json序列化和反序列化对象
    • re:用于在字符串中执行正则表达式匹配和替换
    • math:提供标准算术运算函数的标准库
    • decimal:用于进行精确控制运算精度、有效位数和四舍五入的十进制运算
    • logging:提供了灵活的记录事件、错误、警告和调试信息等日子信息等功能
  • 第三方模块的安装及使用

    • 第三方模块的安装:pip install 模块名
    • 第三方模块的使用:import 模块名
import math
print(id(math))
print(type(math))
print(math)
4415612624
<class 'module'>
<module 'math' from '/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/lib-dynload/math.cpython-38-darwin.so'>

文件

编码格式

  • python的解释器使用的是Unicode(内存)
  • .py文件在磁盘上使用UTF-8存储(外存)
  • 常见编码格式:
    编码格式

文件的读写原理

  • 文件的读写俗称IO操作
  • 文件的读写流程
    Python操作文件->打开或者新建文件->读写文件->关闭资源
  • 操作原理:解释器运行.py文件,调用操作系统,操作硬盘上的文件

文件读写操作

  • 文件类型:
    • 文本文件:存储的是普通‘字符’文本,默认为unicode字符集,可以使用记事本程序打开
    • 二进制文件:把数据内容用‘字节’进行存储,如图片,视频,音频和doc等文件
  • 内置函数open创建或者打开文件:file=open(filename,[mode,encoding])
    • file:被创建的文件对象
    • open:创建文件对象的函数
    • 要创建或打开的文件名称
    • 打开模式,默认只读
    • 默认文本文件中字符的编写格式文gbk
  • 常用的文件打开模式
    • r:只读模式,文件指针放在文件的开头
    • w:只写模式,如果文件不存在则创建,如果文件存在则覆盖原有内容,文件指针在文件开头
    • a:追加模式,如果文件不存在则创建,文件指针在文件开头,如果文件存在则在文件末尾追加内容,文件指针在文件末尾
    • b:二进制模式,不能单独使用,要和其他模式一起使用,如:rb或者wb
    • +:以读写方式打开文件,不能单独使用,需要与其他模式一起使用,a+
# 文件写入
file=open('a.txt','w')
file.write('Python')
file.close()
# 文件读取
file=open('a.txt','r')
s=file.readlines()# 读全部
print(s,type(s))
file.close()
file2=open('a.txt','r')
s2=file2.readline()# 读一行
print(s2,type(s2))
file2.close()
['Python\n', 'JavaPythonPythonPythonPython'] <class 'list'>
Python
 <class 'str'>
# 追加模式
file=open('a.txt','a')
file.write('Python')
file.write('Python')
file.close()
# rb+wb 实现图片的复制
src_file=open('./PythonBase/1-类属性.png','rb')
target_file=open('1.png','wb')
target_file.write(src_file.read())
src_file.close()
target_file.close()
# + 以读写方式打开
'''
如果没有+,那么执行print(file.readlines())的时候会报错
UnsupportedOperation: not readable
'''
file=open('a.txt','a+')
'''
需注意的是你若刚用‘a+’打开一个文件,一般不能直接读取,
因为此时光标已经是文件末尾,除非你把光标移动到初始位置或任意非末尾的位置。
'''
print(file.readlines())
file.write('Python')
file.close()
[]

光标操作

  • seek函数:需要使用文件对象进行调用,无返回值。
    seek(offset,whence)
    • offset 控制光标移动的位移量(字节)
    • whence 模式
      • 0 基于文件开头移动多少字节
      • 1 基于光标当前所在位置移动多少字节
      • 2 基于文件末尾移动多少字节
    • ps:1和2只能在二进制模式下使用 0无所谓
  • tell函数:用来获取光标当前的位置(移动的字节数)
    • 代码表示:文件名.tell( )
    • 返回光标当前所在的字节数
file=open('a.txt','a+')
file.write('Python')
file.seek(0,0)# 把光标置于开头
print(file.readlines())
s=file.tell()
print(s,type(s))
file.close()
['Python\n', 'JavaPythonPython']
23 <class 'int'>

文件对象常用的方法

with语句:上下文管理器

  • 语法:
    with open(文件名,模式) as src_file:
       操作src_file
  • 作用:不用手动关闭流
  • 什么是上下文管理器:实现了__enter__()方法和__exit__()方法
  • open(文件名,模式):其为上下文表达式,结果为上下文管理器,
  • 上下文管理器同时创建一个运行时上下文,自动调用__enter__()方法,并将返回值赋值给src_file
  • 离开运行时上下文,自动调用上下文管理器的特殊方法__exit__()
# 上下文管理器
'''
MyContentMgr实现了特殊方法__enter__和__exit__,称该类对象遵循了上下文管理器协议
该类对象的实例对象称为上下文管理器
'''
class MyContentMgr(object):
    def __enter__(self):
        print('enter方法被调用执行了')
        return self
    def __exit__(self,exc_type,exc_val,exc_tb):
        print('exit方法被执行了')
    def show(self):
        print('show方法被调用执行了')
    def showError(self):
        print('showError方法被调用执行了',1/0)
with MyContentMgr() as file: # 相当于file=MyContentMgr()
    file.show()
print('走出with-----')
with MyContentMgr() as file: # 相当于file=MyContentMgr()
    file.showError()
enter方法被调用执行了
show方法被调用执行了
exit方法被执行了
走出with-----
enter方法被调用执行了
exit方法被执行了



---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

Cell In [93], line 20
     18 print('走出with-----')
     19 with MyContentMgr() as file: # 相当于file=MyContentMgr()
---> 20     file.showError()


Cell In [93], line 15, in MyContentMgr.showError(self)
     14 def showError(self):
---> 15     print('showError方法被调用执行了',1/0)


ZeroDivisionError: division by zero
# rb+wb 实现图片的复制
with open('./PythonBase/1-类属性.png','rb') as src_file:
    with open('2.png','wb') as target_file:
        target_file.write(src_file.read())

目录操作

  • os模块是Python内置的与操作系统功能和文件系统相关的模块,该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上运行,得到的结果可能不一样
  • os模块与os.path模块用于对目录或文件进行操作
  • os模块操作目录相关的函数
    • getcwd( ):返回当前的工作目录
    • listdir(path):返回指定路径下的文件和目录信息
    • mkdir(path,[,mode]:创建目录
    • makedirs(path1/path2…[,mode]):创建多级目录
    • rmdir(path):删除目录
    • removedirs(path1/path2…):删除多级目录
    • chdir(path):将path设置为当前工作目录
  • os.path模块操作目录相关的函数
    • abspath(path):用于获取文件或目录的绝对路径
    • exists(path):用于判断文件或目录是否存在,如果存在返回True,否则返回False
    • join(path,name):将目录与目录或文件名拼接起来
    • split(path):将文件路径和文件名分离
    • splitext():分离文件名和拓展名
    • basename(path):从一个目录中提取文件名
    • dirname(path):从一个路径中提取文件路径,不包括文件名
    • isdir(path):判断是否为路径
  • os.walk(path):获取path下所有文件和目录
import os
# os.system('应用名.exe')可以打开系统自动的软件
# mac的电脑还不知道怎么打开
#os.system('Stickies.app')
# 调用可执行文件:os.startfile(文件路径)mac电脑还不知到怎么弄
#os.startfile('/Applications/WeChat.app/Contents/MacOS/WeChat')
s=os.getcwd()
print(s)
print(os.listdir(s))
os.mkdir('newdir2')
os.makedirs('a/b/c')
os.rmdir('newdir2')
os.removedirs('a/b/c')
os.chdir('/Users/xieshaolin/workpalce/python/quant/newdir')
print(os.getcwd())
os.chdir('/Users/xieshaolin/workpalce/python/quant')
print(os.getcwd())
/Users/xieshaolin/workpalce/python/quant
['.DS_Store', 'python基础语法.ipynb', 'newdir', 'PythonBase', 'a.txt', 'numpy.ipynb', '.ipynb_checkpoints', 'python基础语法.md', '2.png', '1.png']
/Users/xieshaolin/workpalce/python/quant/newdir
/Users/xieshaolin/workpalce/python/quant
import os.path as op
print(op.abspath('a.txt'))
print(op.abspath('./PythonBase/1-类属性.png'))#可以用相对路径
print(op.exists('a.txt'),op.exists('b.txt'))
print(op.join('/Users','a.txt'))#不会校验,只是单纯拼接
print(op.split('/a/b/c'))# 不会区分,只是把最后一层分出来
print(op.splitext('/a/b/c.txt'))#不校验
print(op.basename('/a/b/c'))#不校验,只是提取最后一个
print(op.dirname('/a/b/c'))#不校验,提取前面的
# 会校验是不是真的目录
print(op.isdir('/a/b/c'),op.isdir('/a/b/c.txt'),
      op.isdir('/Users/xieshaolin/workpalce/python/quant/a.txt'),
     op.isdir('/Users/xieshaolin/workpalce/python/quant'))# ../a.txt是文件不是目录
/Users/xieshaolin/workpalce/python/quant/a.txt
/Users/xieshaolin/workpalce/python/quant/PythonBase/1-类属性.png
True False
/Users/a.txt
('/a/b', 'c')
('/a/b/c', '.txt')
c
/a/b
False False False True
# 列出指定目录下的所有文件
import os
path=os.getcwd()
pathlist=os.listdir(path)
for item in pathlist:
    print(os.path.abspath(item))
/Users/xieshaolin/workpalce/python/quant/.DS_Store
/Users/xieshaolin/workpalce/python/quant/python基础语法.ipynb
/Users/xieshaolin/workpalce/python/quant/newdir
/Users/xieshaolin/workpalce/python/quant/PythonBase
/Users/xieshaolin/workpalce/python/quant/a.txt
/Users/xieshaolin/workpalce/python/quant/numpy.ipynb
/Users/xieshaolin/workpalce/python/quant/.ipynb_checkpoints
/Users/xieshaolin/workpalce/python/quant/python基础语法.md
/Users/xieshaolin/workpalce/python/quant/2.png
/Users/xieshaolin/workpalce/python/quant/1.png
import os
path=os.getcwd()
listFile=os.walk(path)
print(listFile,type(listFile))
print('------------------------------------')
for item in listFile:
    print(item,type(item))# item 是一个元组
    print('------------------------------------')
<generator object walk at 0x10b3ec9e0> <class 'generator'>
------------------------------------
('/Users/xieshaolin/workpalce/python/quant', ['newdir', 'PythonBase', '.ipynb_checkpoints'], ['.DS_Store', 'python基础语法.ipynb', 'a.txt', 'numpy.ipynb', 'python基础语法.md', '2.png', '1.png']) <class 'tuple'>
------------------------------------
('/Users/xieshaolin/workpalce/python/quant/newdir', [], []) <class 'tuple'>
------------------------------------
('/Users/xieshaolin/workpalce/python/quant/PythonBase', [], ['.DS_Store', '3-编码格式.jpeg', '2-动态绑定.png', '1-类属性.png']) <class 'tuple'>
------------------------------------
('/Users/xieshaolin/workpalce/python/quant/.ipynb_checkpoints', [], ['numpy-checkpoint.ipynb', 'python基础语法-checkpoint.ipynb']) <class 'tuple'>
------------------------------------
# 元组还可以这么遍历
ls=[(1,2,3),(4,5,6),(7,8,9)]
for a,b,c in ls:
    print(a,b,c)
1 2 3
4 5 6
7 8 9
import os
path=os.getcwd()
listFile=os.walk(path)
'''
第一个:dirpath-当前路径
第二个:dirname-当前路径下的文件夹
第三个:filename-当前路径下的文件名
'''
for dirpath,dirname,filename in listFile:
    for item in filename:
        #print(os.path.abspath(item))这样不行,得出的结果是当前路径+文件名
        print(os.path.join(dirpath,item))
    print('--------------------------------------------------')
/Users/xieshaolin/workpalce/python/quant/.DS_Store
/Users/xieshaolin/workpalce/python/quant/python基础语法.ipynb
/Users/xieshaolin/workpalce/python/quant/a.txt
/Users/xieshaolin/workpalce/python/quant/numpy.ipynb
/Users/xieshaolin/workpalce/python/quant/python基础语法.md
/Users/xieshaolin/workpalce/python/quant/2.png
/Users/xieshaolin/workpalce/python/quant/1.png
--------------------------------------------------
--------------------------------------------------
/Users/xieshaolin/workpalce/python/quant/PythonBase/.DS_Store
/Users/xieshaolin/workpalce/python/quant/PythonBase/3-编码格式.jpeg
/Users/xieshaolin/workpalce/python/quant/PythonBase/2-动态绑定.png
/Users/xieshaolin/workpalce/python/quant/PythonBase/1-类属性.png
--------------------------------------------------
/Users/xieshaolin/workpalce/python/quant/.ipynb_checkpoints/numpy-checkpoint.ipynb
/Users/xieshaolin/workpalce/python/quant/.ipynb_checkpoints/python基础语法-checkpoint.ipynb
--------------------------------------------------

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com

×

喜欢就点赞,疼爱就打赏