本文阅读适合人群:
1.新手小白
2.复习python知识
3.学过其他语言转python语言
文章目录
前言
Python 是一种解释型、面向对象的语言
Python的语法和动态类型,以及解释性语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言
一、变量的定义
1.变量
是什么?变量就是可以变化的数据,
为什么?为了让计算机和人一样可以记住事物的状态
怎么做?变量的组成分为两部分:变量的名字和变量的数据值`
#变量名 = 数据值
#例如:
a = 1
b = 10
#当变量定义完之后可以修改数据值,如何修改?
a = 1 # 定义一个变量,变量名为a,保存了数据1。
a = 10 # 将变量名a重新保存数据10,原来的1就不被a所保存了。
2.标识符
所谓的标识符就是对变量、常量、函数、类等对象起的名字。
首先必须说明的是,Python语言在任何场景都严格区分大小写!
-
Python对于标识符的命名有如下规定:
1、第一个字符必须是字母表中的字母或下划线‘_’
例如, a, Ak, _set_id, green 等都是可以的,但是例如 $abc, &_a, ~bashrc, 123abc 等是不可以的!2、但以下划线开头的标识符通常都有特殊意义
例如,_foo代表禁止外部访问的类成员,需通过类提供的接口进行访问,不能用"from xxx import *"导入;3、而以双下划线开头的
例如__foo,代表类的私有成员;以双下划线开头和结尾的(foo )是python里特殊方法专用的标识,如 init__()
代表类的构造函数。这些在后面会有专门的论述,暂时只要知道它们的特殊性就行了 -
标识符的其他的部分由字母、数字和下划线组成
1.也就是说标识符除了首字符不可以是数字外,其它部分还可以包含数字。那特殊字符呢?当然还是不行的啦。所以, a123c_, bbc, city_of_china 等等都是可行的,而 a&b, king-of-the-world,love@qq.com 都是不行的。2.另外要注意的是,由于l(小写的L)和数字1, 大小写的o与数字0在外观上的相似性,请尽量不要让它们相邻出现,保持语义的清晰性,确保不会发现错误认读的情况。同样,我们继续烧脑,英文中夹塞中文在语法上也是可以的,但绝对不要这么做!
a这都能行b舅服你 = 100
-
标识符对大小写敏感
这条是基于Python严格区分大小写的,所以标识符abc与ABC是不同的两个。 -
变量名全部小写,常量名全部大写
这条不能算语法层面的要求,而是代码规范的要求。虽然你可以用PI来表示一个变量,但通常我们都会认为这是代表圆周率的一个常量。 -
函数和方法名用小写加下划线
同样也不是语法强制,而是代码规范,我们在定义一个函数或者方法的名字的时候,请尽量用类似get、set、count_apple、total_number 之类的命名方式。 -
类名用大写驼峰
也不是语法强制,而是代码规范。所谓的大写驼峰指的是每个单词的首字母大写,组合在一起就像驼峰一样高低高低的排列。例如 ThreadMixIn、BrokenBarrierError、_DummyThread 等等 -
模块和包的名字用小写
请尽量小写模块和包的名字,并且不要和标准库以及著名的第三方库同名。 -
变量的命名不要用关键字和内置函数的名字!
下面我们就会讲到Python有哪些关键字,而内置函数的知识则要到后面的章节。
3.python保留字
Python保留字,也叫关键字,是Python语言官方确定的用作语法功能的专用标识符,不能把它们用作任何自定义标识符名称。关键字只包含小写字母。
也可以参照下表:
4.注释
我们写的程序里,不光有代码,还要有很多注释。注释有说明性质的、帮助性质的,它们在代码执行过程中相当于不存在,透明的,不参与任何工作。但在代码维护、解释、测试等等方面,发挥着不可或缺的重要作用。每一位程序员都要尽量写出高质量的注释。具体的注释专题,有大量的高水平文章和论
述,请自行搜索并学习。这里,我们只讨论Python中注释的方法。
-
单行注释
Python中,以符号“#”为单行注释的开始,从它往后到本行的末尾,都是注释内容。#第一行注释
-
多行注释
以三对单引号/双引号组合,在中间加入被注释的内容。#第一行注释 #第二行注释 #第三行注释 """ 多行注释 """
二、(基本)数据类型
数据可以分为不同类型,方便数据的管理和使用
类似图书馆会对不同类型的书籍进行分类摆放,提高查找效率,方便管理
数据类型分类:根据定义的数据值有不同的分类
- 数值类型—> 整型(int), 浮点型(float)
- 字符串(str),凡是带有引号的数据都是字符串
- 布尔型,只有两个值(False和True), 用作判断
type()
type()
python提供的一个功能
作用:用来查看小括号内写的变量/数据的类型是什么
1.整数
Int 类型
整数类型用于存储数学意义上的整数值
数字类型是不可变类型。所谓的不可变类型,指的是类型的值一旦有不同了,那么它就是一个全新的对象。数字1和2分别代表两个不同的对象,对变量重新赋值一个数字类型,会新建一个数字对象。
还是要强调一下Python的变量和数据类型的关系,变量只是对某个对象的引用或者说代号、名字、调用等等,变量本身没有数据类型的概念。类似1,[2, 3, 4],“haha”这一类对象才具有数据类型的概念。
代码如下(示例):
a = 1 # 创建数字对象1
a = 2 # 创建数字对象2,并将2赋值给变量a,a不再指向数字对象1
print(type(a)) 输出 <class 'int'>
这里,发生了变化的是变量a的指向,而不是数字对象1变成了数字对象2。初学者可能会比较迷糊,但不要紧,我们努力去明白它
这里补充一个小小的知识点
对于内存的概念,看到这里的同学可能不知道内存是个什么东西,但还是想补充一下,如上图代码,数字1与数字2都有一个不同的存储单元(内存块),变量a本来指向数值为1的存储单元元(内存块),通过修改,变量a的指针就指向数值为2的存储单元(内存块),通俗点来说,左边a就是一个变量,右边的数据就是一个内存,不同的数值对应着一个不同的内存,变量a可以用来指向任何的 对象(内存),从而输出变量后得到相应内存中的元素
2.浮点数(小数)
float类型
浮点数类型用于存储数学意义上的小数值
代码如下(示例):
a = 1.1
b = 0.1541
print(type(a),type(b)) <class 'float'> <class 'float'>
3.布尔
布尔类型是计算机中最基本的类型,它是计算机二进制世界的体现,一切都是0和1。Python中的布尔类型只有两种值:True和False。(注意:第一个字符必须为大写)
>>> bool(None)
False
>>> bool(0)
False
>>> bool([])
False
>>> bool(())
False
>>> bool('')
False
>>> bool({})
False
以上是判断为假的情况,总结一下为假的情况有:
(1)None和False
(2)空字符串(‘’)、空元组(())、空列表([])
(3)空字典({})、空集合(set())、range(0)
- 总结一下
无论什么值,只要为空,就返回False
4.字符串
1.字符串:字符串是Python中最常用的数据类型之一,使用单引号或双引号来创建字符串,使用三引号创建多行字符串。字符串要么使用两个单引号,要么两个双引号,不能一单一双!Python不支持单字符类型,单字符在Python中也是作为一个字符串使用。
2.字符串是不可变的序列数据类型,不能直接修改字符串本身,和数字类型一样!Python3全面支持
Unicode编码,所有的字符串都是Unicode字符串,所以传统Python2存在的编码问题不再困扰我们,
可以放心大胆的使用中文。
a = 'abc'
b = '你好,我是jayjay'
c = '中'
d = """abc"""
e = '1'
print(type(a)) <class 'str'>
-
索引/下标/编号
1.下标又称作索引,也就是编号。比如火车座位号,如下图,座位号的作用:按照编号快速找到对应的座位。同理,下标的作用即通过下标快速找到对应的数据。2.使用方法:字符串是由字符组成的,每个字符在字符串中都有一个唯一的位置,这个位置可以用编号来表示。字符串的编号从0开始,即第一个字符的索引为0,第二个字符的索引为1,如下图,依此类推编号从
-
切片
在Python中,切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素,而切片取出序列中一个范围对应的元素,这里的范围不是狭义上的连续片段。下面的代码初步展示了切片索引的力量。
下面我们看代码例子:
s1 = '周大伦的妹妹'
s2 = '周大伦的媳妇'
s3 = '''周大伦的小舅子'''
s4 = '''周大伦的小弟弟'''
索引的用法:
取单个字符的方式:索引(编号)取值
写法:字符串[编号]
在定义字符串的时候,python会自动给每个字符进行编号,从0开始的 (正数编号)
print(s1[0]) 周
print(s1[1]) 大
print(si[2]) 伦
负数编号:
反方向从-1开始
print(s1[-1]) 妹
print(s1[-2]) 妹
print(si[-3]) 的
索引超出范围 报错
print(s1[6]) IndexError: string index out of range 超出索引范围
因为s1最大索引为s1[5]输出-》妹 第六个索引不存在
切片的用法:
从一个字符串中获取连续的多个字符
写法:字符串[开始编号:结束编号] 结束编号不包含
从s1字符串中获取 大伦的妹妹
print(s1[1:6]) 索引1-5
print(s1[-5:]) 从左往右切
print(s1[:]) 取出全部
从一个字符串中获取不连续但是有规律的多个字符
从 周大伦的妹妹 中取出 周伦妹
写法: 字符串[开始编号:结束编号:间隔]
间隔为1代表连续
间隔为2代表隔开1个
间隔为3代表隔开2个
print(s1[0:5:2]) 周伦妹
# 整数 小数 布尔 不可以通过索引取值的方式去获取数据,
s2 = 100
# 能不能获取100的长度?
# 能不能获取100中的0?
# 不可以的,整数是一个整数,不可以被分割
- 字符串的相关功能
1.获取字符串的内容长度
len(字符串变量/字符串数据)
a = 'abcdefgabcdefga#bcde fgabcdefgabcdefgabcdefg'
# 针对字符串类型,可以获取字符串数据的长度(字符的个数)
print(len(a)) # 42
print('我要学python') #9
- 获取字符串中某个子字符串的编号
字符串.find(字符串变量/字符串数据,开始编号) # 开始编号不写,代表从字符串的开头去查找
s3 = 'Python具有简单、易学、免费、开源、可移植、可扩展、可嵌入、面向对象等优点,而且从事Python开发,所从事的工作机会和工作岗位及工作内容可选择的余地很多,未来发展空间也很大。。'
# 对于这种数据比较多的情况下,想要取出某个编号对应的数据,不好一个个的去数
# 获取'python'的编号 写法: 字符串.find(数据)
print(s3.find('python'))
# find功能查找数据的编号,如果数据存在,则返回第一个字第一次出现的编号,如果不存在,则为-1(没有)
print(s3.find('java')) # -1
# 找第一个'python'出现的编号
print(s3.find('python'))
# 当一个字符串中出现了多个'python',可以写第二个数字(第一个'python'的编号+1)
python1 = s3.find('python') # python1变量保存的是字符串中出现的第一个'python'的编号
# 第二个'python'出现的编号
python2 = s3.find('python',python1+1)
# dpython2保存的是第二个'python'的编号,因为指定了从第一个'python'的后面位置开始查找
字符串内置方法
字符串中有很多方法,这里列举几个我们常用的方法
- 字符串.upper()
全部转大写
str = 'abc'
print(str.upper()) #ABC
- 字符串.lower()
全部转小写
str = 'ABC'
print(str.lower()) #abc
- 字符串.count(子字符串)
获取子字符串在字符串中出现的次数
str='aabbcc'
print(str.count(a)) #4
- 字符串.replace(原始数据,新数据)
替换字符(返回值才是替换之后的数据,不会改变原本字符串)
str = 'aabbcc'
pritn(str) #aabbcc
print(str.replace('a','b')) #bbbbcc
s = 'abc'
s.replace('a','b')
#执行s.replace('a','b')之后 ,s不会发生变化
print(s) # abc
print(s.replace('a','b'))
- 字符串.split(字符)
字符串切割成列表
str = 'abjcdjefjfr'
print(str.split('j')) #['ab', 'cd', 'ef', 'fr']
- 列表.join
把列表中的数据按照某个符号进行拼接成字符串
list = ['1','2','3','4','5']
print(''.join(list)) #12345
print('-'.join(list)) #1-2-3-4-5
- 字符串.strip()
去除左右两边的符号
s = ' a b '
print(len(s)) # 5
s = s.strip(' ')
print(len(s)) # 3
s = 'abc'
s = s.strip('a') # bc
print(s)
- 字符串.find
从字符串中查找子字符串第一次出现的编号。
str = 'abcabcc'
print(str.find('a')) #返回找到的第一个索引 0
print(str.find('r')) #找不到 返回-1
- 字符串.index
str = 'abcabcc'
print(str.index('a')) #返回找到的第一个索引 0
print(str.index('r')) #找不到 则报错
- 字符串.title()
把字符串中的多个单词首字母转为大写,但是多个单词之间要隔开
# 驼峰命名法:HelloPython
s5 = 'hello-python'
# 字符串.title() 把多个单词的首字母进行大写(多个单词之间要有分隔)
print(s5.title()) #Hello-Python
-
字符串名.startswith(子字符串)
判断字符串是否以子字符串作为开头
如果是则为True,如果不是则为False -
字符串名.endswith(子字符串)
判断字符串是否以子字符串作为结束
如果是则为True,如果不是则为False
s6 = '标题:女子答应给大叔生个胖娃娃,他比我大18岁,希望别辜负我!'
s7 = 'abcdef'
# 判断字符串是不是以标题作为开头
# 字符串.startswith(子字符串)
print(s6.startswith('标题')) # True 代表正确
print(s7.startswith('标题')) # False 代表错误
# 判断字符串是不是以f作为结束
print(s6.endswith('f')) # False
print(s7.endswith('f')) # True
-
字符串名.isdigit()
判断字符串中所有的字符是否为字母
如果是则为True,如果不是则为False -
字符串名.isalpha()
判断字符串中所有字符是否为数字
s6 = 'abc123'
s7 = 'abcdef'
s8 = '123'
print(s6.isalpha()) # False
print(s7.isalpha()) # True
print(s6.isdigit()) # False
print(s8.isdigit()) # True
- 判断子字符串是否在字符串中存在
- 子字符串名 in 字符串名 如果是则为True,如果不是则为False
s6 = '标题:女子答应给大叔生个胖娃娃,他比我大18岁,希望别辜负我!'
s7 = 'abcdef'
# 胖娃娃是不是在s6字符串中
print('胖娃娃' in s6) # True
print('胖娃娃' in s7) # False
字符串是Python中和列表、字典同样重要的数据类型,对它的操作特别多,因此内置了很多方法。每当
你要处理字符串的时候,不妨来这里查查,或许就有原生的方法,不用你自己去写了。
三、(特殊)数据类型
为什么是(特殊)数据类型呢?
因为以下四类数据类型都是用来存储数据的,所以我们也可以把他们当作数据类型,但是python是一门面向对象编程,当我们后面学到面向对象的时候大家就明白了,下面的四个数据类型都是python内置写好的对象,当我们使用的时候就可以创建对应数据类型的对象,执行类内部的函数,达到我们所需要的效果
1.列表
前面所学习的三种数据类型中,在保存数据的时候,只能保存一个数据,如果需要保存多份数据怎么办呢?这时候就需要学习新的数据类型来解决了。
列表类型用来保存多个数据,使用中括号表示,多个数据之间用逗号隔开。
ls = [1,2,3] # 列表类型,保存三个数据
type(ls) # 查看ls变量保存的数据类型为list
列表特点:
1.可存放多个值
2.按照从左到右的顺序定义列表元素,索引从0开始顺序访问,有序
3.可修改指定索引位置对应的值,可变
- 列表的操作
增加操作:
1.增加单个数据到末尾----列表.append(数据)
ls = [1,2,3] # 列表类型,保存三个数据
ls.append(4)
print(ls) #[1,2,3,4]
- 增加单个数据到指定位置----列表.insert(索引,数据)
ls = [1,2,3] # 列表类型,保存三个数据
ls.insert(0,4)
print(ls) #[4,1,2,3]
ls,insert(-1,5) #索引为负数时,就往左边前一位添加数据
print(ls) #[4,1,2,5,3]
- 增加多条数据到末尾----列表.extend(列表)
ls = [1,2,3] # 列表类型,保存三个数据
ls.extend(['a','b','c'])
print(ls) #[1,2,3,'a','b','c']
- 在末尾增加一个列表----列表.append(列表)
ls = [1,2,3] # 列表类型,保存三个数据
ls.append(['a','b','c'])
print(ls) #[1,2,3,['a','b','c']]
查找操作:
- 通过索引取值(切片)
ls = [1,2,3,4,5,6,7,8]
# 单数据取值 列表[索引]
print(ls[0]) # 1
# 连续多数据取值 列表[开始索引:结束索引] 结束索引不取值
print(ls[0:3]) # [1,2,3]
# 不连续多数据取值 列表[开始索引:结束索引:步长]
print(ls[0:5:2])# [1,3,5]
- 判断某个数据是否在列表中
print(1 in [1,2,3,4]) #True
- 先通过取索引,然后通过索引取值
# 查询
l1.index('p') # 从左开始匹配到一个p的索引
l1.count('c') # 返回列表中c的个数
# python一行代码实现冒泡排序
# 排序操作,按照列表数据的从小到大依次排列
print(sorted(ls))
# 排序操作,按照列表数据的从大到小依次排列
print(sorted(ls,reverse=True))
修改操作:
1.通过索引修改值
data = ['aa', 'bb', 'cc']
data[1] = 'xx'
print(data) #['aa','xx','cc']
删除操作:
- 删除最末尾元素----列表.pop()
data = ['aa', 'bb', 'cc']
data.pop() #['aa', 'bb']
- 删除指定索引元素----列表.pop(索引)
data = ['aa', 'bb', 'cc']
data.pop(0)
print(data) #[ 'bb', 'cc']
- 根据指定数据删除----列表.remove(数据)
data = ['aa', 'bb', 'cc']
data.remove('aa')
print(data) #[ 'bb', 'cc']
- python自带的del(任何情况通用)----del 列表[索引]
data = ['aa', 'bb', 'cc']
del data[0]
print(data) #[ 'bb', 'cc']
- 清空----列表.clear()
data = ['aa', 'bb', 'cc']
data.clear()
pritn(data) # []
2.元组
元组类型用来保存多个数据,使用圆括号表示,多个数据之间用逗号隔开。与列表类型不同的是:元组保存后数据不可以更改!!只能做查询操作
ages = ()
ages = (11, 22, 33, 44, 55)
#或
ages = tuple((11, 22, 33, 44, 55))
#注意
ages = (1) #这个是Int类型
ages = (1,) #这个是元组类型
元组特点:
1.可存放多个值
2.不可变
3.按照从左到右的顺序定义元组元素,索引从0开始顺序访问,有序
- 元组的操作
索引取值
ages = () #空元组
ages = (11, 22, 33, 44, 55)
#或
ages = tuple((11, 22, 33, 44, 55))
#注意
ages = (1) #这个是Int类型
ages = (1,) #这个是元组类型
ages = 1, #这个也是元组类型
元组的操作和列表是一模一样的,除了不可以增删改
注意:元组本身不可变,如果元组中还包含其他可变元素,这些可变元素可以改变
例如:
data = (99, 88, 77, ['小明', '小红'], 33)
data[3][0] = '张三'
print(data) #(99, 88, 77, ['张三', '小红'], 33)
3.字典
字典类型和列表,元组的都是用来保存多个数据的,只是字典类型的数据的特点在于一次性保存了多对数据
字典类型: 字典类型是由一个大括号 {键:值} 如果一个字典中有多个键值对,使用逗号隔开一个数据和另外一个数据有对应关系
姓名 : 小王
性别 : 男
年龄 : 18
# 定义字典的格式:
# 变量名 = 数据值
info = {'姓名':'小王','性别':'男','年龄':18}
# 获取info变量保存的数据值长度为几
print(len(info)) # 3
字典特点:
1- 字典类型中的数据是有对应关系的
2- 字典中的键是唯一的,如果保存数据的时候,键重复了,会把后一个值(冒号后面的)替换给前一个
3- 字典中的值是可以重复的
4- 字典中没有编号(字符串,元组,列表),只能通过键去操作
- 字典的操作
查询操作
#格式1:字典名[键]
s = {'小王': '安徽', '小蓝': '广东', '小帅': '广西','小红':'四川'}
print(s['小王']) # 安徽
#格式2:字典名.get(键)
print(s.get('小蓝')) #广东
区别:当键不存在的时候,格式1会报错,格式2不会报错,会给None(代表没有)
增加操作
# 格式:字典名[键] = 值
s['小红'] = '四川' # 添加一对数据,键为 姚同学,值为四川
print(s) # {'小王': '安徽', '小蓝': '广东', '小帅': '广西','小红':'四川'}
修改操作
# 格式: 字典名[键] = 值
# 把姚同学的值修改为湖南
s['姚铭'] = '湖南'
print(s) # {'小王': '安徽', '小蓝': '广东', '小帅': '广西','小红':'四川', '姚铭': '湖南'}
什么情况下是添加?什么情况下是修改?
当键在字典中不存在,是添加操作,当键在字典中存在,是修改(通过键修改值)
删除操作
#格式 del 字典名[键]
del s['小王']
print(s) # {'小蓝': '广东', '小帅': '广西','小红':'四川', '姚铭': '湖南'}
清空字典
# 格式:字典名.clear()
s.clear()
print(s) #{}
小作业:
'''
保存小明家庭数据
个人信息:姓名,年龄,性别
家庭成员
宠物成员
'''
info = { # 有换行只是为了结构清晰,并不是强制要求换行。
'姓名':'小明',
'年龄':25,
'性别':'男',
# '家庭成员姓名':['大明','小红','大大明','大小红','小小明'],
'家庭成员':{
'父亲':'大明',
'母亲':'小红',
'爷爷':'大大明',
'奶奶':'大小红',
'弟弟':'小小明'
},
'宠物':{'狗':'小小','猫':'明明'}
}
print(info)
4.集合
集合是用来保存多个数据的一种数据类型,无序且唯一
使用{}来进行数据保存
集合特点:
1-集合中能够保存的数据类型有:整数,小数,字符串,布尔,元组
2- 集合保存的数据是无序的 (存进去顺序和取出来的顺序不一样)
3- 集合中保存的数据是唯一的
4- 集合是没有编号的
s = {} #空集合
s =set() #空集合
s = {1,2,3,4,'abc',11,22}
pritn(s) #{2,4,3,1,'abc',11,22} 无序随机
- 集合的操作
增加操作
# 添加数据
# 集合名.add(数据)
s3 = {5,6}
s3.add(1) # 添加数据的时候,如果数据已经在集合中存在了,则添加不进去(唯一的)
print(s3) # {1,5,6}
# 合并数据
# 集合名.update(集合名)
s4 = {1,2,3,4}
# 把s3中的数据合并到s4中
s4.update(s3)
print(s4) #{1,2,3,4,5,6}
删除操作
# 删除数据
s4 = {'abc','aaa',3,4,'coco'}
# 指定数据删除
# 集合名.discard(数据) 如果数据不存在,则不会影响
s4.discard('aaa')
# 集合名.remove(数据)
s4.remove('a1') # 如果数据不存在,则报错
# 清空数据
s4.clear()
print(s4) # set() 代表空集合
print(type(s4)) # 集合类型
5.总结
- 常用类型
1.什么情况下使用集合保存数据?
当数据有多个,并且数据是唯一的情况
2.什么情况下使用元组保存数据?
当数据有多个,并且数据不能发生任何改变
3什么情况下使用字典保存数据?
当数据有多个,并且数据之间有存在对应关系
4.什么情况下使用列表保存数据?
当数据有多个,数据没有约束(没有对应关系,不要求唯一,还可以发生改变)
单个数据:布尔 字符串 整数 小数
整数 int
小数 float
字符串 str
布尔 bool
列表 list
集合 set
字典 dict
元组 tuple
- 类型转换
你要变什么,就用类型关键字(原本的类型数据)
ls = [1,2,1,1,3,4,5]
print(set(ls))
# 整数 ---》字符串
a = 1 # '1'
print(str(a)) # '1'
# 字符串'111' ---》整数 111
a2 = '111'
print(int(a2))
# a3 = 'abc' # --- >整数 运行报错 因为不是数字的字符串不能够转为整数类型
# print(int(a3))
# 字符串 ---》小数
# '1.23' ---> 1.23
运算符
算数运算符
print(float('1.23'))
# 整数 ---》 小数
# 1 ---》 1.0
print(float(1))
# 小数 ---》 整数
# 1.68 ---> 1 直接舍去小数位,不存在任何四舍五入
print(int(1.68))
# 字典 ---》 列表 只会把字典的键存在列表中
d1 = {'姓名':'coco'}
print(list(d1))
# 列表---》字典
# print(dict(ls))
# 布尔 --- 》整数
print(int(True)) # 1
print(int(False)) # 0
# 任何类型 ---》 布尔 只有0为False,其它都为True
print(bool({1:2}))
print(bool(-1.1))
# '中文'
s1 = '中文' #--->['中','文']
s1 = 'abc' #--->['a','b','c']
print(list(s1))
# ' '
s2 = ' '
print(list(s2))
print(set(s2)) #{' '}'
ls = [' ',' ']
s = str(ls) # "[' ',' ']"
print(type(s))
四、判断语句
在生活中存在很多的判断,在python中同样也存在判断语句,目的是为了要让程序跟人一样做思考,判断某件事是否成立再去做。
- if语句
if语句是用来进行判断的,其使用格式如下:
语法1:
if 判断条件:
代码1
代码2
代码3
# 注意缩进(代码前的空格) 通过缩进个数来表示是一个部分
hour = 12
if hour>11:
print('该吃饭了')
从上往下执行 满足条件(hour>11为True)就是输出该吃饭了
hour = 12
if hour>11:
print('该吃饭了')
print(123)
#输出
该吃饭了
123
# 因为if语句和print语句前面的空格一样,所以没有关系,执行完if代码之后再执行print代码
在使用if的时候,它只能做到满足条件时要做的事情。那万一需要在不满足条件的时候,做某些事,该怎么办呢?
- if else语句
语法2
if 判断条件:
代码1
代码2
代码3
else:
代码1
代码2
代码3
results=59
if results>=60:
print ('及格') # 满足条件时要做的事情
else :
print ('不及格') # 不满足条件时要做的事情
继续升级,如果判断语句不仅有两个,有些时候需要多个,比如上面的例子中大于 60 的为及格,那我们还要判断大于 90 的为优秀,在 80 到 90 之间的良好呢?这时候需要用到 if 语句多个判断
条件
- if elif else语句
if 判断条件1:
执行语句1……
elif 判断条件2:
执行语句2……
elif 判断条件3:
执行语句3……
else:
执行语句4……
if results >= 90:
print('优秀')
elif results >= 80 and results <90: # and代表并且
print('良好')
elif results >= 60 and results <80:
print ('及格')
else:
print ('不及格')
- 三目运算符
三目运算符主要用来化简代码量的,化简的是非常简单的if…else的代码,也就是if条件成立就执行一句代码,不成立就执行另外一句代码。
一般能不使用就不使用,除了简短没什么优点(也不美观)
格式: 为真结果 if 判断条件 else 为假结果
if a>b:
max = a
else:
max = b
#三目运算符
max = a if a>b else b
补充:
- 输入输出
python提供了两个功能
print() 往控制台中输出小括号的内容
input() 往控制台中输入数据 一般作用于用户交互
五、流程控制
- while循环
循环就是重复做某个事情,在python中,我们编写的代码有时候也需要重复执行,所以可以利用循环可以解决
循环的语法:
while 条件表达式: 条件表达式结果为True执行语句,为False,则不执行语句(结束循环)
执行语句
如果想要输出10次 认真学习
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
print('认真听课')
次数为10次代码还可以复制粘贴 但是当次数过多,再去复制粘贴代码就不那么好了,毕竟属于劳动力操作,所以可以改为循环的语法
a = 0
while a<10: # 循环10次
print('认真听课')
a=a+1 # 必须要改变a变量的值,否则就是无限循环
# 无限循环的代码
a = 0
while a<5: # 造成无限循环的原因:a永远都是0 永远都小于5 件永远为True
print('认真听课')
# 作业改造
#提示用户输入5次数字,检查它是否在范围 10-20 内,并且是偶数。输出结果
a = 0
while a<5:
num = int(input('请输入一个数字'))
if num>=10 and num<=20 and num%2==0:
print(f'{num}是一个10-20之间的数,并且还是偶数')
else:
print(f'{num}不是一个10-20之间的数,或者不是偶数')
a += 1
所以针对这种情况,可以总结出知道循环次数的语法为:
# 知道循环次数:
变量 = 0
while 变量<次数:
执行代码
变量+=1
- for循环
python中提供了两种循环方式,一种为while一种为for,for循环使用的场景更多的是在取值(取出列表中的每个数据,并且做操作)
比如需求:
a = [11,22,33,44,55]
# 获取a列表中 哪些数据是奇数? 思路:需要取出列表中的每一个数,来做判断。
# 第一种方式:
#获取列表中第1个数 判断是不是奇数?
print(a[0]%2!=0)
# 获取列表中第2个数 判断是不是奇数?
print(a[1]%2!=0)
# 获取列表中第3个数 判断是不是奇数?
print(a[2]%2!=0)
# 获取列表中第4个数 判断是不是奇数?
print(a[3]%2!=0)
# 获取列表中第5个数 判断是不是奇数?
print(a[4]%2!=0)
# 这种写法虽然可以实现,但是很麻烦,如果列表的数据个数很多的话怎么处理?
# 通过观察,上面五行代码只有编号值不一样,并且编号都是有规律的 ,每次+1
# 所以可以改为循环完成
# 第二种方式:
a = [11,22,33,44,55,88,99]
count = 0 # 变量名 = 数据值
# 循环次数:取决于列表中数据的个数 所以可以用len获取列表的数据个数 来作为循环的次数
while count<len(a):
# 取出列表中的每个数
# count=0 count=1 count=2 count=3 count=4
# 因为每次循环count值都会发生改变,正好对应着列表的编号
# print(a[count]%2!=0)
if a[count]%2!=0:
print(a[count])
count+=1
# while循环可以解决代码重复的问题,每次循环把count作为了编号,循环一次就+1,在循环中通过这个变量去取出数据即可
# 第三种方式
a = [11,22,33,44,55,88,99]
# 使用for循环列表
for i in a: # for循环多少次,取决于列表中有多少个数据。
# 在循环内部,可以使用i变量获取列表中的每个数据
# print(i)
if i%2!=0:
print(i)
由此可见,for循环在针对保存多个数据的数据类型中,取出每个数据更加简单。
- for循环取值
# for循环字符串 每循环一次 取出字符串中的一个字符
s = 'abc'
for i in s:
print(i)
# for循环元组 每循环一次 取出元组中的每一个数据
t = (1,2,3,4)
for i in t:
print(i)
# for循环集合 每循环一次 取出集合中的每一个数据
s = {1,2,3,4,5,5} #{1,2,3,4,5}
for i in s:
print(i)
# for循环字典:每循环一次 取出字典中的每一个键
d = {"name":"小王","age":11}
for i in d:
# print(i) # name
# print(d[i]) # 字典取值:字典名[键]
print(f'{i} {d[i]}')
# 获取字典的关系(结婚证)
# print(d.items())
# 同时获取键和值
for key,value in d.items():
print(key,value)
- for指定循环次数
# for循环次数 循环的是列表 字符串 元组 字典 集合
# 这些类型中保存了几个数据值,就循环几次
name = 'xiaohong'
password = '111'
s = 'abcbc'
for i in s:
# for循环 in后面放的是一个字符串数据,字符串中有多少个字符就循环几次
# 虽然下面代码可以实现要求,但是这个字符串没有任何的含义,并且在循环中也没有使用到
# 所以字符串很多余\
inp = input('请输入您的用户名:')
pn = input('请输入您的密码:')
if name == inp and pn == password:
print('登录成功')
break
else:
print('登录失败')
-
推荐写法
for循环生成循环次数 range(数字):指定循环几次,从0-数字减1 range(开始数字,结束数字):指定循环次数,从指定开始到 结束减一 range(开始数字,结束数,间隔):指定循环次数,从指定开始到 结束减一,并且设置间隔(步长)间隔为1代表连续,间隔为2,代表隔开1个,间隔为3,代表隔开2个
# 使用range
# range(次数)
name = 'xiaohong'
password = '111'
for i in range(5):
inp = input('请输入您的用户名:')
pn = input('请输入您的密码:')
if name == inp and pn == password:
print('登录成功')
break
else:
print('登录失败')
for i in range(5): # range(5) -->[0,1,2,3,4] 默认从0开始,到4结束
print(i)
#输出1-100的所有数
#range(开始,结束) # 结束不包含
for i in range(1,101):
print(i)
#循环49次,从1开始 到49结束
for i in range(1,50):
print(i)
# 循环49次,从50开始 到99结束
for i in range(50,100):
print(i)
# range(开始,结束,间隔)
for i in range(1,5,2): # 1 3
print(i)
六、函数
函数是一段具备有某个功能的代码块。
为了重复使用某个功能。
#在python中求和操作
list1 =[59,23,56,78,90,234,64,12,9]
sum = 0
for i in list1:
sum+=i
print(sum)
# 求list2的和
list2 =[1,2,156,178,190,1234,164,112,19]
sum = 0
for i in list2:
sum+=i
print(sum)
# 求list3的和
list3 =[11,12,156,1178,1190,11234,1164,1112,119]
sum = 0
for i in list3:
sum+=i
print(sum)
# 如果想要计算不同列表数据的总和,解决办法:复制粘贴相同的代码,循环的列表名更改
# 可以解决问题,但是有缺点:代码重复率太高了 (证明这个开发水平不够)
# 函数解决问题:
# 解决数据求和的问题 ---》写个函数,专门用来求和
1.基础
- 函数的定义
'''
函数的基本定义
def 函数名():
执行操作要做的事情
函数定义之后,需要调用才会被执行函数的代码
函数名()
'''
# 定义函数
def function():
print('这是function函数的代码....')
return 1 #返回值
# 调用(使用)函数 不限调用次数
function() #这是function函数的代码....
print(function()) # 1 #打印 函数() 返回returm的返回值
pritn(function) # 返回的是function 函数地址
# function是函数的名字,函数名保存的是函数地址
- 形参与实参
形式参数:在定义函数的时候,在小括号中编写的内容,编写的是一个名字(变量名)
实参:实际参数:在使用(调用)函数的时候,在小括号内编写的内容,编写的是数据
def func(x): # x保存的是什么值?当调用func函数,就需要传入一个数据(实参)
print(x)
#使用函数的时候,给定参数值
#函数名()
func(1)
func(['ac','bb'])
func('abc')
func(1,2)# 错误写法:函数只有一个形参,调用函数就只能传一个实参
def func(x,y):
print(x)
print(y)
# func(10) 错误写法:函数有2个形参,调用函数就只能传2个实参
func(10,20)
func('abc',20)
# # 实参的类型不固定,实参默认按照参数位置一一给到形参。
func(20,'abc')
# # 关键字传参 按照形参的名字给定数据值
func(y=1,x=2)
# func(x=1,a=2) 运行问题,定义函数的时候,没有a参数,只有x和y参数
# func(x=1,x=2) 语法问题,
func(3,3)
#混合使用 语法规定,单个数据值,必须要放在最前面,关键字放在后面
def func(x,y,z):
print(x)
print(y)
print(z)
func(1,z=2,y=3)
func(z=2,y=3,1) #语法问题
func(1,x=2,y=3) #运行问题:x参数只有保存一个数据,不能保存多个
一切以需求出发,如果需求中有没有不确定的数据,如果有,写形参,如果没有,就不写形参
例如:
需求:定义一个函数,做列表数据求和的功能
需求中有不确定的:列表
需要写形参:形参个数:1
def get_sum(ls): # 函数的名字叫sum 函数有一个形参 形参名为ls
sum = 0
# 定义变量 保存和
for i in ls: # 循环列表
sum+=i # 把每个数+和变量中
print(sum) # 所有数据的和
list1 = [59, 23, 56, 78, 90, 234, 64, 12, 9]
get_sum(list1)
list2 =[1,2,156,178,190,1234,164,112,19]
get_sum(list2)
list3 =[11,12,156,1178,1190,11234,1164,1112,119]
get_sum(list3)
- 函数的参数类型
位置参数
def func(a,b):
print(a,b)
# 这种格式的就是属于位置参数,参数的特点在于:形参和实参的个数必须要对应上,多一个不行,少一个不行
# 调用函数
func(1,2)
func(a=1,b=2)
func(1,b=2)
# 当需求中 有未知的数据 并且确定参数个数时,选择位置参数即可
默认参数
# 默认参数,在调用函数的过程中,多次调用传入的实参一致,可以将参数定义为默认参数
def func(a,b=1): # 语法要求:如果形参中包含位置参数和默认参数,位置参数要放在最前面
print(a,b)
func(10) # 没有传入参数b的数据值,则使用默认值
func(10,20) # 传入了b的数据值,则使用传入的,而不是默认值
func(10,20,30) # 不可以,参数多了一个
可变长度参数
# 可变长度参数:在定义形参的过程中,不能分析出到底有几个不确定的数据
def func(*args,**kwargs): # * 用来接收所有的实参,并且变为了元组类型交给args保存
print(args,kwargs) # ** 用来接收所有的关键字实参,并且变为了字典类型交给了kwargs保存
# args和kwargs只是一种规范,就是一个形参的名字。
func(1)
func(1,3)
func(1,3,4,4)
func(1,3,4,4,4)
func(aa=1,b=2,c=3) #{'aa':1,'b':2,'c':3}
func(1,2,x=1,y=2) #(1,2){'x':1,'y':2}
2.进阶
- 作用域
定义在函数内部的变量拥有一个局部作用域,称之为局部变量,定义在函数外的拥有全局作用域,称之为全局变量
局部变量: 只能在其函数内部访问
全局变量: 可以在任何地方访问
函数内部查找机制
- 首先,在函数内部查找变量。这些变量是在函数内部声明或传递给函数的参数。
- 如果在函数内部没有找到变量,解释器会继续查找包含当前函数的外部函数的作用域,直到找到为止。
- 如果在上述步骤中仍然没有找到变量,解释器会查找全局作用域中的变量。全局作用域是指在函数外部定义的变量。
- 最后,如果在前面的步骤中都没有找到变量,则查找内置的变量和函数名,如 print() 和 len() 等。
x = 10 # 全局变量
def foo():
y = 20 # 局部变量
print(x) # 在函数内部访问全局变量
print(y) # 在函数内部访问局部变量
foo() # 输出: 10 20
print(x) # 输出: 10
print(y) # 报错,y 在函数外部不可见
- global关键字
如果你想在函数内部修改全局变量的值,你需要使用 global 关键字。通过在函数内部使用 global 关键字声明变量,将其指定为全局变量,就可以对全局变量进行修改。
a = 1
def f():
global a
a = a + 1
f()
print(a) # 输出: 2
- Lambda函数
lambda 函数也称为 匿名函数,用来创建一个简单的函数,而无需使用 def 关键字定义一个常规函数
语法: lambda arguments: expression
参数:
1.arguments 是函数的参数列表,可以包含零个或多个参数(多个参数使用逗号分隔)
2.expression 则是函数体中的表达式
# 求两个数的和
add = lambda x, y: x + y
result = add(3, 4)
print(result) # 输出: 7
# 求一个数的平方
square = lambda x: x**2
result = square(5)
print(result) # 输出: 25
- 高阶函数
高阶函数是指可以接受一个或多个函数作为参数,或者返回一个函数的函数
1.map()
作用: 将一个函数应用到迭代器的每个元素上,并返回一个包含结果的迭代器。
语法: map(function, iterable, …)
参数:
function :要应用于每个元素的函数。
iterable :要处理的可迭代对象,如列表、元组等。
示例:
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # 输出: [1, 4, 9, 16, 25]
通俗理解:
就是遍历列表中的数据并且执行函数方法,返回执行函数后的数据
2.filter()
作用: 根据函数的返回值筛选出符合条件的元素,并返回一个包含这些元素的迭代器。
语法: filter(function, iterable)
参数:
function :用于筛选元素的函数。
iterable :要筛选的可迭代对象。
示例:
numbers = [1, 2, 3, 4, 5]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # 输出: [2, 4]
通俗理解:
就是遍历列表中的数据,返回列表中与函数方法匹配的数据
3.sorted()
作用: 对可迭代对象进行排序,并返回一个新的列表。可以通过 key 参数指定排序的关键字,通过 reverse 参数指定是否降序排序。
语法: sorted(iterable, key=None, reverse=False)
参数:
iterable :要排序的可迭代对象。
key (可选):用于指定排序的关键字函数。
reverse (可选):是否进行降序排序,默认为升序排序。
示例:
# 示例一: 默认排序
numbers = [5, 3, 1, 4, 2]
sorted_numbers = sorted(numbers)
print(sorted_numbers) # 输出: [1, 2, 3, 4, 5]
# 示例二:根据字符串的第二个字符排序
numbers = ['c2', 'b3', 'a4', 'd1']
sorted_numbers = sorted(numbers, key=lambda x: x[1])
#x=1 从小到大 x=0 从大到小
print(sorted_numbers) # 输出: ['d1', 'c2', 'b3', 'a4']
# 示例三: 根据字符串的长度排序
numbers = ['ccc', 'a', 'aa', 'bbbb']
sorted_numbers = sorted(numbers, key=lambda x: len(x))
print(sorted_numbers) # 输出: ['a', 'aa', 'ccc', 'bbbb']
通俗理解:
就是一个用来排序的函数
4.zip()
作用: 用于将多个可迭代对象(例如列表、元组等)打包成一个元组的迭代器
语法: zip(*iterables)
参数:
*iterables : 可变数量的可迭代对象参数,可以是列表、元组等 。
示例:
fruits = ['苹果', '香蕉', '桔子']
prices = [5.0, 3.5, 6.8]
for fruit, price in zip(fruits, prices):
print(fruit, price)
# 输出结果
苹果 5.0
香蕉 3.5
桔子 6.8
# zip(fruits, prices)将fruits和prices两个列表打包成一个元组的迭代器。在每次迭代中,fruit变量接收fruits列表中的元素,price变量接收prices列表中的元素,然后打印它们。
通俗理解:
就是将可迭代列表转化为可迭代元组,一般用于遍历时候提取数据用
5.enumerate ( )
作用: 用于在for循环中得到计数,利用它可以同时获得索引和值,即需要index和value值的时候可以使用enumerate 。
语法: enumerate(sequence, [start=0])
参数:
sequence : 序列、迭代器对象 。
start : 下标起始位置。
示例:
s = [1, 2, 3, 4, 5]
for index, value in enumerate(s):
print('%s, %s' % (index, value))
# 输出结果
0, 1
1, 2
2, 3
3, 4
4, 5
s = [1, 2, 3, 4, 5]
# 从指定索引1开始
for index, value in enumerate(s, 1):
print('%s, %s' % (index, value))
输出结果:
1, 1
2, 2
3, 3
4, 4
5, 5
通俗理解:
就是拿到数据值的同时也拿到索引
- 闭包
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包
通过闭包的定义,我们可以得知闭包的形成条件
- 在函数嵌套(函数里面再定义函数)的前提下
- 内部函数使用了外部函数的变量(还包括外部函数的参数)
- 外部函数返回了内部函数
# 定义一个外部函数
def outer(num1):
# 定义一个内部函数
def inner(num2):
# 内部函数使用了外部函数的变量(num1)
result = num1 + num2
print("结果是:", result)
# 外部函数返回了内部函数,这里返回的内部函数就是闭包
return inner
# 创建闭包实例
f = outer(1)
# 执行闭包
f(2)# 3
f(3)# 4
- 装饰器
就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数
功能特点:
- 不修改已有函数的源代码
- 不修改已有函数的调用方式
- 给已有函数增加额外的功能
装饰器的示例代码
#装饰器标准写法
def outer(fun):
def inner(*args,**kwags):
print('函数执行之前')
ret = fun(*args,**kwargs)
print('函数执行之后')
return ret
return inner
#装饰器语法糖
@outer
def game():
print('我要玩游戏')
#调用game函数
game()
#结果:
'''
函数执行之前
我要玩游戏
函数执行之后
'''
小案例
# 定义装饰器
import time
def outer(function): # func1需要添加功能的函数
def inner(*args, **kwargs):
# 计算函数调用耗时是多久
start_time = time.time()
ret = function(*args, **kwargs) # 原函数需要传参的话应该怎么做
end_time = time.time()
result_time = end_time - start_time
print('当前程序总耗时:%s' % result_time)
return ret
return inner
# 需要添加功能的函数
@outer
def func1():
list1 = []
for i in range(1000000):
list1.append(i)
# 调用函数
func1() #当前程序总耗时:0.15700030326843262
七、面向对象
python是属于一门面向对象语言。
面向对象和面向过程的区别在于:
面向对象:只要找到对象,就可以让对象帮我们实现操作(不需要管对象是如何做的)
面向过程:必须要按照步骤,一步步的像流水线完成工作
# 比如组装电脑
# 面向过程:根据步骤一步步实现
1- 查找资料
2- 查找配件
3- 对比配置,对比价格
4- 下单购买
5- 拿快递
6- 组装
# 面向对象:找到对象帮我完成
找一个会组装电脑的人
# 找这个对象的前提:这个对象能做这个事情
那python如何自定义对象呢?
- 类
python的所有对象都来源于类,有类才可以创建对象。类就像对象的设计图纸。
class 类名:
属性 # 属性就是对象的数据(本质就是类中的变量)
方法 # 方法就是对象的功能(本质就是类中的函数)
class 手机:
# 对象的数据 在类中用变量保存 (属性)
尺寸 = 5.7
品牌 = '华为'
颜色 = '黑色'
样式 = '曲面屏'
价格 = 8888
内存 = '1T'
# 对象的功能 在类中用函数定义 (方法)
def 上网聊天(self):
print('上微信')
def 打电话(self,号码): # 号码是形参
print(f'正在给{号码}拨打电话')
def 刷视频(self,软件名):
print(f'正在{软件名}刷视频')
有了类之后 如何创建对象
- 对象
# 创建对象的方式:类名()
对象名 = 类名() # 对象名实际保存的是对象的地址
# 有了对象才可以操作类中的属性和方法
# 调用类中的方法
对象名.方法名() # 有参传参,没参不传,self不需要传
# 操作类中的属性
# 获取类属性值
print(对象名.属性名)
# 修改类属性值
对象名.属性名 = 属性值
# 添加类属性
对象名.属性名 = 属性值
如果对象中有该属性,则修改,如果没有,则添加
# 如何创建手机对象?
#变量名 = 类名()
sj = 手机()
# 如果调用方法? 对象.方法名()
sj.上网聊天()
# 如何获取属性值 对象.属性名 获取到的就是对象的属性值
print(sj.颜色)
# 如何修改属性值? 对象.属性名 = 属性值
# 把手机对象的颜色改为白色
sj.颜色 = '白色'
print(sj.颜色)
# 如何添加属性? 对象.属性名 = 属性值
sj.像素 = '6400万'
print(sj.像素)
# 如何判断是添加属性还是修改属性? 如果对象中有,则修改,没有,则添加
# 当有了类之后,可以造出无数个对象 每个对象都是新的
sj2 = 手机()
print(sj2) # 保存的是对象在内存空间中的地址
# 修改属性
sj2.价格 = 11800 # 只会修改其中一个对象的属性 ,而不是所有对象的
sj3 = 手机()
print(sj3.价格)
sj4 = 手机()
sj4.打电话('110')
当我们按照面向对象的思想去设计类时,如果把所有的属性都直接定义在类中,创建出来的所有对象属性值都是相同的。比如
class 手机:
# 对象的数据 在类中用变量保存 (属性)
尺寸 = 5.7
品牌 = '华为'
颜色 = '黑色'
样式 = '曲面屏'
价格 = 8888
内存 = '1T'
# 对象的功能 在类中用函数定义 (方法)
def 上网聊天(self):
print('上微信')
def 打电话(self,号码): # 号码是形参
print(f'正在给{号码}拨打电话')
def 刷视频(self,软件名):
print(f'正在{软件名}刷视频')
但是实际上 不同的手机有不同的数据值,所以这时候我们会把这些属性放到初始化方法中
class 手机:
# 初始化方法
# 手机('苹果','5.9',1111) #
def __init__(self,品牌,尺寸,价格): # 形参
# self是一个形参,但是不需要我们自己手动传入实参
# self=对象地址 当前对象是谁,self就是谁
# print(self)
# 对象.属性名 = 属性值 (来源于参数)
self.品牌 = 品牌
self.尺寸 = 尺寸
self.价格 = 价格
print('执行init了')
# 对象的功能 在类中用函数定义 (方法)
def 上网聊天(self):
print(f'{self.品牌}上微信')
def 打电话(self,号码): # 号码是形参
print(f'正在给{号码}拨打电话')
def 刷视频(self,软件名):
print(f'正在{软件名}刷视频')
# 使用
# 创建对象 . 方法名()
s = 手机('小米','5.8',2222) # 创建对象的时候 __init__方法是自动执行 (自动被调用)
s.上网聊天()# 小米手机正在上微信
s2 = 手机('苹果','5.9',1111)
s2.上网聊天()# 苹果手机正在上微信
# 如果每个对象中的数据是一样的,就直接放在类中,如果每个对象中的数据是不一样的,就放在init中
-
继承
描述如下对象: 笔 数据:颜色 材质 品牌 长度 价格 .... 功能:写字 画画 钢笔: 数据:颜色 材质 品牌 长度 价格... 功能:写字 画画 眉笔: 数据:颜色 材质 品牌 长度 价格 功能:画眉毛 粉笔: 数据:颜色 材质 品牌 长度 价格 功能: 写字 画画 铅笔: 数据:颜色 材质 品牌 长度 价格 功能: 写字 画画 继承满足的前提: 子类属于父类 铅笔属于笔 √ 眉笔属于笔 √ 粉笔属于笔 √ 钢笔属于笔 √ 每个类中都有重复的代码,思考能不能使用继承去解决代码重复问题。继承发生的前提一定是!子类属于父类,不能为了简 化代码而继承
class 笔: # 父类
def __init__(self,颜色,价格):
self.颜色 = 颜色
self.价格 = 价格
def 写字(self):
print('写字')
def 画画(self):
print('画画')
class 钢笔(笔): # 子类 如何继承父类?子类(父类名)
pass
class 眉笔(笔): # 子类
def 画眉毛(self):
print('画眉毛')
class 粉笔(笔):
pass
class 铅笔(笔):
pass
# 如何使用
# 创建对象
qb = 铅笔('黑色',1.88)
qb.写字()
# qb.画眉毛() # 没有这个方法,所以报错 铅笔和眉笔属于兄弟关系
b = 笔('红色',5.22)
b.写字()
b.画画()
# b.画眉毛() # 没有这个方法,所以报错 儿子继承父亲
mb = 眉笔('灰色',78)
mb.画眉毛()
mb.画画()
mb.写字()
# 如果想要按照面向对象的思想去设计对象,就需要创建这么几个类
# 但是发现这些里面的代码 都是重复的
# 类--->继承---->子类继承父类
- 重写
当继承之后,子类写了一个和父类一模一样的方法,就发生了重写
学生:
属性:性别 姓名 年龄
方法:学写代码 写作业
老师:
属性:性别 姓名 年龄 工资
方法:教写代码 布置作业
学生继承老师?
老师继承学生?
定义一个人类:
属性:性别 姓名 年龄
方法:吃 喝 玩 乐
示例:
# 父类
class People:
# 人名
personName = '人' # 类属性
def __init__(self,name,age,sex): # 形参接收实参
self.name = name
self.age = age
self.sex = sex
def play(self):
print(f'{self.name}正在玩耍')
# 子类
class Teacher(People):
# 因为重写了,所以在初始化方法中,参数就要有4个
# shine = Teacher('shine',18,'男',111111)
def __init__(self,name,age,sex,salary):
# self.name = name
# self.age = age
# self.sex = sex
# 既然父类已经对这三个属性进行了添加,能不能直接调用父类的初始化方法呢?
super().__init__(name,age,sex) # 传入实参
self.salary = salary
def teach_a_lesson(self):
print(f'{self.name}正在教代码')
def homework(self):
print(f'{self.name}正在布置作业')
# 子类
class Student(HKYXPeople):
def learn_code(self):
print(f'{self.name}正在学代码')
def do_the_homework(self):
print(f'{self.name}正在写作业')
def play(self):
print(f'{self.name}正在玩pubg')
# 子类对象
shine = Teacher('shine',18,'男',111111)
shine.homework()
shine.teach_a_lesson()
mmx = Student('猛犸象',20,'男')
mmx.learn_code()
mmx.do_the_homework()
mmx.play() # 猛犸象正在玩pubg
# 当子类和父类中拥有一个相同的方法(方法名)
# 子类到底有几个?1 子类
# 只有继承才有会重写:子类重新写了一个和父类一模一样的方法
# 创建子类对象,调用方法,执行的子类的
ya = Teacher('ya',18,'男',8.88)
ya.homework()
ya.play() #ya正在玩耍
注意! 发生重写之后,创建子类对象,调用重写方法,执行的是子类自己的。而创建父类对象,调用重写方法,执行的也是父类自己的。
'''
发生在继承的关系上
重写:子类重新编写和父类一模一样的方法
对父类的方法没有影响
'''
class Dog:
def eat(self):
print('正在吃东西')
class KejiDog(Dog):
def wrestling(self):
print('摔跤....')
def eat(self):
print('正在吃高贵的狗粮')
# 创建父类对象
d = Dog()
d.eat() # 执行本类方法
# 创建子类对象
k = KejiDog()
k.eat() # 执行重写后的方法,执行的是子类
- 多继承方式
class A:
def a(self):
print('a')
class B:
def b(self):
print('b')
class C(A,B): # 多继承,直接在小括号内用逗号隔开
def c(self):
print('c')
c = C()
c.a() #继承了 A 中的方法
c.b() #继承了 B 中的方法
c.c() # 执行自己类中的方法
class A:
def b(self):
print('a')
class B:
def b(self):
print('b')
class C(A,B): # 多个父类中有相同的方法
# c类中只有两个方法
def c(self):
print('c')
c = C()
c.b()
c.c()
#查找顺序 创建该类对象,调用方法,按照列表的顺序依次查找
print(C.mro())
#结果:
#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
class A:
def a(self):
print('a')
class B(A):
def b(self):
print('b')
class C(B):
def c(self):
print('c')
class D(C):
def d(self):
print('d')
d = D()
d.a()
d.b()
d.c()
d.d()
八、文件操作
文件的作用
大家应该听说过一句话:“好记性不如烂笔头”。
不仅人的大脑会遗忘事情,计算机也会如此,比如一个程序在运行过程中用了九牛二虎之力终于计算出了结果,试想一下如果不把这些数据存放起来,相比重启电脑之后,“哭都没地方哭了”可见,在把数据存储起来有做么大的价值
使用文件的目的:
就是把一些存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力
文件的打开与关闭
如果想用word编写一份简历,应该有哪些流程呢?
- 打开word软件,新建一个word文件
- 写入个人简历信息
- 保存文件
- 关闭word软件
同样,在操作文件的整体过程与使用word编写一份简历的过程是很相似的
- 打开文件,或者新建立一个文件
- 读/写数据
- 关闭文件
打开文件
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件open(文件名,访问模式)
示例如下:f = open('test.txt', 'w')
关闭文件
close()
示例:
# 新建一个文件,文件名为:test.txt
f = open('test.txt', 'w')
# 关闭这个文件
f.close()
- 文件的读写
使用write()可以完成向文件写入数据
f = open('test.txt', 'w')
f.write('hello world, i am here!')
f.close()
注意:
如果文件不存在那么创建,如果存在那么就先清空,然后写入数据
读数据(read)
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
示例:
f = open('test.txt', 'r')
content = f.read(5)#字节为5的长度
print(content)
print("-"*30)
content = f.read()
print(content)
f.close()
注意:
如果open是打开一个文件,那么可以不用打开的模式,即只写 open(‘test.txt’)
如果使用读了多次,那么后面读取的数据是从上次读完后的位置开始的(光标指到哪就是哪的位置开始读)
读数据(readlines)
就像read没有参数时一样,readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
#coding=utf-8
f = open('test.txt', 'r')
content = f.readlines()
print(type(content)) #<class 'list'>
i=1
for temp in content:
print("%d:%s"%(i, temp))
i+=1
f.close()
# 如何按照一次读取一行的方式,读取完文件的所有内容?
# 循环解决:
while True:
res = f.readline() # res=一行内容
# # 循环结束的条件 :如果数据读取完了,res的长度为0
if len(res)==0:
break
print(res)
# for循环 in后面可以放 字符串 元组 列表 集合 字典 文件对象
with open('test.txt', 'rw',encoding='utf-8') as f:
for i in f:
print(i)
# 每循环一次,从文件中读取一行数据,交给i变量保存
# 什么时候结束循环?当文件读取完毕之后,循环结束
上下文管理器
with 是在编程语言中用于处理资源的上下文管理器。它提供了一种简洁和可靠的方式来确保资源在使用完毕后被正确释放,无论是否发生异常。
语法:
with 资源 as 变量:
# 对资源进行操作的代码块
1.其中,资源是指需要在代码块中使用的对象,比如文件、网络连接、数据库连接等。变量则是一个命名的引用,用于在代码块中引用该资源。
2.当进入 with 代码块时,资源会被自动分配给变量,并且在退出 with 代码块时会自动释放资源。即使在代码块中发生了异常,也能确保资源的正确释放。
3.以使用文件操作为例,可以使用 with 语句打开和读取文件内容,而无需显式地调用关闭文件的操作
with open('file.txt', 'r') as f:
data = f.read()
# 对文件内容进行操作
访问模式说明
- 访问模式操作
w模式
w为只写模式:如果文件不存在,自动创建文件,如果文件存在,则覆盖数据(原本文件中的数据没有了)
name = input('请输入你的名字')
# 字符串前加r:字符串中任何的符号都不生效
with open(r'D:\1.txt','w') as f: # f = open(r'D:\1.txt','w') 多了一个f.close()的操作
# 写内容
# 变量名.write(字符串)
f.write(name) # 把name变量保存的数据值写入到文件中
r模式
# r为只读模式 :如果文件不存在,则No such file or directory(文件或者文件夹不存在)
with open(r'D:\1.txt','r')as f:
r = f.read() # 从文件中读取所有数据,并且交给r变量保存
print(r)
a模式
#a为只写模式:如果文件不存在,自动创建文件,如果文件存在,则追加数据(原本文件中的数据还在)
name = input('请输入你的名字')
with open(r'D:\1.txt','a') as f:
f.write(name)
b模式
rb wb ab
#b模式为二进制模式:将文件转化为二进制数据
#通常是用来处理图片,音乐
'''
图片:
实现电脑复制粘贴的效果
一次读取一行数据
先复制 再粘贴
读取原文件数据
写入到新文件中
'''
#r w a 操作的都是字符串数据
#图片 视频 音频 保存的数据不是字符串数据!!!!二进制数据(字节数据)
#rb 读取字节数据
with open('r.jpg','rb')as f:
jpg = f.read() # 读取文件的内容,保存到jpg变量中
with open('r_copy.jpg','wb')as f2:
f2.write(jpg)
#把复制到的二进制内容写入f2对象中,进而写入r_copy.jpg文件中
'''
\xcf\xda\x9d\xa9G\x89\x04\t\xb5#\x8eV\x8dT\x0f\xa6O^\xa7\x8
'''
编码:文字 ---- 》 二进制 字符串.encode('utf-8')
字符串 ----》字节
看得懂的 ----》看不懂的
解码 :二进制 ---》文字 字节.decode(utf-8)
字节 ----》字符串
看不懂的 ---》看得懂的
a = '中文'
a.encode('utf-8')
可读可写
1.r+
2.w+
3.a+
补充:
with open('2.txt','w+')as f:
f.write('巴适得板')
# 移动光标到文件的开头
f.seek(0)
# 读取
print(f.read()) #
九、异常处理
异常(Exception)是指在程序执行期间发生的错误或意外情况。当程序遇到异常时,会中断正常的执行流程。通过异常处理可以将异常捕获,从而让程序正常走完。
示例:
list = [1,2,3,4,5]
print(list[5]) #Indexerror : list index out of range
语法:
try:
# 可能抛出异常的代码
except 异常类型 as e:
print(f'异常错误原因:{e}')
# 异常处理代码
finally:
#无论是否异常都会执行的代码
我们需要先分清楚哪些代码需要加入异常处理
语法错误:
处理办法?把代码修改正确
逻辑错误:
1- 错误发生的条件是可以预知的:解决就是 把代码修改正确
2- 错误发生的条件是不可以预知的:(一般是正常测试没问题,非法测试有问题)
解决办法:使用异常处理的方式:
try except finally
示例代码:
num = 1
try:
# 如果try里面的代码出现了异常,则进入except进行异常的处理
# 如果try里面的代码没有出现异常,则不进入except
i = int(input('请输入你要猜的数字')) # 用户
if num>i:
print('猜小了')
elif num<i:
print('猜大了')
else:
print('猜对了')
except:
# 处理办法
print('请正确输入数字!!!')
finally:
# 不管try中的代码是否出现了异常,都一定执行
print('执行了finally')
print(111)
十、正则表达式
正则表达式(Regular Expression),是一种用来匹配、查找和操作文本的强大工具。在 Python 中,我们可以使用内置的 re 模块来支持正则表达式的使用。
- 正则函数
re.match( )
作用: 匹配字符串的开头,若匹配成功返回一个match对象,若失败返回None
语法: re.match(pattern, string)
参数:
pattern :匹配规则
string :被匹配的字符串
示例:
import re
pattern = 'python'
string = 'python3.7,python'
result = re.match(pattern, string)
# 1. 匹配成功返回match对象
print(result) # <re.Match object; span=(0, 6), match='python'>
# 2. 调用span()可以查看匹配到的位置
print(result.span()) # (0, 6)
# 3. 调用group()可以查看匹配到的字符
print(result.group()) # python
# 4. 匹配失败返回None
result = re.match('python', '1python3.7,python')
print(result) # None
re.search( ) 常用
作用: 搜索整个字符串,找出匹配的字符,找到第一个后就会停止,不会继续向后搜索,若匹配成功返回一个match对象,若失败返回None
语法: re.search(pattern, string)
参数:
pattern :匹配规则
string :被匹配的字符串
示例:
import re
pattern = 'python'
string = '1python3.7'
result = re.search(pattern, string)
# 1. 匹配成功返回match对象
print(result) # <re.Match object; span=(1, 7), match='python'>
# 2. 调用span()可以查看匹配到的位置
print(result.span()) # (1, 7)
# 3. 调用group()可以查看匹配到的字符
print(result.group()) # python
# 4. 匹配失败返回None
result = re.search('python', '1pyton3.7')
print(result) # None
re.findall( ) 常用
作用: 匹配整个字符串,找出全部匹配项,返回一个列表
语法: re.findall(pattern, string)
参数:
pattern :匹配规则
string :被匹配的字符串
示例:
import re
pattern = 'python'
string = '1python3.7,python,sasdf'
result = re.findall(pattern, string)
# 1. 返回一个列表
print(result) # ['python', 'python']
# 2. 匹配失败返回空列表
result = re.findall('python', '1pon3.7')
print(result) # []
re.sub( )
作用: 替换所匹配到的字符串,返回替换后的字符串
语法: re.sub(pattern, repl, string)
参数:
pattern :匹配规则
repl :替换内容
string :被匹配的字符串
示例:
import re
# 定义要搜索的字符串和匹配的模式
string = "Hello, 123 World! 456"
pattern = "123" # 匹配 123
# 使用re.sub进行模式匹配和替换
replaced_string = re.sub(pattern, "NUM", string)
print("替换后的字符串:", replaced_string)
# 输出: 替换后的字符串: Hello, NUM World! 456
re.split( )
作用: 根据指定模式对字符串进行分割,返回分割后的子字符串列表
语法: re.split(pattern, string)
参数:
pattern :匹配规则
string :被匹配的字符串
示例:
import re
# 定义要拆分的字符串和匹配的模式
string = "Hello, 123 World! 456"
pattern = "123" # 匹配一个或多个数字
# 使用re.split进行拆分
splitted_parts = re.split(pattern, string)
print("拆分后的结果:", splitted_parts)
# 输出: 拆分后的结果: ['Hello, ', ' World! 456']
- 正则元字符
单字符匹配
示例:
import re
# . 匹配任意字符,除了换行符
print(re.search('.', 'python123')) # <re.Match object; span=(0, 1), match='p'>
print(re.search('1.3', 'python123')) # <re.Match object; span=(6, 9), match='123'>
# [] 匹配[]中列举的字符
print(re.search('[p23]', 'python123')) # <re.Match object; span=(0, 1), match='p'>
print(re.search('[ew3]', 'python123')) # <re.Match object; span=(8, 9), match='3'>
print(re.search('[0-9]', 'python123')) # <re.Match object; span=(6, 7), match='1'>
# \s 匹配空白字符,如空白,空格,tab等
print(re.search(r'\s', 'python 123*')) # <re.Match object; span=(6, 7), match=' '>
# \S 匹配任意非空白字符
print(re.search(r'\S', 'python 123*')) # <re.Match object; span=(0, 1), match='p'>
print(re.search(r'\S\S', 'python 123*')) # <re.Match object; span=(0, 2), match='py'>
# \d 匹配任意数字
print(re.search(r'\d', 'python 123')) # <re.Match object; span=(7, 8), match='1'>
# \D 匹配任意非数字
print(re.search(r'\D', 'python 123')) # <re.Match object; span=(0, 1), match='p'>
匹配数量
示例:
import re
# * 前一个字符出现0次或无限次 ,即可有可无
print(re.search('abc*', 'abcab ')) # <re.Match object; span=(0, 3), match='abc'>
print(re.search('abc*dd', 'abcabddd ')) # <re.Match object; span=(3, 7), match='abdd'>
# + 前一个字符出现1次或无限次,即至少出现1次
print(re.search('abc+', 'abccccab ')) # <re.Match object; span=(0, 6), match='abcccc'>
print(re.search('abc+', 'abcab ')) # <re.Match object; span=(0, 3), match='abc'>
# ? 前一个字符出现1次或0次 ,即要么1次要么没有
print(re.search('abc?', 'abccccab ')) # <re.Match object; span=(0, 3), match='abc'>
# {m} 前一个字符出现m次
print(re.search('abc{2}', 'abccccabc ')) # <re.Match object; span=(0, 4), match='abcc'>
# {m,} 前一个字符至少出现m次
print(re.search('abc{2,}', 'abccccabc ')) # <re.Match object; span=(0, 6), match='abcccc'>
# {m, n}前一个字符出现m到n次
print(re.search('abc{2,4}', 'abccccabc ')) # <re.Match object; span=(0, 6),
match='abcccc'>
匹配分组
import re
# () 匹配括号内的表达式作为一个分组
# 示例1:匹配日期并提取年、月、日
date_string = "2023-07-14"
pattern = r"(\d{4})-(\d{2})-(\d{2})"
match = re.match(pattern, date_string)
print(match.group(1)) # 2023
print(match.group(2)) # 07
print(match.group(3)) # 14
# | 匹配左右任意一个表达式
print(re.search('hello|aaaa', 'asdflasjaaaasd')) # <re.Match object; span=(8, 12),
match='aaaa'>
print(re.search('hello|aaaa', 'asdflhelloasjaaaasd')) # <re.Match object; span=(5, 10),
match='hello'>
匹配边界
import re
# ^ 匹配字符串的开头
print(re.search('^a', 'abcd')) # <re.Match object; span=(0, 1), match='a'>
print(re.search('^a', 'bcd')) # None
# $ 匹配字符串的末尾
print(re.search('a$', 'abcda')) # <re.Match object; span=(4, 5), match='a'>
print(re.search('a$', 'abcd')) # None
- 贪婪匹配和非贪婪匹配
贪婪匹配:
在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
非贪婪匹配:
加上 ?将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
示例:
import re
# 贪婪匹配
print(re.search('ab+', 'abbb')) # <re.Match object; span=(0, 4), match='abbb'>
# 非贪婪匹配(懒惰匹配)
print(re.search('ab+?', 'abbb')) # <re.Match object; span=(0, 2), match='ab'>
小案例: 检查用户输入的手机号是否合法
import re
phone = input('请输入您的手机号码:')
if len(phone) == 11 and re.match(r'1[356789]\d{9}', phone) != 'None':
print('ok')
else:
print('手机号码不合法')