Python 介绍
Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的。
Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
现在 Python 是由一个核心开发团队在维护,Guido van Rossum 仍然占据着至关重要的作用,指导其进展。
- Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。
- Python 是交互式语言: 这意味着,您可以在一个 Python 提示符 >>> 后直接执行代码。
- Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。
- **Python 是初学者的语言:**Python 对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发
Python 应用
- 云计算:云计算最热的语言,典型的应用OpenStack
- WEB开发:许多优秀的 WEB 框架,许多大型网站是Python开发、YouTube、Dropbox、Douban……典型的Web框架包括Django
- 科学计算和人工智能:典型的图书馆NumPy、SciPy、Matplotlib、Enided图书馆、熊猫
- 系统操作和维护:操作和维护人员的基本语言
- 金融:定量交易、金融分析,在金融工程领域,Python 不仅使用最多,而且其重要性逐年增加。
- 图形 GUI:PyQT,WXPython,TkInter
Python 在一些公司的运用有:
- 谷歌:谷歌应用程序引擎,代码。openAI.com、 openAI 爬虫、openAI 广告和其他项目正在广泛使用 Python。
- CIA:美国中情局网站是用 Python 开发的。
- NASA:美国航天局广泛使用 Python 进行数据分析和计算。
- YouTube:世界上最大的视频网站 YouTube 是用 Python 开发的。
- Dropbox:美国最大的在线云存储网站,全部用 Python 实现,每天处理 10 亿的文件上传和下载。
- Instagram:美国最大的照片共享社交网站,每天有 3000 多万张照片被共享,所有这些都是用 Python 开发的。
- Facebook:大量的基本库是通过 Python 实现的
- Red Hat/Centos:世界上最流行的 Linux 发行版中的 Yum 包管理工具是用 Python 开发的
- Douban:几乎所有公司的业务都是通过 Python 开发的。
- 知乎:中国最大的 Q&A 社区,通过 Python 开发(国外 Quora)
- OpenAI:人工智能领域前沿技术研发,大量研发代码使用Python 实现的
除此之外,还有搜狐、金山、腾讯、盛大、网易、百度、阿里、淘宝、土豆、新浪、果壳等公司正在使用 Python 来完成各种任务。
Python 环境安装
见环境安装教程资料
Python代码执行
1.解释器执行
1.电脑的搜索中输入:python
2.找到IDLE(Python 3.8 32-bit)
3.打开python解释器 输入python语法执行
2.解释器执行
1.打开任意文件夹输入cmd 来到系统的控制台
2.输入python,打开python的解释器
3.输入python语法执行
3.编辑器执行
1.打开python编辑器创建项目环境
2.新建.py文件
3.输入python语法,执行项目
4.pycharm编辑器为例:




PyCharm的使用
-
PyCharm 下快捷键
shift + 回车 换行
ctrl + s 保存
ctrl + / 注释和取消注释
ctrl + d 可以复制当前行到下一行
ctrl + alt + L 可以将程序自动格式化成 符合PEP8 编码规范的格式
PyCharm 的调试
-
目标
让程序单步执行,同时可以观察程序的执行步骤和各个变量的值
-
步骤
- 设置断点
- 启动调试
- 单步执行并观察程序
Python 输入和输出
1.输出
Python 的输出函数
-
print() 函数
-
作用:
向终端输出文字信息,在控制台输出打印数据,能让用户看到
当有多个数据要输出时,中间用英文的逗号(,) 分隔开
-
调用格式
print(数据1, 数据2, 数据3, ..., sep=' ', end='\n')
-
说明
-
sep 关键字参数用来定义多个数据之间的分割符,默认用空格分隔
-
end 关键字参数用来定义数据输出完后用什么字符结束,默认是换行符(‘\n’),注意是每次调用
print()
后换行
-
-
在python中主要使用print实现输出,print是一个函数
在python中函数调用需要添加(),括号内是传给函数的参数
- 示例
print("hello world!") print("我们班有多少人": 12) print(1, 2, 3, 4) print(1, 2, 3, 4, sep=" ", end="\n") print(1, 2, 3, 4, sep="###", end="\n\n\n") print(1, 2, 3, 4)
2.输入
Python的基本输入函数 input 函数
-
作用
是个阻塞函数,让程序停下来,等待用户输入文字信息,返回用户输入文字的 字符串
-
调用格式
input("提示信息")
-
示例
name = input('请输入您的姓名:')
python中,通过input函数获取用户键盘输入
input函数的参数是字符串,它是屏幕提示语
str = input("请输入:")#程序到这里不会继续往下执行,等待用户输入完毕后继续执行
print ("你输入的内容是: ", str)
Python注释
在 Python 中,注释不会影响程序的执行,但是会使代码更易于阅读和理解。
Python 中的注释有单行注释和多行注释。
1.井号 (#)
# 这是一个注释print("Hello, World!")
多行注释用三个单引号 ‘’’ 或者三个双引号 “”" 将注释括起来,例如:
2.单引号(‘’')
'''这是多行注释,用三个单引号这是多行注释,用三个单引号 这是多行注释,用三个单引号'''
print("Hello, World!")
3.双引号(“”")
"""这是多行注释,用三个双引号这是多行注释,用三个双引号 这是多行注释,用三个双引号"""
print("Hello, World!")
注意:多行注释可以嵌套使用,但是单行注释不能嵌套使用。
Python变量
1.赋值语句
-
作用
变量是代数的思想,用来代替或缓存数据,可以让程序更加简洁
创建一个自定义名字的变量,此变量可以用于绑定数字类型或者表达式执行的结果,供后续使用
-
语法
变量名 = 数字类型 变量名 = 表达式 变量名1 = 变量名2 = 变量名3 = 数字类型 变量名1, 变量名2, 变量名3 = 数字类型1, 数字类型2, 数字类型3
-
示例
one_hundred = 99 + 1 a = b = c = 200 a, b = 100, 200 counter = 100 # 整型变量 miles = 1000.0 # 浮点型变量 name = "hqyj" # 字符串 print (counter) print (miles) print (name)
-
说明
- 第一次为变量赋值,python 会创建变量,同时绑定表达式执行的结果
- 第二次或者以后为变量赋值,会改变原有变量的绑定关系
- python 的变量没有类型,它绑定的对象才有类型
- 变量在使用之前,必须先进行赋值
- 变量赋值是一个自右向左的运算,将=右边表达式的计算结果,赋值给左边的变量
2.变量
变量是在python 内用赋值语句创建,用来绑定一个数据的有名对象
-
变量名
变量名必须是一个标识符
-
标识符的命名规则
-
第一个字母必须是英文字母[A-Z a-z]或下划线 [ _ ],所以数字不能开头
-
从第二个字母起(如果有),必须是英文字母、下划线、数字
[ A-Z、a-z、 0-9、 _ ]
变量名称约定
-
变量名区分大小写
-
-
示例
以下是合法的标识符
a a1 abc ABC a1b2c3d4 one_hundred count _a __ABC__ getNameAge get_name_age GetNameAge # 小驼峰 匈牙利命名法 大驼峰
python 编程语言中的关键字不能作为标识符
-
推荐采用的命名方法
- 变量名全部采用小写字母,如pythonstring
- 简短、有意义,如pystr
- 多个单词间用下划线分隔,如py_str
- 变量名用名词,函数名用谓词(动词+名词),如 phone / update_phone
- 类名采用驼峰形式,如MyClass
-
关键字(keywords)
- 计算机编程语言中保留的标识符称为关键字, 关键字不能当成变量名使用
关键字通常用于语法标识
- python中的部分关键字
False await else import pass None break except in raise True class finally is return and continue for lambda try as def from nonlocal while assert del global not with async elif if or yield
注意:
- 避免使用单个字母或不明确的缩写作为变量名,除非是在特定上下文中广泛使用的约定,如循环变量
i
。 - 合理使用命名空间:避免定义与Python内置函数或常用模块的名称相同的变量,以防止命名冲突。
- 模块级别的变量可以使用大写字母,表示为常量,例如
PI = 3.14159
。
- 示例
>>> a = 10 + 5 # 第一次为变量赋值是创建变量
>>> a
15
>>> a = 100 # 再次为变量赋值,会改变已经存在的变量.
-
课后练习
写一个程序 myprog.py # 1. 让用户输入用户名 # 2. 让用户输入密码 # 3. 打印 谁谁谁 的密码是 xxx
参考答案
name = input("请输入您的姓名: ") password = input("请输入您的密码: ") print(name, '的密码是:', password)
3. 变量类型
在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。
python中的数据类型
- 字符串 str
- 数字
- 整数 int
- 浮点数 float
- 布尔数 bool
- 容器
- 列表 list
- 元组 tuple
- 字典 dict
- 集合 set / 固定集合 frozenset
- 字节串 bytes / 字节数组 bytearray
基础类型(内置类型)
字符串
程序中,用来记录人类的文字信息的一种数据类型
- 创建字符串的字面值
## 用 英文的 ' 或 " 或 ''' 或 """ 开始或结束
## 此示例示意字符串的写法
print('同学们好')
print("同学们好")
print('''同学们好''')
print("""同学们好""")
-
说明
- 双引号的字符串的内部的单引号不算是结束符
- 单引号的字符串的内部的双引号不算是结束符
# I'm a teacher! print("I'm a teacher!") # 我有一只"狗" print('我有一只"狗"')
- 三引号字符串的内部可以包含单引号和双引号
# I'm a teacher! 我是"徐婧" print('''I'm a teacher! 我是"徐婧"''')
- 三引号字符串又称为所见即所得字符串, 每一次换行会转换成换行符 ‘\n’
# print("咏鹅\n鹅鹅鹅,\n曲项向天歌;\n白毛浮绿水,\n红掌拨清波。") # 等同于如下写法 print('''咏鹅 鹅鹅鹅, 曲项向天歌; 白毛浮绿水, 红掌拨清波。''')
-
思考
我是单引号',我是双引号", 我是三单引号''', 我是三双引"""
-
字符串的转义
字符串的字面值中,可以用反斜杠 \ 后加一个或多个字符串,代表一个单个的字符
\' 代表一个单引号 \" 代表一个双引号 \n 代表一个换行符 \\ 代表一个反斜杠
# 解决方法 print('我是单引号\',我是双引号\", 我是三单引号\'\'\', 我是三双引"""')
课后练习
# 练习打印 """ ''' " '*#
参考答案
print('""" \'\'\' " \'*#')
-
Python 中全部的转义字符串
转义序列 | 含义 | 注释 |
---|---|---|
\newline | 反斜杠加换行全被忽略 | |
\\ | 反斜杠 (\ ) | |
\' | 单引号 (' ) | |
\" | 双引号 (" ) | |
\a | ASCII 响铃 (BEL) | |
\b | ASCII 退格 (BS) | |
\f | ASCII 进纸 (FF) | |
\n | ASCII 换行 (LF) | |
\r | ASCII 回车 (CR) | |
\t | ASCII 水平制表 (TAB) | |
\v | ASCII 垂直制表 (VT) | |
\ooo | 八进制数 ooo 码位的字符 | (1,3) |
\xhh | 十六进制数 hh 码位的字符 | (2,3) |
-
课后练习:
# 写程序,打印如下文本内容 print("hello world") print(1,2,3,sep='\t')
参考答案
>>> print('print("hello world")') print("hello world") >>> >>> print("print(\"hello world\")") print("hello world") # 1 2 3
字符串运算
连接:+;* ; in / not in
-
字符串的基本运算
+ 号运算符, 用于拼接字符串(生成新的字符串)
+ 号的两侧都必须是字符串
'今天是' + '7月13日' # 生成 '今天是7月13日' s1 = '123' s2 = "456" s3 = s1 + s2 print(s1) # 123 print(s2) # 456 print(s3) # 123456 name = "华清" other_name = "远见" print('你好,'+name+',我是'+other_name) print(f'你好,{name},我是{other_name}')
-
相邻的两个或多个 字符串字面值 (引号标注的字符)会自动合并
x='Py' 'thon' print(x)#Python
-
字符串多次重复:* 运算, 用于生成重复的字符串
字符串只能和整数相乘,如 :
x=3*('a' + 'b') print(x)#ababab print('我想你了' * 100)
-
in / not in 运算
-
作用
in 用于序列,字符串,字典中,用于判断某个值是否存在于序列中,如果存在就返回True, 否则返回False
not in 的返回值与 in 相反
-
示例
>>> s = 'welcome to beijing!' >>> 'to' in s True >>> 'weimingze' in s False >>> 'beijing' not in s False >>> 'weimz' not in s True
-
索引 index
-
语法
字符串[整数表达式]
-
作用
用来获取字符串其中的一个字符
-
说明
正向索引: 字符串的正向索引是从0开始的,… 最后一个索引为 len(s)-1
反向索引: 字符串的反向索引是从 -1 开始的,-1 代表最后一个,… -len(s) 代表第一个
-
示例
>>> s = 'ABCDE' >>> s[1] B >>> s[1+2] D >>> s[-1] E
注: len(x) 函数可以求取一个字符串的长度
-
课后练习
写程序,输入一个字符, 打印字符串的如下内容 1. 打印这个字符串的第一个字符 2. 打印这个字符串的最后一个字符串 3. 如果这个字符串的长度是 奇数,则打印中间这个字符 用 len(x) 求字符串的长度
参考答案
s = input("请输入一段文字: ") print('第一个字符是:', s[0]) print('最后一个字符是:', s[-1]) if len(s) % 2 == 1: print('中间的字符是', s[len(s) // 2])
切片 slice
-
作用
从字符串序列中取出相应位置的元素,重新组成一个新的字符串
-
语法
字符串[(开始索引b):(结束索引e)(:(步长s))]
注: () 括起来的内容代表可以省略
-
说明
-
开始索引b是切片切下的开始位置
-
结束索引e 是切片的终止位置**(但不包含终止点)**
-
步长是切片取出数据后向后移动的方向和偏移量
- 没有步长,相当于步长为1(默认为1)
- 当步长为正数时,取正向切片
- 开始索引默认为0, 结束索引是最后一个元素的下一个索引
- 当步长为负数时,取反向切片
- 开始索引默认为-1, 结束索引是第一个元素的前一个索引
-
-
示例
# 01234 >>> s = 'ABCDE' >>> s[1:] # 'BCDE' >>> s[-2:] # 'DE' >>> s[1:4] # 'BCD' >>> s[:] # 'ABCDE' >>> s[:2] # 'AB' >>> s[1:1] # '' >>> s[4:2] # '' >>> s[::] # 等同于 s[::1] 'ABCDE' >>> s[::2] # 'ACE' >>> s[2::2] # 'CE' >>> s[-1::-2] # 'ECA' >>> s[::-1] # 'EDCBA' >>> x='huaqyj'[0:2:2] >>> print(x)
-
课后练习1
写一个程序,输入一个字符串,把字符串的第一个字符和最后一个字符去掉,打印处理后的字符串
-
课后练习2
输入一个字符串, 判断这个字符串是否是回文 上海自来水来自海上 ABCCBA 13531
字符串的格式化表达式
占位符
-
作用
生成具有一定格式的字符串
-
语法规则
格式化字符串 % 参数1 # 或者 格式化字符串 % (参数1, 参数2, 参数3)
-
占位符和类型码
占位符和类型码 | 说明 |
---|---|
%s | 转成字符串, 使用 str(x) 函数转换(常用) |
%d | 转成 十进制的整数(常用) |
%o | 转成 八进制的整数 |
%x,%X | 转成 十六进制的整数 |
%e,%E | 转成 指数格式的浮点数 |
%f,%F | 转成小数格式的浮点数(常用) |
%g,%G | 转成指数格式或小数格式的浮点数 |
%% | 转成一个% |
补充:%m,nf,m是指总宽度,默认右对齐,加个 - 表示左对齐,n 是指保留的小数点位数
- 示例1
>>> fmt = """
甲方:_____%s_____
乙方:_____%s_____
....... 金额:_%d__
"""
>>> s = fmt % ("小王", '华清', 10000)
b = fmt % ("小红", '华清', 10000)
>>> print(s)
甲方:_____小王_____
乙方:_____华清_____
....... 金额:_10000__
- 示例2
>>> "+++%d+++" % 999 # 返回 '+++999+++'
>>> "+++%s+++" % 3.14 #'+++3.14+++'
>>> "+++%s+++" % "weimz" #'+++weimz+++'
>>> "+++%d+++" % 3.1415 # '+++3+++'
>>> "+++%o+++" % 13
'+++15+++'
>>> "+++%x+++" % 13
'+++d+++'
>>> "+++%e+++" % 3.1415
'+++3.141500e+00+++'
>>> "+++%f+++" % 3.1415
'+++3.141500+++'
>>> "+++%g+++" % 3.1415
'+++3.1415+++'
>>> "+++%g+++" % 3141523274812374281342374324.23748123742183472
'+++3.14152e+27+++'
f-string
f-string 是 python3.6 之后版本添加的,称之为字面量格式化字符串,是新的格式化字符串的语法。
之前我们习惯用百分号 (%):
实例
name = 'hqyj'
print('Hello %s' % name)#Hello hqyj
f-string 格式化字符串以 f 开头,后面跟着字符串,字符串中的表达式用大括号 {} 包起来,它会将变量或表达式计算后的值替换进去
用了这种方式明显更简单了,不用再去判断使用 %s,还是 %d。
x = 1
y = 2.3
print(f'{x+1}') #2
x = 1
print(f'{x+1=}') #x+1=2
d = 12
print(f'abc{d}') # 其中的{}中为变量或表达式
# 可以使用:对变量进一步格式化
pi = 3.1415
print(f'{s:.2f}') # 3.14
字符串的常用函数API
-
方法的调用语法
对象.方法名(参数)
-
示例:
>>> "abc".isalpha() x = "abc" x.isalpha() True >>> "123".isalpha() False >>> "123".isdigit() True
. 是"的"的意思
Python 的字符串常用内建函数如下:
序号 | 方法及描述 |
---|---|
1 | capitalize()将字符串的第一个字符转换为大写 |
2 | center(width, fillchar)返回一个指定的宽度 width 居中的字符串,fillchar 为填充的字符,默认为空格。 |
3 | count(str, beg= 0,end=len(string))返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数 |
4 | endswith(suffix, beg=0, end=len(string))检查字符串是否以 suffix 结束,如果 beg 或者 end 指定则检查指定的范围内是否以 suffix 结束,如果是,返回 True,否则返回 False。 |
5 | expandtabs(tabsize=8)把字符串 string 中的 \t 符号转为空格,tab 符号默认的空格数是 8 。 |
6 | find(str, beg=0, end=len(string))检测 str 是否包含在字符串中,如果指定范围 beg 和 end ,则检查是否包含在指定范围内,如果包含返回开始的索引值,否则返回-1 |
7 | index(str, beg=0, end=len(string))跟find()方法一样,只不过如果str不在字符串中会报一个异常。 |
8 | isalnum()非空字符串 中没有符号 就返回True |
9 | isalpha() 判断字符串是否是英文字符 是就返回True |
10 | isdigit()如果字符串只包含数字则返回 True 否则返回 False |
11 | islower() 用于检测字符串中的所有字符是否都是小写字母,字符都是小写,则返回 True,否则返回 False |
12 | isnumeric()如果字符串中只包含数字字符,则返回 True,否则返回 False |
13 | isspace()如果字符串中只包含空白,则返回 True,否则返回 False. |
14 | istitle()如果字符串是标题化的(见 title())则返回 True,否则返回 False |
15 | isupper()用于检测字符串中的所有字符是否都是大写字母,并且都是大写,则返回 True,否则返回 False |
16 | join(seq)以指定字符串作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串 |
17 | len(string)返回字符串长度 |
18 | ljust(width, fillchar])返回一个原字符串左对齐,并使用 fillchar 填充至长度 width 的新字符串,fillchar 默认为空格。 |
19 | lower()转换字符串中所有大写字符为小写. |
20 | lstrip()截掉字符串左边的空格,\t,\r,\n或指定字符。 |
21 | maketrans()创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。 |
22 | max(str)返回字符串 str 中最大的字母。 |
23 | min(str)返回字符串 str 中最小的字母。 |
24 | replace(old, new , max)把 将字符串中的 old 替换成 new,如果 max 指定,则替换不超过 max 次。 |
25 | rfind(str, beg=0,end=len(string))类似于 find()函数,不过是从右边开始查找. |
26 | rindex( str, beg=0, end=len(string))类似于 index(),不过是从右边开始. |
27 | rjust(width, fillchar)返回一个原字符串右对齐,并使用fillchar(默认空格)填充至长度 width 的新字符串 |
38 | rstrip()删除字符串末尾的空格\t,\r,\n或指定字符。 |
29 | split(sep=“”, maxsplit=string.count(str))以 sep为分隔符截取字符串,如果 maxsplit有指定值,则仅截取 maxsplit+1 个子字符串 |
30 | splitlines(keepends)按照行(‘\r’, ‘\r\n’, \n’)分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。 |
31 | startswith(substr, beg=0,end=len(string))检查字符串是否是以指定子字符串 substr 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查。 |
32 | strip(chars)在字符串上执行 lstrip()和 rstrip() |
33 | swapcase()将字符串中大写转换为小写,小写转换为大写 |
34 | title()返回"标题化"的字符串,就是说所有单词都是以大写开始,其余字母均为小写 |
35 | upper()转换字符串中的小写字母为大写 |
36 | zfill (width) 在字符串左侧填充指定数量的零,确保整个字符串达到指定长度 |
详见文档: https://docs.python.org/zh-cn/3/library/stdtypes.html#string-methods
1. str.lower(): 将字符串转换为小写
text = "Hello, World!"
print(text.lower()) # 输出: hello, world!
2. str.upper(): 将字符串转换为大写
text = "Hello, World!"
print(text.upper()) # 输出: HELLO, WORLD!
3. str.strip(): 移除字符串两端的空白字符
text = " Hello, World! "
print(text.strip()) # 输出: Hello, World!
4. str.split(): 将字符串拆分为列表
text = "Hello, World!"
print(text.split()) # 输出: ['Hello,', 'World!']
text = "Hello,World!"
print(text.split(',')) # 输出: ['Hello', 'World!']
5. str.join(): 将列表中的字符串连接为一个字符串
words = ['Hello', 'World']
print(" ".join(words)) # 输出: Hello World
words = ['apple', 'banana', 'cherry']
print(", ".join(words)) # 输出: apple, banana, cherry
6. str.replace(): 替换字符串中的子字符串
text = "Hello, World!"
print(text.replace("World", "Python")) # 输出: Hello, Python!
7. str.find(): 查找子字符串,返回第一次出现的位置
text = "Hello, World!"
print(text.find("World")) # 输出: 7
print(text.find("Python")) # 输出: -1(如果未找到则返回 -1)
8. str.startswith(): 检查字符串是否以指定子字符串开头
text = "Hello, World!"
print(text.startswith("Hello")) # 输出: True
print(text.startswith("World")) # 输出: False
9. str.endswith(): 检查字符串是否以指定子字符串结尾
text = "Hello, World!"
print(text.endswith("World!")) # 输出: True
print(text.endswith("Hello")) # 输出: False
10. str.isdigit(): 检查字符串是否只包含数字字符
text1 = "12345"
text2 = "12345abc"
print(text1.isdigit()) # 输出: True
print(text2.isdigit()) # 输出: False
11. str.isalpha(): 检查字符串是否只包含字母字符
text1 = "Hello"
text2 = "Hello123"
print(text1.isalpha()) # 输出: True
print(text2.isalpha()) # 输出: False
12. str.isalnum(): 检查字符串是否只包含字母和数字字符
text1 = "Hello123"
text2 = "Hello 123"
print(text1.isalnum()) # 输出: True
print(text2.isalnum()) # 输出: False
13. str.title(): 将字符串中的每个单词的首字母转换为大写
text = "hello, world!"
print(text.title()) # 输出: Hello, World!
14. str.capitalize(): 将字符串的首字母转换为大写
text = "hello, world!"
print(text.capitalize()) # 输出: Hello, world!
15. str.count(): 计算子字符串在字符串中出现的次数
text = "Hello, World! Hello, Python!"
print(text.count("Hello")) # 输出: 2
print(text.count("Python")) # 输出: 1
16. str.format(): 格式化字符串
name = "John"
age = 30
print("My name is {} and I am {} years old.".format(name, age))
# 输出: My name is John and I am 30 years old.
print(f"My name is {name} and I am {age} years old.")
# 输出: My name is John and I am 30 years old. (使用 f-string)
其他字符串
- 字节串(bytes):表示二进制数据,以字节为单位,例如b’hello’。
- 空值(NoneType):表示一个特殊的空值,通常用于表示缺失或未定义的值。
使用type函数可以获取一个变量或值的类型。
x = 123
>>> type(x)
<class 'int'>
# 创建一个字节串
byte_string = b'hello'
print(byte_string) # 输出: b'hello'
print(type(byte_string)) # 输出: <class 'bytes'>
print(len(byte_string)) # 输出: 5
# 变量未初始化,赋值为 None
value = None
print(value) # 输出: None
print(type(value)) # 输出: <class 'NoneType'>
数字
- Python 中的基本的数字类型
- 整数 int
- 浮点数(小数) float
- 布尔类型数 bool
整数 int
整数的字面值
## 十进制的写法
100 0 -5
## 二进制的写法 0b 开头 后跟 0~1
0b1101
## 八进制的写法 0o开头 后跟 0~7
0o777 等于 0b111111111 等于 511
## 十六进制的写法 0x 开头 后跟 0~9, a-f, A-F
0xA1B2C3D4
浮点数(小数) float
浮点数的字面值
## 小数写法
3.14 0.14 .14 3.0 3. 0.0
## 科学计数法
6.18E-1 # 等同于 0.618
2.9979E8 # 等同于 299790000.0
布尔类型的数 bool
- True 真(表示行,好,成立) 值为1
- False 假(表示不行,不好,不成立) 值为0
引用类型(复合类型)
- 列表(list):可变序列,用于存储一组值,可以包含不同类型的元素。
- 元组(tuple):不可变序列,用于存储一组值,元素不能被修改。
- 字典(dict):键值对映射,用于存储关联性数据,由键和对应的值组成。
- 集合(set):无序集合,用于存储唯一的元素,不允许重复。
- 枚举类型(Enum):本质上是一个类,它是标准库中的
enum
模块提供的一个功能,用于创建有限的、命名的枚举类型 - 自定义类(class):创建自定义类来表示复杂的数据结构,具有自定义属性和方法。
按照是否可以修改划分:
- 不可变数据:Number(数字)、String(字符串)、Tuple(元组)
- 可变数据:List(列表)、Dictionary(字典)、Set(集合)
4. del删除变量
可以通过使用del语句删除单个或多个对象的引用
del var
del var_a, var_b
x=100
del x
print(x)#报错name 'x' is not defined
Python 数字操作
Python 数字数据类型用于存储数值。
数据类型是不允许改变的,这就意味着如果改变数字数据类型的值,将重新分配内存空间。
1.Python 数字类型转换
有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。
- int(x) 将x转换为十进制整数
- float(x) 将x转换到一个浮点数。
- **bin(x)**将x转换为二进制
- **oct(x)**将x转换为八进制
- **hex(x)**将x转换为十六进制
- complex(x) 将x转换到一个复数,实数部分为 x,虚数部分为 0。
- complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。x 和 y 是数字.
- **bool(x)**将 x 转化为布尔值
print(int(20.5))#20
print(float(20))#20.0
print(bin(3))#0b11
print(oct(20))#0o24
print(hex(29))#0x1d
print(complex(29))#(29+0j)
print(complex(10,3))#(10+3j)
数据类型转换相关的函数
函数 | 说明 |
---|---|
str(x) | 把传入的x 转化成字符串并返回 |
int(x) | 把 x 转化为整数并返回 |
float(x) | 把 x 转化为浮点数并返回 |
bool(x) | 把 x 转化为布尔类型的数并返回 |
-
示例:
>>> age = input('请输入年龄: ') # 输入 35 >>> int(age) 35 >>> int("35") 35 >>> int(3.14) 3 >>> int('3.14') # 报错 >>> f = 3.14 >>> str(f) '3.14' >>> int(f) 3 >>> bool(f) True
-
python 中假值对象
None # 空值对象 False # 布尔类型的假值 0 # 整数的0 0.0 # 浮点数的0 '' # 字符串的空字符串 [] # 空列表 {} # 空字典 ...
-
课后练习
写程序,输入您的年龄, 打印出去年你几岁,明年你几岁 用 str(x) , int(x), float(x), bool(x)
参考答案
age = int(input('请输入您的年龄: ')) print('去年您', age-1, '岁') print('明年您', age+1, '岁')
2.Python 运算符
a). 算术运算符
+
:加法-
:减法*
:乘法/
:除法%
:取模(取余数)**
:幂运算//
:整除(向下取整数部分)
除法 / 总是返回一个浮点数
整除// 得到的并不一定是整数类型的数,它与分母分子的数据类型有关系。
不同类型的数混合运算时会将整数转换为浮点数:
print(10+20.3)#加法运算:30.3
print(17 / 3) # 整数除法返回浮点型:5.666666666666667
print(17 // 3) # 整数除法返回向下取整后的结果:5
print(17.0 // 3) # 整数除法返回向下取整后的结果:5.0
print(17 // 3.0) # 整数除法返回向下取整后的结果:5.0
print(17 % 3) # %操作符返回除法的余数:2
print(2**3) #幂运算2的3次方: 8
课后练习1
超市的西瓜 13 元一个, 问 你拿100 元可以买几个西瓜,剩余 几元
课后练习2
现在是 18:02:31 秒 请问现在距离 凌晨 0:0:0 过了多少秒?
写程序打印出来
课后练习3:
已知从凌晨 0:0:0 到现在已经过了 63320 秒, 请问现在是 几时几分几秒?
用地板除法和求余数实现
b). 比较运算符
==
:等于!=
:不等于<
:小于>
:大于<=
:小于等于>=
:大于等于
比较运算符的运算结果为布尔值,比较运算符通常返回布尔类型的数, True, False
print(10==10.0)#只比较值是否相等:True
print(3.14!=3.1415)#True
print(255>170)#True
print(255<170)#False
print(255>=255)#True
print(255<=255)#True
x=15
print(5<x<20)#注意:两个符号同时参与比较 相当于 (5 < x) and (x < 20)
x=100
y=200
z=-10
a=True
print(a is not x is not y < z)#a和x判定 然后和y判定 然后和z判定
# False
在Python中,is not
是一种身份运算符,用于判断两个对象是否不是同一个对象。它与 is
运算符相对,后者用于判断两个对象是否是同一个对象。
具体来说:
a is b
返回True
当且仅当a
和b
是同一个对象(即它们的身份相同)。a is not b
返回True
当且仅当a
和b
不是同一个对象(即它们的身份不同)
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a is b) # True,因为 a 和 b 是同一个对象
print(a is c) # False,因为 a 和 c 是不同的对象,即使它们的内容相同
print(a is not c) # True,因为 a 和 c 不是同一个对象
c). 逻辑运算符
and
:与(逻辑与)or
:或(逻辑或)not
:非(逻辑非)
A and B表达式的结果: 如果A表达式的布尔判定为真则B表达式的结果作为整个表达式的结果,如果A表达式的布尔判定为假则A表达式的结果作为整个表达式的结果
注意: 如果A判定为假 B将不会执行
or和not跟and一样
-
and 与运算
两者(两个元素同时为真,结果才为真)
- 语法
x and y # x, y代表表达式
- 示例
>>> 3 + 4 > 5 and 6 + 7 > 100 False
- 真值表
x的值 y的值 x and y的值 True True True True False False False True False False False False 优先返回假值对象, 如果x 为假值,返回x, 否则返回y
-
or 或运算
两者(两个元素只要有一个为真,结果就为真)
x or y # x, y代表表达式
-
真值表
x的值 y的值 x or y的值 True True True True False True False True True False False False 优先返回真值对象, 如果x 为真值,返回x, 否则返回y
-
not 非运算
not 运算符是一元运算符
作用
将表达式的结果取 非 操作
语法
not 表达式
示例
not True # False not False # True not 3.14 # False not '' # True not 1 + 2 # False
-
示例
>>> True and True # True >>> True and False # False >>> False and True # False >>> False and False # False >>> True or True # True >>> True or False # Ture >>> False or True # Ture >>> False or False # False >>> not False # True >>> not True # Flase >>> 3.14 and 5 # 5 >>> 0.0 and 5 # 0.0 >>> 3.14 or 5 # 3.14 >>> 0.0 or 0 # 0 >>> not 3.14 # False >>> not 0.0 # True
-
问题
写一个程序,输入一个整数, 判断这个整数是奇数还是偶数 奇数: 1 3 5 7 9 偶数: 2 4 6 8 10 x % 2 == 1 结果为True,x 一定是奇数 x % 2 == 1 结果为False,x 一定是偶数
d). 位运算符
Python中的位运算符主要用于处理整数类型的二进制位操作。以下是Python中的6种主要位运算符:
&
:按位与|
:按位或^
:按位异或~
:按位取反<<
:左移位>>
:右移位
-
按位与(&):
- 表达式:
a & b
- 功能:对于每一位,如果a和b的相应位都是1,则结果位为1,否则为0。
# 示例:计算两个二进制数的按位与 a = 0b1011 # 二进制表示的11 b = 0b1101 # 二进制表示的13 result_and = a & b # 计算两者之间的按位与 print(bin(result_and)) # 输出:0b1001 (十进制为9)
- 表达式:
-
按位或(|):
- 表达式:
a | b
- 功能:对于每一位,只要a和b中至少有一位是1,则结果位为1,否则为0。
# 示例:计算两个二进制数的按位或 a = 0b1011 b = 0b1101 result_or = a | b # 计算两者之间的按位或 print(bin(result_or)) # 输出:0b1111 (十进制为15)
- 表达式:
-
按位异或(^):
- 表达式:
a ^ b
- 功能:对于每一位,如果a和b的相应位不同(一个为1,另一个为0),则结果位为1,否则为0。
# 示例:计算两个二进制数的按位异或 a = 0b1011 b = 0b1101 result_xor = a ^ b # 计算两者之间的按位异或 print(bin(result_xor)) # 输出:0b110 (十进制为6)
- 表达式:
-
按位取反(~):
- 表达式:
~a
- 功能:对操作数a的每一个二进制位进行取反,即将1变为0,0变为1。
# 示例:计算一个二进制数的按位取反 a = 0b1011 result_not = ~a # 计算a的按位取反 print(bin(result_not)) # 输出:-0b1100
- 表达式:
-
左移运算符(<<):
- 表达式:
a << b
- 功能:将a的二进制表示向左移动b位,左边移出的部分会被丢弃,右边空出的位置补零。相当于乘以2^n次方
# 示例:将一个二进制数向左移动两位 a = 0b1011 result_left_shift = a << 2 # 将a向左移动两位 print(bin(result_left_shift)) # 输出:0b101100 (十进制为44)
- 表达式:
-
右移运算符(>>):
- 表达式:
a >> b
- 功能:将a的二进制表示向右移动b位,对于无符号整数,右边移出的部分会被丢弃,左边空出的位置补零(通常补0);对于有符号整数,右移时取决于具体实现,可能是算术右移(符号位扩展)或者逻辑右移(补0)。同理,相当于除以2^n
- 表达式:
# 示例:将一个有符号二进制数向右移动一位
a = -0b1000 # 十进制为-8
result_right_shift = a >> 1 # 将a向右移动一位
print(bin(result_right_shift)) # 输出:-0b100 (十进制为-4)
# 对于无符号数的例子
unsigned_a = 0b1000
unsigned_result_right_shift = unsigned_a >> 1
print(bin(unsigned_result_right_shift)) # 输出:0b100 (十进制为4)
e). 赋值运算符
-
=
:赋值 -
+=
:加法赋值 -
-=
:减法赋值 -
*=
:乘法赋值 -
/=
:除法赋值 -
%=
:取余赋值 -
**=
:幂运算赋值 -
//=
:整除赋值注意:
没有 a++、 a-- 这种自增自减运算符;
x=100
x%=3
print(x)#1
f)运算符的优先级
1 + 3 * 3 ** 2 + 4 // 2
1 + 3 * 9 + 4 // 2
1 + 27 + 4 // 2
1 + 27 + 2
28 + 2
30
- 运算符优先级表
运算符 | 描述 |
---|---|
(expressions...) ,[expressions...] , {key: value...} , {expressions...} | 绑定或加圆括号的表达式,列表显示,字典显示,集合显示 |
x[index] , x[index:index] , x(arguments...) , x.attribute | 抽取,切片,调用,属性引用 |
** | 乘方 |
+x , -x , ~x | 正,负,按位非 NOT |
* , / , // , % | 乘,除,整除,取余 |
+ , - | 加和减 |
<< , >> | 移位 |
& | 按位与 AND |
^ | 按位异或 XOR |
` | ` |
in , not in , is , is not , < , <= , > , >= , != , == | 比较运算,包括成员检测和标识号检测 |
not x | 布尔逻辑非 NOT |
and | 布尔逻辑与 AND |
or | 布尔逻辑或 OR |
if – else | 条件表达式 |
lambda | lambda 表达式 |
:= | 赋值表达式 |
条件语句
1. 整体
-
语法
if 条件表达式1: 语句块1 elif 条件表达式2: 语句块2 elif 条件表达式3: 语句块3 ... elif 条件表达式n: 语句块n else: 语句块(其他)
2. if
if condition:
# 当条件为真时执行这里的代码,否则不执行这里
year=1993
if year%4==0:
print("year能被4整除")
3. if-else
if condition:
# 当条件为真时执行这里的代码
else:
# 如果前面的条件都为假,执行这里的代码
year=1993
if year%4==0:
print("year能被4整除")
else:
print("year不能被4,400整除")
4. if-elif-else
if condition:
# 当条件为真时执行这里的代码
elif another_condition:
# 当上面条件为假,而这个条件为真时执行这里的代码
else:
# 如果前面的条件都为假,执行这里的代码
year=1992
if year%4==0:
print("year能被4整除")
elif year%400==0:
print("year能被400整除")
else:
print("year不能被4,400整除")
-
课后练习1
写一个程序,输入一个整数,用程序判断这个整数是正数,负数,还是零
-
课后练习2
写一个程序, 06_input_score.py, 输入一个学生的成绩,如果成绩在 60~100 之间提示"及格", 否则提示不及格
-
课后练习3
写一个程序, 07_input_score.py, 输入一个学生的成绩, 如果成绩在 [0,60) 提示"不及格" 如果成绩在 [60,80) 提示"及格" 如果成绩在 [80,90) 提示"良好" 如果成绩在 [90,100] 提示"优秀" 如果是其他值,则提示"您的输入有误"
[ ] 表示包含 () 表示不包含
-
if 语句也是语句,他可以嵌套到其他的复合语句中
if xxxx: if yyyy > 0: print('.....') else: print("fjdsfdf") else: print("hello")
5. 条件表达式
Python 中的三元表达式(或称条件表达式)的语法规则如下:
<表达式1> if <条件> else <表达式2>
语法解释:
<条件>
:要判断的条件表达式,通常是一个布尔表达式(例如a > b
)。<表达式1>
:当条件为True
时返回的值或执行的表达式。<表达式2>
:当条件为False
时返回的值或执行的表达式。
示例:
x = 5
y = 10
# 使用三元表达式判断并赋值
result = "x is greater" if x > y else "y is greater"
print(result) # 输出: "y is greater"
if x > y:
result = "x is greater"
else:
result = "y is greater"
循环语句
while 语句
-
作用
根据一定的条件,重复的执行某个语句块
-
语法
while 真值表达式: 语句块1 (*此部分可能会重复执行) else: 语句块2
-
说明
- else 子句可以省略
- else 子句 当且仅当 真值表达式为假Flase的时候 会执行 else 里的语句块2
- 如果 此 while 是因为 调用 break 语句而终止循环。则 else 子句里的语句不会执行
-
示例1
while 1 < 2: print("hello world")
再终端界面下 ctrl + c 可以终止正在执行的程序(进程)
-
示例2
# 打印 5 行 "hello world" i = 0 while i < 5: print("hello world") i = i + 1 # 也可写成 i += 1 else: print("while 语句已经结束!")
-
课后练习1
写一个程序,输入一个整数,写程序打印如下 n 行文字 如: 请输入: 10 这是第 1 行 这是第 2 行 这是第 3 行 ... 这是第 10 行
-
课后练习2
写一个程序 打印1~20 的整数, 打印在 1 行内 每个数字之间用一个空格分隔开 1 2 3 4 5 ... 19 20 提示: print(x, end=' ')
语句嵌套
-
while 语句也是语句, 和其他的语句一样,可以嵌套到其他的任何复合语句中。外层控制行,内层控制列。
-
while 语句嵌套示意:
while 真值表达式: ... while 真值表达式2: ... else: ... ...... else: ...
示例
写一个程序 打印1~20 的整数, 打印在 1 行内 每个数字之间用一个空格分隔开 1 2 3 4 5 ... 19 20 打印 10 行 1 2 3 4 5 ... 19 20 1 2 3 4 5 ... 19 20 1 2 3 4 5 ... 19 20 1 2 3 4 5 ... 19 20 1 2 3 4 5 ... 19 20 .... 1 2 3 4 5 ... 19 20
-
课后练习:
写一个程序 打印1~20 的整数, 打印在 1 行内 每个数字之间用一个空格分隔开 1 2 3 4 5 ... 19 20 以上输出打印 10 行
-
课后练习1
写程序,输入一个整数n , 代表结束的整数, 计算 1 + 2 + 3 + 4 + ..... + n 的和 请输入: 100 5050 # 提示: he = 0 # 用一个变量来记录这个和
-
课后练习2
打印 1~ 20 的整数, 每行打印 5 个, 打印 四行, 如: 1 2 3 4 5 6 7 8 9 10 ... 16 17 18 19 20 # 提示: print() 换行
-
课后练习3
已知, 局域网的IP 都是: 192.168.0.xxx 写程序,生成 从 192.168.0.1 ~ 192.168.0.254 区间的 254 个 IP 地址
-
课后练习4
写一个程序,输入三行文字, 按最长的一行, 打印如下图形方框 请输入: hello 请输入: welcome to beijing 请输入: aaaaaaa 打印: +--------------------+ | hello | | welcome to beijing | | aaaaaaa | +--------------------+ 提示: str.center(width)
参考答案
# 写一个程序,输入三行文字, 按最长的一行, 打印如下图形方框 # 请输入: hello # 请输入: welcome to beijing # 请输入: aaaaaaa # 打印: # +--------------------+ # | hello | # | welcome to beijing | # | aaaaaaa | # +--------------------+ # 提示: str.center(width) s1 = input("请输入:") # ctrl + d 可以复制当前行 s2 = input("请输入:") s3 = input("请输入:")
break 语句
-
作用
用于循环语句(while, for语句)中, 当break 执行是,她会终止包含他的当前循环。
-
语法
break
-
说明
- break 语句只能用在 while 语句或for语句的内部。
- break 语句通常和 if 语句组合使用。
- 当break 语句执行后,此循环语句break 之后的所有语句都不会执行(else 子句里的语句也不执行)
- break 语句只能终止包含他的当前循环,当有循环嵌套时,只能跳出离他最近的一个循环
-
示例
i = 1 while i <= 5: print('i=', i) if i == 2 break i += 1 else: print('循环结束: i=', i)
死循环
death loop
- 死循环是指循环条件一直成立的循环
- 死循环通常使用 break 语句来终止循环
- 死循环的 else 子句中的语句永远不会执行
写法
while True:
语句块
死循环通常用户循环次数无法确定的循环
-
课后练习1:
写程序, 任意输入一些正整数, 当输入负数时结束输入,当输入完成后,打印您输入的这些正整数的和 如: 请输入: 1 请输入: 2 请输入: 3 请输入: 4 请输入: -1 您刚才输入的正整数之和是: 10
for 语句
-
作用
- 用来遍历可迭代对象的数据元素
遍历是指经历且只经历一遍
可迭代对象是指能够依次获取数据元素的对象
可迭代对象
- 字符串
- ---- 以下后面才讲----
- 列表 list
- 字典 dict
- …
-
语法
for 变量列表 in 可迭代对象: 语句块1 else: 语句块2
-
语法说明
- else 子句可以省略
- else 子句的语句块2 只有在 可迭代对象不再能提供数据的时候才会执行
- 因为 语句块1 部分调用break 而终止循环式,else 子句部分不会执行。
-
示例
s = 'ABCDE' for ch in s: print('ch=', ch) else: print("遍历结束")
-
课后练习1
写一个程序,输入一个任意长度的字符串,用for 语句找出这个字符串中有几个英文的等号(=) 注: 不允许使用 str.count 方法 如: 请输入: a = b = c = 100 结果: 3
range 函数
-
作用
用来生成一个能够得到一系列整数的可迭代对象(也叫整数序列生成器)
-
调用格式
range(stop) # stop 停止整数 range(start, stop) # start 开始整数 range(start, stop, step) # step 步长
range 函数调用会生成从 start 开始,到 stop 结束(不包含stop) 的一系列整数,整数的间隔 step
start 默认值为0, step 默认值为1
-
示意
range(4) # 生成 0 1 2 3 range(3, 6) # 生成 3 4 5 range(1, 10, 2) # 生成 1 3 5 7 9 range(5, 0, -2) # 生成 5 3 1
-
示例
>>> for x in range(4): ... print(x) ... 0 1 2 3 >>> for x in range(3, 6): ... print(x) ... 3 4 5 >>> for x in range(1, 10, 2): ... print(x) ... 1 3 5 7 9 >>> for x in range(5, 0, -2): ... print(x) ... 5 3 1
-
课后练习1
用 for 语句 打印 1~20 的整数,打印在一行内 1 2 3 4 .... 19 20
-
课后练习2
写程序,计算 1 + 3 + 5 + 7 + ..... + 97 + 99 的和 分别用 for 循环和 while 实现。
continue 语句
-
作用
用于循环语句(while 语句和for语句)中, 不再执行本次循环内 continue 之后的语句,开始一次新的循环
-
语法
continue
-
说明
- 在for 语句中, 执行continue 语句,for语句将会从可迭代对象向中获取下一个元素绑定变量后再次进行循环
- 在while 中,执行continue 语句, 将会直接跳转到while 语句的真值表达式处,重新判断循环条件。
-
示例1
for x in range(5): if x % 2 == 0: continue print(x) # 1 3
-
示例2
x = 0 while x < 5: print(x) x += 1
-
课后练习3
假设一个用户信息如下: 用户名是:root 密码是: 123456 写一个身份验证的程序,让用户输入用户名和密码登录, 用户名和密码全部匹配,提示登录成功。 否则继续,最多尝试3次。3次不匹配以后提示登录失败.
pass 语句
pass是空语句,是为了保持程序结构的完整性。
pass 不做任何事情,一般用做占位语句
for x in range(10):
if x == 7:
pass
else:
print(x)
补充知识点
表达式和语句的概念
-
表达式
是由数字,字符串(文字), 运算符,函数调用等组成,通常用于计算并得到一个结果
表达式是语文中的字或短语
-
语句
语句是计算机执行程序的最小单位
- 示例
a = 100 # 赋值语句 print(a) # 表达式语句 del a # del 语句
表达式和语句的区别:
表达式 (Expression)
- 定义:表达式是一个可以求值的代码片段,它会返回一个值。
- 作用:用来计算一个值。
- 举例
- 数学运算:2 + 3
是一个表达式,求值结果是
5`。 - 函数调用:
len("hello")
是一个表达式,求值结果是5
。 - 变量引用:
x
是一个表达式,返回变量x
的值。 - 复合表达式:
x + y * z
是一个表达式,返回计算结果。
- 数学运算:2 + 3
语句 (Statement)
-
定义:语句是完整的执行单元,它执行某种操作,但不一定返回值。
-
作用:用来执行某种操作。
-
举例
-
赋值语句:
x = 5
是一个语句,它给变量x
赋值,但不返回任何值。 -
控制流语句:
if x > 0: print("x is positive")
-
函数定义:定义一个函数也是一个语句。
def greet(): print("Hello, world!")
-
复合语句:包含多个子语句。
for i in range(5): print(i)
-
-
函数调用是表达式
学过的函数
input(‘xxxx’) 返回字符串
print(“xxxx”) 返回 None
函数调用语法规则
函数名(传入的参数)
None 是表示空值的一个对象
容器
python 中默认有4种容器
- 列表list
- 字典 dict
- 集合 set
- 元组 tuple
容器都是可迭代对象, 可以用for 语句来遍历容器
for x in [1, 2, 3]:
print(x)
for y in (1, 2, 3):
print(y)
Python列表(list)
Python 支持多种复合数据类型,可将不同值组合在一起。最常用的列表 ,是用方括号标注,逗号分隔的一组值。列表可以包含不同类型的元素,但一般情况下,各个元素的类型相同
- 列表是一种可以存储任意个各种类型的序列容器
- 列表内的数据有先后顺序关系
- 列表是可变的容器
1.列表的创建
-
创建列表的字面值
>>> L = [] # 创建一个空的列表 >>> L = ['北京', '上海', '广州', '西安'] # 创建一个含有4个字符串的列表 >>> L = [1, 'Two', 3.14, True, False, None] >>> L = [1, 2, [3.1, 3.2], 4] # 含有四个元素的列表,第三个元素是列表 >>> L2 = [ ['姓名','语文成绩','数学成绩'], ['小王', 90, 100], ['牛犇', 59, 26] ]
注: python 中的 (), [], {} 和 三引号字符串都要成对出现, 可以换行
-
创建列表的构造函数 list
list() # 创建一个空的列表,等同于 [] list(可迭代对象) # 用可迭代对象创建一个列表
示例
L = list() # L = [] L = list("ABC") # L = ['A', 'B', 'C'] L = list(range(5)) # L = [0, 1, 2, 3, 4]
-
列表的运算
列表list同字符串str都是序列, 他们的运算规则基本相同
-
+ 用于拼接列表
>>> [1, 2, 3] + [4, 5, 6] # [1, 2, 3, 4, 5, 6]
-
+= 追加
语法
列表 += 可迭代对象
>>> L = [1, 2, 3] >>> L += [4, 5] # L = [1, 2, 3, 4, 5] >>> L = [1, 2, 3] >>> L += "ABC" # L = [1, 2, 3, 'A', 'B', 'C'] >>> L += range(2)
-
* 用于生产重复的列表
>>> [1, 2] * 3 # [1, 2, 1, 2, 1, 2] >>> L = [5, 6] >>> L *= 3 # L = [5, 6, 5, 6, 5, 6]
-
== != 用于比较
>>> [1, 2, 3] == [1, 2, 3] # True >>> [1, 2, 3] != [3, 2, 1] # True
-
in /not in 用于判断一个数据元素是否在列表中
>>> "hello" in [1, "hello", 'world'] True >>> '红楼梦' in ['三国演义', '西游记'] False
-
2.访问列表中的值
2.1 索引
列表[整数表达式]
L = [1, 2, 3, 4, 5, 6]
print(L[0]) # 1
print(L[-1]) # 6
与字符串的索引一样,列表索引从 0 开始,第二个索引是 1,依此类推。
list = ['red', 'green', 'blue', 'yellow', 'white', 'black']
print( list[0] )
print( list[1] )
print( list[2] )
2.2 反向索引
索引也可以从尾部开始,最后一个元素的索引为 -1,往前一位为 -2,以此类推。
list = ['red', 'green', 'blue', 'yellow', 'white', 'black']
print( list[-1] )
print( list[-2] )
print( list[-3] )
2.3 切片
列表[(开始索引b):(终止索引e)(: (步长s))]
() 里的内容代表可以省略
x = [1, 2, 3, 4, 5, 6, 7, 8]
y1 = x[:4] # y1 = [1, 2, 3, 4]
y2 = x[::2] # y2 = [1, 3, 5, 7]
y3 = x[::-1] # y3 = [8, 7, 6, 5, 4, 3, 2, 1]
列表是可变的容器(不同于字符串)
列表是可变的
字符串是不可变的
nums = [10, 20, 30, 40, 50, 60, 70, 80, 90]
print(nums[0:4])
list = ['openAI', 'hqyj', "Zhihu", "Taobao", "Wiki"]
# 读取第二位
print (list[1])
# 从第二位开始(包含)截取到倒数第二位(不包含)
print (list[1:-2])
# 从下标2开始(包含2)到最后一个
print (list[2:])
# 从下标0开始到下标3结束(左闭右开)
print (list[:3])
3.列表的数据操作(增、删、改、查)
3.1 添加数据(增)
- 方法
方法名(L代表列表) | 说明 |
---|---|
L.append(x) | 向列表的末尾追加单个数据 |
L.insert(index, obj) | 将某个数据obj 插入到 index这个索引位置的数据之前 |
L.extend(可迭代对象) | 等同于: L += 可迭代对象 |
- 示例
mylist1 = [1, 3, 4] # 目标是变成 [1, 2, 3, 4, 5]
mylist1.append(5) # mylist1 = [1, 3, 4, 5]
mylist1.insert(1, 2) # mylist1 = [1, 2, 3, 4, 5]
mylist1.extend(range(6, 10)) # mylist1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
切片赋值的特性
Python 列表支持通过切片赋值向列表中插入或替换元素:
- 语法:
list[start:end] = iterable
- 当
start == end
时,表示在这个位置插入,而不会删除或替换现有元素。
3.2 修改数据 (改)
- 用索引赋值可以改变列表内的数据
列表[整数表达式] = 表达式
- 示例
mylist2 = [1, 1.99, 3] # 把1.99 改为2
mylist2[1] = 2 # mylist2 = [1, 2, 3]
3.3 删除数据 (删)
-
方法
方法 说明 L.remove(x) 从列表L中删除第一次出现在列表中的数据元素,如果x不存在则报错 L.pop() 根据索引删除元素,并返回该元素。若不提供索引,默认删除最后一个元素 L.clear() 清空列表 - 示例
L = [1, 2, 3, 4, 2, 2, 3, 4] L.remove(3) # L = [1, 2, 4, 2, 2, 3, 4] L.remove(3) # L = [1, 2, 4, 2, 2, 4] L.remove(3) # 报错了 L.clear() # L = []
-
del 语句删除指定位置的数据元素
-
语法
del 变量名 # 删除变量,同时解除变量绑定的对象 del 列表[整数表达式]
-
示例
L = ['张飞', '赵云', '鲁班7号', '孙悟空'] del L[2] # L = ['张飞', '赵云', '孙悟空'] del L # 删除 L 变量
-
3.4 查看(索引取值就是查看)
print(L[0]) # 取值
-
课后练习1
写一个程序, 用列表保存用户输入的数据 1. 让用户输入4个任意的整数,放入列表 2. 在第三个整数前面插入一个100 3. 删除列表中的第4个整数 4. 将之前输入的第二个整数加上1 后放回原处 5. 打印现在的列表
-
课后练习1
写程序,输入一个整数, 打印如下的四个三角形 如: 请输入: 3 1. 打印 * ** *** 2. 打印 * ** *** 3. 打印 *** ** * 4. 打印 *** ** *
-
课后练习2
写程序,输入一个整数,打印如下的正方形 如: 请输入: 4 打印: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 请输入: 5 打印: 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
-
课后练习3
写程序,输入一个整数,打印如下的正方形 如: 请输入: 4 打印: 1 2 3 4 2 3 4 5 3 4 5 6 4 5 6 7 请输入: 5 打印: 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9
-
课后练习4
已知, 局域网的IP 都是: 192.168.xxx.yyy xxx 从 0 ~ 9, yyy 从 1 ~ 254 写程序,生成 从 192.168.0.1 ~ 192.168.9.254 区间的 2540 个 IP 地址, 将这些IP地址放入 列表并打印
提示用循环嵌套
4.嵌套列表
使用嵌套列表即在列表里创建其它列表
a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]
print(x)#[['a', 'b', 'c'], [1, 2, 3]]
print(x[0])#['a', 'b', 'c']
print(x[0][1])#b
5.Python列表常用API
操作列表的函数
序号 | 函数 |
---|---|
1 | len(list)列表元素个数 |
2 | max(list)返回列表元素最大值 |
3 | min(list)返回列表元素最小值 |
4 | list(seq)将元组转换为列表 |
列表的常用方法
运算 | 结果 |
---|---|
s.index(x[, i[, j]]) | x 在 s 中首次出现项的索引号(索引号在 i 或其后且在 j 之前) |
s.count(x) | x 在 s 中出现的总次数 |
s.append(x) | 将 x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x] ) |
s.clear() | 从 s 中移除所有项 (等同于 del s[:] ) |
s.copy() | 创建 s 的浅拷贝 (等同于 s[:] ) |
s.extend(t) 或 s += t | 用 t 的内容扩展 s (基本上等同于 s[len(s):len(s)] = t ) |
s.insert(i, x) | 在由 i 给出的索引位置将 x 插入 s (等同于 s[i:i] = [x] ) |
s.pop([i]) | 提取在 i 位置上的项,并将其从 s 中移除 |
s.remove(x) | 删除 s 中第一个 s[i] 等于 x 的项目。 |
s.reverse() | 就地将列表中的元素逆序。 |
s.sort( key=None, *reverse=False*) | 对列表内的数据进行排序, reverse=False 升序排序,否则是降序排序 |
示例:
s = [1, "二", 3]
value = s.pop(1) # s= [1, 3]; value = '二'
>>> s = [1, 2, 3, 5]
>>> s.reverse() # 反转
>>> s
[5, 3, 2, 1]
>>> s = [1, 2, 3, 4, 2, 2, 3, 4]
>>> s.index(3) # 返回第一次出现的位置的索引
2
>>> s.index(3, 4)
6
>>> s.index(100) # 触发异常,要用try 语句处理
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 100 is not in list
>>> s.count(3) # 在列表 s 中 找出所有值为3 的元素的个数,并返回
2
>>> s.count(2)
3
>>> L1 = [2, 4, 6, 8, 9, 1]
>>> L1.reverse()
>>> L1
[1, 9, 8, 6, 4, 2]
>>> s.sort() # 排序,默认是升序排序
>>> s
[1, 2, 2, 2, 3, 3, 4, 4]
>>> s.sort(reverse=True)
>>> s
[4, 4, 3, 3, 2, 2, 2, 1]
Python元组(tuple)
- 元组是不可改变的列表
- 同列表list 一样,元组可以存放任意类型的数据
- 但是,一旦创建将不可修改
- 元组使用小括号 ( ),列表使用方括号 [ ]
1.元组的创建
创建元组的字面值
用小括号() 括起来,单个元素括起来后加逗号来区分单个元素还是元组
t = () # 空元组
t = (100,) # 含有一个数据元素的元组
t = 100, # 含有一个数据元素的元组,元组中只包含一个元素时,需要在元素后面添加逗号 ,否则括号会被当作运算符使用
t = (1, 2, 3) # 含有三个数据元素的元组
t = ( 'hqyj', 2004) # 存放不同类型的元组
t = 1, 2, 3 # 含有三个数据元素的元组
type(x) 函数用来返回数据x的类型
创建元组的函数 tuple
t = tuple() # t = ()
t = tuple(range(5)) # t = (0, 1, 2, 3, 4)
2.元组的数据操作(删,查,运算)
2.1 删除元组
元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组
tup = ('openAI', 'hqyj', 100, 200)
print (tup)
del tup
print (tup)#name 'tup' is not defined
2.2 查看元组
元组与字符串类似,下标索引从 0 开始,可以进行截取,组合等。
tup1 = ('python', 'hqyj', 100, 200)
tup2 = (1, 2, 3, 4, 5, 6, 7 )
print (tup1[0])#python
print (tup2[1:5])#(2, 3, 4, 5)
print (tup2[:4])#(1, 2, 3, 4)
print (tup2[2:])#(3, 4, 5, 6, 7)
2.3 元组的运算
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合
tup1 = (12, 34.56)
tup2 = ('abc', 'xyz')
# 创建一个新的元组
tup3 = tup1 + tup2
print (tup3)
>>> t = (1, 2, 3) + (4, 5, 6)
>>> t += (7, 8, 9) # 等同于 t = t + (7, 8, 9)
>>> t = t * 2
>>> t *= 2
>>> 5 in t
True
3.元组不可变
所谓元组的不可变指的是元组所指向的内存中的内容不可变。
tup = (1, 2, 3, 4, 5, 6, 7)
tup[1] = 100
print(tup)#报错'tuple' object does not support item assignment
4.元组常用API
Python元组包含了以下内置函数
序号 | 方法 | 描述 |
---|---|---|
1 | len(tuple) | 返回元组中元素个数。 |
2 | max(tuple) | 返回元组中元素最大值。 |
3 | min(tuple) | 返回元组中元素最小值。 |
4 | tuple(list) | 将列表转换为元组。 |
元组常用的方法
运算 | 结果 |
---|---|
s.index(x[, i[, j]]) | x 在 s 中首次出现项的索引号(索引号在 i 或其后且在 j 之前) |
s.count(x) | x 在 s 中出现的总次数 |
Python字典(dict )
-
字典是一种可变容器模型,且可存储任意类型对象。
-
字典的数据都是以键(key)-值(value)对的形式进行映射存储.
-
字典的每个键值对( key:value )用冒号分割,每个对之间用逗号分割,整个字典包括在花括号 {} 中
-
d = {key1 : value1, key2 : value2, key3 : value3 }
-
字典的数据是无序的
-
字典的键不能重复,且只能用不可变类型作为字典的键
-
字典中的数据只能用"键"key 进行索引,不能用整数进行索引
1.字典的创建
- 创建字典的字面值:
字典的表示方式以 {} 括起来, 以英文的冒号 (😃 分隔键值对,各键值对之间用逗号(,)分隔
d = {} # 创建空字典
d = {'name': "weimingze", "age": 35}
d = {'a': [1, 2, 3]}
d = {'b': {"bb": 222}}
d = {1:'壹', 2:'贰', 5:'伍'}
d = {(1, 2, 3):'壹贰伍'}
以下写法会存在问题
-
键必须是唯一的,但值则不必。
-
值可以取任何数据类型,但键必须是不可变的,如字符串,数字。
d = {'a': 1, 'b': 2, 'a': 3} # 字典的键不能重复 d = {'a': 3, 'b': 2}
d = {[1, 2, 3]: 'a'} # 不能用可变类型作为字典的键 # 报错
- 字典的创建函数 dict()
d = dict() # d = {}
d = dict([("name", "小王"), ("age", 35)]) # {'name': '小王', 'age': 35}
d = dict(a=1, b=2, c=3) # {'a':1, 'b':2, 'c':3}
d = dict([1, 2, 3, 4]) # 错
2.字典的数据操作(增、删、改、查)
2.1 增加和修改字典
-
添加和修改字典的元素
-
语法
字典[键key] = 表达式
键不存在, 会创建键并绑定键对应的值
键存在, 会改变键对应的值
-
示例:
d = {} d['name'] = 'tarena' # 添加键值对 d = {'name': 'tarena'} d['age'] = 18 # d = {'name': 'tarena', 'age': 18} d['age'] = 19 # 改变 'age' 键对应的值 d = {'name': 'tarena', 'age': 19} dict.update(dict2) # 把字典dict2的键/值对更新到dict里 如果 dict2 中的键在 dict 中已经存在,其值会被覆盖
-
2.2 访问字典里的值
-
字典的键索引
- 语法
字典[键key]
用键索引可以查看字典中的数据
-
示例:
d = {'one': 1, 'two': 2} print(d['two'])
如果用字典里没有的键访问数据,会输出错误
mydic = {'Name': 'hqyj', 'Age': 7, 'Class': 'First'}
print (mydic['Alice'])
- in / not in 运算符
用 in 可以判断一个键是否存在于字典中,如果存在返回 True, 否则返回 False
not in 与 in 相反
- 示例
>>> d = dict(a=1, b=2) # d = {'a': 1, 'b': 2}
>>> 'a' in d
True
>>> 1 in d
False
>>> 'hello' not in d
True
dict.get(key, default=None) #返回指定键的值,如果键不在字典中返回 default 设置的默认值
2.3 删除字典元素
能删单一的元素也能清空字典,清空只需一项操作
显式删除一个字典用del命令
- 语法
del 字典[键]
- 示例
mydic = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
del mydic['Name'] # 删除键 'Name'
mydic.clear() # 清空字典
print (mydic['Age'])
print (mydic['School'])
del mydic # 删除字典
3.字典的特性
字典值可以是任何的 python 对象,既可以是标准的对象,也可以是用户定义的,但键不行。
1)不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
mydic = {'Name': 'jack', 'Age': 27, 'Name': 'karen'}
print (mydic['Name'])
2)键必须不可变,所以可以用数字,字符串或元组充当,而用列表等就不行
mydic1 = {97:"a",98:"b"}
mydic2 = {"name":"karen","age":27}
mydic3 = {['Name']: 'karen', 'Age': 27}
print(mydic3[['Name']])#报错unhashable type: 'list'
注: python 中有四种可变类型
-
列表 list
-
字典dict
-
集合 set
-
字节数组 bytearray
字典是可迭代对象, 字典只能对所有的键进行迭代访问,默认访问键
d = {'name': 'tarena', 'age': 19}
for k in d:
print(k)
name
age
for k in d:
print("key=", k, 'value=', d[k])
key= name value= tarena
key= age value= 19
可以使用 for
循环来遍历字典的键和值。可以使用 dict.keys()
方法遍历键,使用 dict.values()
方法遍历值,使用 dict.items()
方法同时遍历键和值。
1.遍历字典的键:
my_dict = {'a': 1, 'b': 2, 'c': 3}
for key in my_dict.keys():
print(f"Key: {key}")
#输出:Key: a Key: b Key: c
2.遍历字典的值:
my_dict = {'a': 1, 'b': 2, 'c': 3}
for value in my_dict.values():
print(f"Value: {value}")
# 输出:Value: 1 Value: 2 Value: 3
3.同时遍历字典的键和值:
my_dict = {'a': 1, 'b': 2, 'c': 3}
for key, value in my_dict.items():
print(f"Key: {key}, Value: {value}")
# 输出:Key: a, Value: 1 Key: b, Value: 2 Key: c, Value: 3
4.字典常用API
操作字典的函数:
序号 | 函数 | 描述 |
---|---|---|
1 | len(dict) | 计算字典元素个数,即键的总数。 |
2 | str(dict) | 输出字典,可以打印的字符串表示。 |
3 | type(variable) | 返回输入的变量类型,如果变量是字典就返回字典类型。 |
字典的方法:
序号 | 函数及描述 |
---|---|
1 | dict.clear()删除字典内所有元素 |
2 | dict.copy()返回一个字典的浅复制 |
3 | dict.fromkeys(seq[, value])创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值 |
4 | dict.get(key, default=None)返回指定键的值,如果键不在字典中返回 default 设置的默认值 |
5 | key in dict如果键在字典dict里返回true,否则返回false |
6 | dict.items()以列表返回一个可用for语句循环的对象 |
7 | dict.keys()返回一个可用for语句循环的对象 |
8 | dict.setdefault(key, default=None)和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default |
9 | dict.update(dict2)把字典dict2的键/值对更新到dict里 |
10 | dict.values() 返回一个可用for语句循环的对象 |
11 | pop(key,default)删除字典 key(键)所对应的值,返回被删除的值。 |
12 | popitem()返回并删除字典中的最后一对键和值。 |
-
示例
>>> d = {'name': 'tarena', 'age': 19} >>> >>> d['age'] 19 >>> d['address'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'address' >>> d.get('address', '未填写住址') '未填写住址' >>> d.get('age', 0) 19 >>> n = d.pop('name') >>> d { 'age': 19} >>> n 'tarena' keys = ['a', 'b', 'c'] my_dict = dict.fromkeys(keys)
5.列表、元组、字典小结
-
列表和元组是有序的,字典的存储是无序的
-
列表、字典是可变的,元组是不可变的
-
字典的键索引速度快,列表的索引速度也快
d = {'a':1, 'b':2, .........} print(d['c']) # 速度快 L = [7, 5, 1, ........] print(L[10009]) # 速度快
-
列表和元组是顺序存储的,字典是散列存储的
-
字典的 in / not in 运算符快于列表的 in / not in 运算符
L = ['孙悟空', '赵云', '吕布', ...] if '王昭君' in L: # 速度慢 pass D = {'孙悟空':'花果山', '赵云':'长山', '吕布':'石家庄', .....} if '王昭君' in D: # 速度快 pass
集合set/ 固定集合 frozenset
-
集合是可变的容器,固定集合是不可变的集合
-
集合相当于只有键没有值的字典
-
集合是无序的不重复元素的存储结构
-
集合内的数据都是唯一的,不可变的
1.集合的创建
-
创建集合的方式
空集合 set()
非空集合 用 {} 括起来,值用逗号分隔开
s = set() # 用函数空集合 s = {1, 2, 3, 4} # 创建非空集合的字面值 s = set(range(5)) # 调用 set(可迭代对象) 来创建集合 s = {0, 1, 2, 3, 4} s = set("ABC") # s = {'B', 'C', 'A'} s = set("ABCCCCCCC") # s = {'B', 'C', 'A'} s = set(['ABC']) # s = {'ABC'} 使用 set()函数从列表创建集合 s = set((4, 5, 6, 7))# 使用 set()函数从元组创建集合
-
创建固定集合frozensets的方式
fs = frozenset() # 空固定集合 fs = frozenset() fs = frozenset([1, 2, 3]) # fs = frozenset({1, 2, 3})
**注意:**创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
2.集合的数据操作(增、删)
2.1 添加元素
将元素 x 添加到集合 s 中,如果元素已存在,则不进行任何操作。
s.add( x ) 添加元素到集合
s.update( x ) 添加元素到集合,且参数可以是列表,元组,字典等 ,x 可以有多个,用逗号分开
s1 = set((4, 5, 6, 7))
s1.add(100)
print(s1)
s1.update([200,300])
print(s1)
2.2 删除元素
s.remove( x ):将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误。
s.discard( x )):将元素 x 从集合 s 中移除,如果元素不存在,不会发生错误。
s.pop()):对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除。
s1 = {10, 20, 30}
s1.remove(20)
print(s1)
s1.remove(40)#报错
s1 = {10, 20, 30}
s1.discard(20)
print(s1)
s1.discard(40)
s1 = {10, 20, 30}
s1.pop()
print(s1)
del s1 # 也可以直接删除整个集合
注意:集合(set)没有索引查看的功能。集合是一种无序、不可重复的数据结构,用于存储唯一的元素。由于集合是无序的,所以不能通过索引来访问其中的元素。所以也没有对应的修改功能。
x in s 判断元素 x 是否在集合 s 中,存在返回 True,不存在返回 False。
s1 = {10, 20, 30}
print(20 in s1)
3.集合内置方法常用API
集合的方法
方法 | 描述 |
---|---|
add() | 为集合添加元素 |
clear() | 移除集合中的所有元素 |
copy() | 拷贝一个集合 |
difference() | 返回多个集合的差集 |
discard() | 删除集合中指定的元素 |
intersection() | 返回集合的交集 |
pop() | 随机移除元素返回集合的交集 |
remove() | 移除指定元素 |
union() | 返回两个集合的并集 |
update() | 给集合添加元素 |
len() | 计算集合元素个数 |
pop() | 随机移除元素 |
remove() | 移除指定元素 |
示例:
# 1.len()
s1 = {10, 20, 30}
print(len(s1))
#2. clear()
s1 = {10, 20, 30}
s1.clear()
print(s1)
#3.union()
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set3 = {5, 6, 7}
result = set1.union(set2, set3)
print(result)
容器总结
-
容器总结
-
类型
- 列表 list
- 元组 tuple
- 字典 dict
- 集合 set / 固定集合 frozenset
-
可变和不可变
- 可变的容器
list dict set
- 不可变得容器
tuple, frozenset
-
有序和乱序
-
有序
list tuple
-
无序
dict set frozenset
-
-
-
课后练习
写一个程序,输入一段文字, 1) 写程序计算出文字中,每个字出现的次数, 2) 求出 这段文字中字符的个数 如: 我喜欢你,你不喜欢我 '我': 2 '你': 2 '喜': 2 '欢': 2 ',': 1 '不': 1 您输入的这段文字有 6 种字符
-
课后练习1
写程序, 输入一个整数n,打印 宽度为n 的正方形 如: 请输入: 4 打印: #### # # # # #### 请输入: 5 打印: ##### # # # # # # #####
-
课后练习2
写一个程序,输入任意行文字,当输入为空字符串时结束输入,将所有的字符串以最长的字符串宽度打印如下方框 请输入: hello 请输入: hello world 请输入: <回车输入结束> +-------------+ | hello | | hello world | +-------------+
-
课后练习3
写一个程序: 输入一个整数,代表树干的高度,打印如下圣诞树 请输入: 3 打印: * *** ***** $ $ $ 请输入: 4 打印: * *** ***** ******* $ $ $ $
-
课后练习4
算出 100 ~ 999 的水仙花数 水仙花数是 指百位的3次方 + 十位的3次方 + 各位的3次方 等于原数的数 打印出所有的 水仙花数
例如: 153 = 1 3 + 5 3 + 3 3 153 = 1^3 + 5^3 + 3^3 153=13+53+33
-
课后练习5
打印 九九 乘法表 1x1=1 1x2=2 2x2=4 1x3=3 2x3=6 3x3=9 .... 1x9=9 ........ 9x9=81
Python推导式
Python 推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。
Python 支持各种数据结构的推导式:
- 列表(list)推导式
- 字典(dict)推导式
- 集合(set)推导式
- 元组(tuple)推导式
1.列表推导式
-
作用
用简单的表达式方式来创建列表
-
语法规则
[ 表达式 for 自定义变量 in 可迭代对象 ] # 或 [ 表达式 for 自定义变量 in 可迭代对象 if 真值表达式 ]
-
示例
# 生成一个列表, 里面有 100 个数是[1, 4, 9, 16, 25, ...] # 用 for 语句实现 L = [] for x in range(1, 101): L.append(x ** 2) print(L) # 用列表推导式 L2 = [ x ** 2 for x in range(1, 101)] print(L2) L3 = [] for x in range(1, 101): if x % 2 == 0: L3.append(x ** 2) L3 = [ x ** 2 for x in range(1, 101) if x % 2 == 0] # 取出所有的偶数 # L3 = [4, 16, 36, ...]
-
课后练习:
写程序,输入任意行文字。当没有输入的时候时结束, 将所有输入的字符串先保存在一个列表L1中 , 将L1 中的字符串的长度都计算出来,存入列表L2 中 1) 然后打印最长的字符串的字符个数 2) 打印最长的那个字符串 如: 请输入: hello 请输入: abcdef 请输入: a 请输入: <直接回车结束输入> 打印: 最长的字符个数是: 5 最长的字符串是: abcdef L1 = ['hello', 'abcdef', 'a'] L2 = [5, 6, 1] mymax = 6 # 求出最长的字符串的长度 pos = L2.index(6) # 求出最长的字符串的位置 ...
2.字典推导式
字典推导基本格式:
-
{ 键表达式: 值表达式 for 元素 in 集合 }
-
{ 键表达式: 值表达式 for 元素 in 集合 if 条件 }
# 将列表中各字符串值为键,各字符串的长度为值,组成键值对
listdemo = ['karen','jack', 'marry']
newdict = {key:len(key) for key in listdemo}
print(newdict)#{'karen': 5, 'jack': 4, 'marry': 5}
#提供三个数字,以三个数字为键,三个数字的平方为值来创建字典:
dic = {x: x**2 for x in (2, 4, 6)}
print(dic)#{2: 4, 4: 16, 6: 36}
3.集合推导式
集合推导式基本格式:
- { 表达式 for 元素 in 序列 }
- { 表达式 for 元素 in 序列 if 条件 }
#计算数字 1,2,3 的平方数:
setnew = {i**2 for i in (1,2,3)}
print(setnew)#{1, 4, 9}
#判断不是 abc 的字母并输出:
a = {x for x in 'abracadabra' if x not in 'abc'}
print(a)#{'d', 'r'}
4.元组推导式
元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型,快速生成一个满足指定需求的元组。
元组推导式和列表推导式的用法也完全相同,只是元组推导式是用 () 圆括号将各部分括起来,而列表推导式用的是中括号 [],另外元组推导式返回的结果是一个生成器对象。
元组推导式基本格式:
- (表达式 for 元素 in 序列 )
- (表达式 for 元素 in 序列 if 条件 )
#生成一个包含数字 1~9 的元组
a = (x for x in range(1,10))
print(a)#返回的是生成器对象
print(tuple(a))#使用 tuple() 函数,可以直接将生成器对象转换成元组
课堂练习
生成1—10之间的数字,将其平方存入list01中。
将list01中所有偶数存入list02中。
将list01中所有大于5的奇数增加1后存入list03中。
要求都用列表推导式
一、Python函数
1. 定义一个函数
-
什么是函数
- 函数是可以重复执行的语句块,可以重复调用
-
作用
用于封装语句块, 提高代码的重用性。
函数是面向过程编程的最小单位
1.1 def 语句
-
作用
用来定义( 创建)函数
-
语法
def 函数名(形式参数列表): 语句块
-
说明
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
- 函数名是一个变量,不要轻易对其赋值
- 函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,但不能轻易对其改变
- 函数的形参列表如果不需要传入参数,形式参数列表可以为空
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数内容以冒号 : 起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
-
示例
# 定义一个函数,用 say_hello 变量绑定 def say_hello(): print("hello world!") print("hello tarena!") print("hello everyone!") # 定义一个函数,传入两个参数,让这个函数把最大的值打印到终端 def mymax(a, b): if a > b: print("最大值是", a) else: print("最大值是", b)
1.2 函数的调用
-
语法
函数名(实际调用传递参数)
-
说明
- 函数调用是一个表达式
- 如果函数内没有return 语句,函数执行完毕后返回 None 对象
-
示例
# 调用 say_hello() # 调用一次 say_hello() # 调用第二次 # 调用 mymax(100, 200) mymax(999, 1) mymax('abc', 'cba')
-
课后练习
写一个函数 myadd, 此函数传入两个参数, x, y 次函数的功能是打印 x + y 的和: def myadd(......): .... myadd(100, 200) # 300 myadd('ABC', '123') # ABC123
1.3 return 语句
-
语法
return [表达式]
注: [] 代表 内部的内容可以省略
-
作用
用于函数的内部,结束当前函数的执行,返回到调用此函数的地方,同时返回一个对象的引用关系
-
说明
-
return 语句后面的表达式可以省略,省略后相当于 return None
-
如果函数内部没有 return 语句, 则函数执行完毕后返回None, 相当于在最后一条语句后有一条return None
-
-
示例
#没有return def fn1(): print("调用了函数") re=fn1() print(re)#None #返回一个值 def fn2(x): return x+100 re2=fn2(100) print(re2)#200 #返回多个值 def fn3(x): return x*x,x%3 re3=fn3(100) print(re3)#(10000, 1) x,y=fn3(100) print(x,y)#10000 1
-
课后练习2
写一个函数 myadd, 实现给出两个数,返回这两个数的和 如: def myadd(x, y): .... a = int(input("请输入第一个数: ")) b = int(input("请输入第二个数: ")) print('您输入的两个数之和是:', myadd(a, b))
2. 函数参数
2.1 函数的调用传参
-
位置传参
实际参数传递时,实参和形参按位置来依次对应
-
关键字传参
实际参数传递时,实参和形参 按名称依次对应
注: 位置传参要先于关键字传参
示例
def myfun1(a, b, c):
print('a=', a)
print('b=', b)
print('c=', c)
## 位置传参
myfun1(1, 2, 3)
## 关键字传参
myfun1(c=33, a=11, b=22)
## 位置传参要先于关键字传参
myfun1(111, c=333, b=222) # 正确
# 序列实参:使用星号将序列拆分后,与形参进行对应
list01 = [7,8,9]
myfun01(*list01)
# 字典实参:使用双星号将字典拆分后,依次与形参对应
dict01 = {"c":3,"b":2,"a":1}
myfun01(**dict01)
-
问题
写一个函数 myadd4, 实现给出四个数,返回这四个数的和 如: def myadd4(...): .... a = int(input("请输入第一个数: ")) b = int(input("请输入第二个数: ")) c = int(input("请输入第三个数: ")) d = int(input("请输入第四个数: ")) print('您输入的四个数之和是:', myadd4(a, b, c, d)) # 思考用什么方式实现: print(myadd4(1, 2)) # 3 print(myadd4(1, 2, 3)) # 6 print(myadd4(1, 2, 3, 4)) # 10
2.2 函数的形式参数定义方法
函数的缺省参数(默认参数)
语法
def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ... ):
语句块
说明
缺省参数即默认实参,必须自右向左依次存在(即,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数)
示例
def myadd4(a, b, c=0, d=0):
print(a)
print(b)
print(c)
print(d)
return a + b + c + d
print(myadd4(1, 2))
print(myadd4(1, 2, 3))
print(myadd4(1, 2, 3, 4))
错误示例
>>> def myadd(a, b=0, c): # 报错
... pass
形参的定义
- 位置形参
- 星号元组形参(*args)
- 命名关键字形参
- 双星号字典形参(**kwargs)
1)位置形参
-
语法:
def 函数名(形参名1, 形参名2, ...): pass
2)星号元组形参
-
语法
def 函数名(*元组形参名): pass
-
作用
收集多余的位置实参
元组形参名一般命名为args
-
示例
def myfunc2(*args): print("len(args)=", len(args)) print('args=', args) myfunc2() # args=() myfunc2(1, 2, 3) # args=(1, 2, 3) def myfunc3(a, b, *args): print(a, b, args) myfunc3(1, 2) # 1-->a, 2-->b, ()--->args myfunc3(1, 2, 3, 4) # # 1-->a, 2-->b, (3, 4)--->args
3)命名关键字形参
-
语法
def 函数名(*, 命名关键字形参1, 命名关键字形参2, ...): pass # 或者 def 函数名(*args, 命名关键字形参1, 命名关键字形参2, ...): pass
-
作用
强制,所有的参数都必须用关键字传参
-
示例
def myfunc4(a, b,*args, c, d): print(a, b, c, d) myfunc4(1, 2, d=4, c=3) # 正确,c,d 必须关键字传参 myfunc4(1, 2, 3, 4) # 错误
4)双星号字典形参
-
语法
def 函数名(**kwargs): pass
-
作用
收集多余的关键字传参
字典形参名最多有一个,
字典形参名 一般命名为 kwargs
-
示例
def myfunc5(**kwargs): print(kwargs) # {'name': 'tarena', 'age': 18}-->kwargs myfunc5(name='tarena', age=18)
函数的形参定义方法说明
- 位置形参,星号元组形参,命名关键字参数,双星号字典形参,默认参数可以混合使用。
- 函数的形参定义自左至右的顺序为:位置形参,星号元组形参,命名关键字参数,双星号字典形参
示例:
def fn(a, b, *args, c, d, **kwargs):
print(a)
print(b)
print(*args)
print(c)
print(d)
print(kwargs)
fn(100, 200, 300, 400, c='C',name='tarena',d='D')
思考:
print() # 函数是如何定义的呢:
def myprint(*args, sep=' ', end='\n'):
pass
3. 匿名函数
在Python中,匿名函数通常使用lambda
关键字来创建。匿名函数也被称为lambda函数,它是一种简单的、一行的函数,常用于临时需要一个小函数的地方。匿名函数的语法如下:
-
语法
lambda [函数的参数列表]: 表达式
-
作用
- 创建一个匿名函数对象
lambda
是关键字,表示你正在定义一个匿名函数。- 同 def 类似,但不提供函数名
[函数的参数列表]
是函数的参数,可以有零个或多个参数,参数之间用逗号分隔。: 表达式
是函数的返回值,通常是一个表达式,匿名函数会计算这个表达式并返回结果。
-
说明
lambda 表达式 的创建函数只能包含一个表达式
-
示例
def myadd(x, y): return x + y print('1 + 2 =', myadd(1, 2)) # 3 # myadd 函数可以改写成 myadd2 = lambda x, y: x + y print('3 + 4 =', myadd2(3, 4)) # 7 square = lambda x: x * x print(square(5)) # 输出: 25
4. 变量作用域
4.1 什么是变量作用域
一个变量声明以后,在哪里能够被访问使用,就是这个变量"起作用"的区域:也就是这个变量的作用域
一般来说,变量的作用域,是在函数内部和外部的区域 来体现,因此常常与函数有关
4.2 局部变量和全局变量
-
局部变量
- 定义在函数内部的变量称为局部变量(函数的形参也是局部变量)
- 函数内部的变量只能在函数内部或者函数内部的函数内部访问 ,函数外部不能访问
- 局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁
-
全局变量
- 定义在函数外部,模块内部的变量称为全局变量
- 全局变量, 所有的函数都可以直接访问(取值,但函数内部不能直接将其赋值改变)
-
局部变量示例
>>> def fn(a, b):
... c = 100
... print(a, b, c) # a, b, c三个都是局部变量
>>> fn(1, 2)
>>> print(a, b, c) # 报错, 因为a,b,c 在调用后就销毁了
- 全局变量示例
a = 100 # 全局变量
def fx(b, c): # b, c 局部变量
d = 400 # d 局部变量
print(a, b, c, d)
fx(200, 300)
print(a) # 100
print(b) # 报错, 因为此时 b 不存在了
- 全局变量示例2
a = 100 # 全局变量
def fx(b):
a = 666 # 创建局部变量,不是改变全局变量
c = 300
print(a, b, c) # 优先访问局部变量
fx(200) # 666 200 300
print(a) # 100
4.3 局部作用域修改全局变量
- 问题
## 如何用一个变量来记录一个函数调用的次数
count = 0
def hello(name):
print('hello', name)
count += 1 # 等同于 count = count + 1 # 如何让 此语句能改变全局变量而不是创建局部变量
hello('小张')
hello('小李')
print('您共调用hello函数', count, '次') # 2 次
-
作用
告诉python 的解释执行器, global 语句声明的一个或多个变量, 这些变量是全局变量
-
语法
global 变量名1, 变量名2, ....
-
示例
# 如何用一个变量来记录一个函数调用的次数 count = 0 def hello(name): global count # 声明 global 是全局变量 print('hello', name) count += 1 # 等同于 count = count + 1 hello('小张') hello('小李') hello('小魏') print('您共调用hello函数', count, '次') # 3 次
-
global 说明
- 全局变量如果要在函数内部被赋值,则必须经过全局声明 global
- 默认全局变量在函数内部可以使用,但只能取值,不能赋值
- 不能先声明为局部变量,再用 global 声明为全局变量,此做法不符合语法规则
-
函数的形参已经是局部变量,不能用 global 声明为全局变量
错误示例
a = 100
b = 200
def fa(a):
b = 20 # SyntaxError: name 'b' is assigned to before global declaration
global b
b = 222
4.4 局部作用域修改外部变量
在函数内部 提前用nonlocal声明 函数内部的某个变量为外部的变量
前提:必须是函数嵌套
说明:
(1)变量的查找顺序还是遵从:LEGB顺序
在 Python 中,LEGB 代表四种作用域的查找顺序:Local、Enclosing、Global 和 Built-in。
(2)局部作用域中若要修改外部函数嵌套作用域中的变量需要使用:nonlocal 语句
- 格式:nonlocal 变量名
- 作用:将局部作用域中变量声明为外部函数嵌套作用域中的变量。
LEGB顺序
Local (L):
- 本地作用域,指当前函数内部的变量。
- 当你在函数内部定义变量并尝试访问它时,Python 首先会在函数内部查找这个变量。
def outer_function():
x = 10 # Local variable
print(x) # 查找顺序从 Local 开始
Enclosing (E):
- 闭包函数外的函数作用域,指嵌套函数的外部函数中定义的变量。
- 如果在当前函数内部找不到变量,Python 会查找外层(闭包)函数中的变量。
def outer_function():
x = 10 # Enclosing variable
def inner_function():
print(x) # 查找顺序从 Enclosing 开始
inner_function()
Global (G):
- 全局作用域,指模块级别定义的变量。
- 如果在本地和闭包函数中找不到变量,Python 会查找全局作用域的变量。
x = 20 # Global variable
def outer_function():
print(x) # 查找顺序从 Global 开始
Built-in (B):
- 内建作用域,指 Python 预定义的变量、函数等,如
len
、sum
等。 - 如果在以上三个作用域中都找不到变量,Python 会查找内建作用域。
def outer_function():
print(len) # 查找顺序从 Built-in 开始
nonlocal
"""
外部嵌套作用域
"""
def func01():
a = 10
def func02():
# 内部函数,可以访问外部嵌套变量
# print(a)
# 内部函数,如果修改外部嵌套变量,需要使用nonlocal语句声明
nonlocal a
a = 20
func02()
print(a)
func01()
5. 函数的内存分配
1、将函数的代码存储到代码区,函数体中的代码不执行。
2、调用函数时,在内存中开辟空间(栈帧),存储函数内部定义的变量。
3、函数调用后,栈帧立即被释放。
def func(a, b):
a = 20
b[0] = 20
a = 10
b = [100]
func(a, b)
print(a) # 10
print(b) # 20
5.1 可变不可变
可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
- **不可变类型:**变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
- **可变类型:**变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
- **不可变类型:**值传递: 如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
- **可变类型:**引用传递: 如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
python 中一切都是对象(后面会讲),严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
传不可变对象实例
通过内置的 id() 函数来查看内存地址变化:
def change(a):
print(id(a))
a=10
print(id(a))#1428793408
a=1
print(id(a))#1428793264
#总结:可以看见在调用函数前后,形参和实参指向的是同一个对象(对象 id 相同),在函数内部修改形参后,形参指向的是不同的id。
传可变对象实例
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。
def changeme( mylist ):
mylist.append(40)
print (mylist)
mylist = [10,20,30]
changeme(mylist)#[10, 20, 30, 40]
print (mylist)#[10, 20, 30, 40]
#总结:传入函数的和在末尾添加新内容的对象用的是同一个引用
5.2 总结
(1) 不可变类型参数有:
- 数值型(整数,浮点数)
- 布尔值bool
- None 空值
- 字符串str
- 元组tuple
(2) 可变类型参数有:
- 列表 list
- 字典 dict
- 集合 set
(3) 传参说明:
- 不可变类型的数据传参时,函数内部不会改变原数据的值。
- 可变类型的数据传参时,函数内部可以改变原数据。
6. 函数自调用(递归)
6.1 递归的定义
在定义一个过程或函数时出现调用本过程或本函数的成分,称之为递归。
若调用自身,称之为直接递归。
若过程或函数A调用过程或函数B,而B又调用A,称之为间接递归。
在算法设计中,任何间接递归算法都可以转换为直接递归算法来实现,所以主要讨论直接递归。
- 递归算法通常通常把一个大的复杂问题层层转化为一个或多个与原问题相似的规模较小的问题来求解。
- 递归策略只需少量的代码就可以描述出解题过程所需要的多次重复计算,大大减少了算法的代码量。
解决递归问题满足的三个条件:
- 需要解决的问题可以转化为一个或多个子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量规模上不同。
- 递归调用的次数必须是有限的。
- 必须有结束递归的条件来终止递归。
6.2 递归的使用
找出函数的等价关系式,我们要不断缩小参数的范围,缩小之后,我们可以通过一些辅助的变量或者操作,使原函数的结果不变。
比如,f(n) 这个范围比较大,我们可以让 f(n) = n * f(n-1)。这样,范围就由 n 变成了 n-1 了,范围变小了,并且为了原函数f(n) 不变,我们需要让 f(n-1) 乘以 n。
说白了,就是要找到原函数的一个等价关系式,f(n) 的等价关系式为 n * f(n-1),即
f(n) = n * f(n-1)。
举个栗子,还是从阶乘来出发
假设我们用递归来算阶乘 f(n)
f 里面用到了 f,怎么理解呢?很简单,把式子展开即可:
看到递归了吗?
先递进,再回归——这就是「递归」。
- 函数直接或间接的调用自身
讲故事:
- 从前有座山,山上有座庙,庙里有个老和尚讲故事
- 从前有座山,山上有座庙,庙里有个老和尚讲故事
- 从前有座山,山上有座庙,庙里有个老和尚讲故事
- 从前有座山,山上有座庙,庙里有个老和尚讲故事
示例:
# 函数直接的调用自身
def f():
f() # 调用自己
# 此递归达最大深度出错
# f()
print("递归完成")
# 函数直接的调用自身
def fa():
fb()
def fb():
fa()
fa()
print("递归完成")
说明:
- 递归一定要控制递归的层数,当符合某一条件时要终止递归调用
- 几乎所有的递归都能用while循环来代替
递归的实现方法:
- 先假设此函数已经实现
递归优缺点:
- 优点:
- 递归可以把问题简单化,让思路更为清晰,代码更简洁
- 缺点:
- 递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
限制层数递归示例:
递归函数示例
计算阶乘 factorial
迭代实现
def factorial(n):
result = 1
i = 1
while i <= n:
result *= i
i+=1
return result
print("factorial: ", factorial(5))
递归实现示例
# file: factorial.py
def factorial(n):
if n == 1:
return 1
s = n * factorial(n-1)
return s
print("factorial: ", factorial(5))
- 课后练习1
写一个程序: 输入一个整数,代表树干的高度,打印如下圣诞树
请输入: 3
打印:
*
***
*****
$
$
$
请输入: 4
打印:
*
***
*****
*******
$
$
$
$
- 课后练习2
写一个函数 myrange 实现和 range 一样的功能, 但返回列表
def myrange(start, stop=None, step=None):
# return range(start, stop, step) 不能这样
if stop == None: # 这是一个参数
return list(range(0, start))
... 此处自己完成
for x in myrange(4):
print(x) # 0, 1, 2, 3
for x in myrange(3, 6):
print(x) # 3, 4, 5
for x in myrange(1, 10, 2):
print(x) # 1, 3, 5, 7, 9
- 课后练习3
斐波那契数列(Fibonacci sequence)是一种经典的数列,它的特点是从第 3 项开始,每一项都等于前两项之和。前两项通常定义为:
- F(0) = 0
- F(1) = 1
从 F(2) 开始:
- F(2) = F(1) + F(0) = 1 + 0 = 1
- F(3) = F(2) + F(1) = 1 + 1 = 2
使用递归的思想实现斐波那契数列
二、Python类和对象
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。
接下来我们先来简单的了解下面向对象的一些基本特征。
1. 面向对象编程 Object-Oriented Programming
-
什么是对象
- 对象是指现实中的物体或实体
-
什么是面向对象
- 把一切看成对象(实例),用各种对象之间的关系来描述事务。
-
对象都有什么特征
- 对象有很多属性(名词) 变量
- 姓名, 年龄, 性别,
- 对象有很多行为(动作,动词) 函数
- 学习,吃饭,睡觉,踢球, 工作
- 对象有很多属性(名词) 变量
-
什么是类:
- 拥有相同属性和行为的对象分为一组,即为一个类
- 类是用来描述对象的工具,用类可以创建此类的对象(实例)
-
面向对象 示意
/-------> BYD E6(京A.88888) 实例,对象
车(类)
\-------> BMW X5(京B.00000) 实例(对象)
/-------> 小京巴(户籍号:000001)
狗(类)
\-------> 导盲犬(户籍号:000002)
/-------> 100 (对象)
int(类)
\-------> 200 (对象)
2. 类和对象的基础语法
2.1 类的定义
类是创建对象的 ”模板”。
-
数据成员:表明事物的特征。 相当于变量
-
方法成员:表明事物的功能。 相当于函数
-
通过
class
关键字定义类。 -
类的创建语句语法:
class 类名 (继承列表): 实例属性(类内的变量) 定义 实例方法(类内的函数method) 定义 类变量(class variable) 定义 类方法(@classmethod) 定义 静态方法(@staticmethod) 定义
示例代码:
class Dog: # 定义一个Dog类
pass
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"My name is {self.name} and I am {self.age} years old.")
类的创建的说明:
- 类名必须为标识符(与变量的命名相同,建议首字母大写)
- 类名实质上就是变量,它绑定一个类
2.2 实例化对象(构造函数)
(1) 构造函数调用表达式
变量 = 类名([参数])
(2) 说明
– 变量存储的是实例化后的对象地址。
– 类名后面的参数按照构造方法的形参传递
- 对象是类的实例,具有类定义的属性和方法。
- 通过调用类的构造函数来创建对象。
- 每个对象都有自己的状态,但共享相同的方法定义。
示例代码:
class Dog:
pass
# 创建第一个实例:
dog1 = Dog()
print(id(dog1)) # 打印这个对象的ID
# 创建第二个实例对象
dog2 = Dog() # dog2 绑定一个Dog类型的对象
print(id(dog2))
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"My name is {self.name} and I am {self.age} years old.")
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)
实例说明
- 实例有自己的作用域和名字空间,可以为该实例添加实例变量(也叫属性)
- 实例可以调用类方法和实例方法
- 实例可以访问类变量和实例变量
2.3 self
大家学Python面向对象的时候,总会遇到一个让人难以理解的存在:self
这个self到底是谁啊,为什么每个类实例方法都有一个参数self,它到底有什么作用呢?
「先下结论:类实例化后,self即代表着实例(对象)本身」
想要理解self有个最简单的方法,就是你把self当做**「实例(对象)的身份证」**。
类比人类,人类就是一个Python类,每个个体的人代表着实例(对象),而每个人的身份证代表的Python中self,每个人可以凭借身份证去上大学、坐高铁、住酒店…(方法),而Python中的实例(对象)也可以凭着self去调用类的方法。

self
是类方法的第一个参数,用于引用对象本身。self
不是Python关键字,但是约定俗成的命名,可以使用其他名称代替,但通常不建议。
示例代码:
class Students:
# 构造方法
def __init__(self,name):
self.name = name
# 实例方法
def study(self,examination_results):
self.examination_results = examination_results
print("同学{}的考试分数是{}".format(self.name,self.examination_results))
print("该实例对象的地址是{}".format(self))
- 先来个实例student_a
studend_a = Students('studend_a')
print(studend_a.name)
- 再来个实例student_b
studend_b = Students('studend_b')
print(studend_b.name)
可以看出,实例(对象)不一样,打印出的结果也不一样,当类被实例化后,self.name其实就等于实例(对象).name
还是以刚刚的代码为例,我们再来调用里面的实例方法,里面会打印出self,就能看得更加明显了
实例student_a:
studend_a.study(80)
实例student_b:
studend_b.study(80)
大家能清楚看到两个实例打印出的self是不一样的,因为self代表着实例(对象)本身。
打印self出现下面对象信息
<main.Students object at 0x00000129EB0F6B38>
<main.Students object at 0x00000129EB0F6B00>
这个时候是不是就清楚了,类实例化后,self即代表着实例(对象)本身
3. 属性和方法
3.1 实例属性
3.1.1 初始化方法
-
初始化方法的作用:
为新创建的对象添加实例属性
-
初始化方法的语法格式:
class 类名(继承列表): def __init__(self[, 形参列表]): 语句块 # [] 代表其中的内容可省略
-
初始化方法的说明:
- 初始化方法名必须为
__init__
不可改变 - 初始化方法会在构造函数创建实例后自动调用,且将实例自身通过第一个参数self传入
__init__
方法 - 构造函数的实参将通过
__init__
方法的参数列表传入到__init__
方法中 - 初始化方法内如果需要return语句返回,则必须返回None
- 初始化方法名必须为
-
初始化方法示例:
# file : init_method.py class Car: def __init__(self, c, b, m): self.color = c # 颜色 self.brand = b # 品牌 self.model = m # 型号 def run(self, speed): print(self.color, "的", self.brand, self.model, "正在以", speed, "公里/小时的速度行驶") def change_color(self, c): self.color = c a4 = Car("红色", "奥迪", "A4") a4.run(199) a4.change_color("黑色") a4.run(230)
3.1.2 实例属性调用
-
每个实例可以有自己的变量,称为实例变量(也叫属性)
-
属性的使用语法
实例.属性名
-
属性的赋值规则
- 首次为属性赋值则创建此属性.
- 再次为属性赋值则改变属性的绑定关系.
-
作用
-
记录每个对象自身的数据
-
属性使用示例:
# file : attribute.py
class Dog:
def eat(self, food):
print(self.color, '的', self.kinds, '正在吃', food)
pass
# 创建一个实例:
dog1 = Dog()
dog1.kinds = "京巴" # 添加属性
dog1.color = "白色"
dog1.color = "黄色" # 改变属性的绑定关系
print(dog1.color, '的', dog1.kinds)
dog2 = Dog()
dog2.kinds = "藏獒"
dog2.color = "棕色"
print(dog2.color, '的', dog2.kinds)
- 实例方法和实例属性(实例变量)结合在一起用:
class Dog:
def eat(self, food):
print(self.color, '的',
self.kinds, '正在吃', food)
# 创建第一个对象
dog1 = Dog()
dog1.kinds = '京巴' # 添加属性kinds
dog1.color = '白色' # 添加属性color
# print(dog1.color, '的', dog1.kinds) # 访问属性
dog1.eat("骨头")
dog2 = Dog()
dog2.kinds = '牧羊犬'
dog2.color = '灰色'
# print(dog2.color, '的', dog2.kinds) # 访问属性
dog2.eat('包子')
-
练习:
- 定义一个’人’类:
class Human: def set_info(self, name, age, address='不详'): '''此方法用来给人对象添加'姓名'、'年龄'和 '家庭住址' 属性 # 此处自己实现 def show_info(self): '''此处显示此人的信息''' # 此处自己实现 # 如: s1 = Human() s1.set_info('小张', 20, '北京市朝阳区') s2 = Human() s2.set_info('小李', 18)`` s1.show_info() # 小张 今年 20 岁, 家庭住址: 北京市朝阳区 s2.show_info() # 小李 今年 18 岁, 家庭住址: 不详
3.2 实例方法
class 类名(继承列表):
def 实例方法名(self, 参数1, 参数2, ...):
"文档字符串"
语句块
-
实例方法的作用
-
用于描述一个对象的行为,让此类型的全部对象都拥有相同的行为
-
实例方法说明
- 实例方法的实质是函数,是定义在类内的函数
- 实例方法至少有一个形参,第一个形参绑定调用这个方法的实例,一般命名为"self"
- 实例方法名是类属性
-
实例方法的调用语法
实例.实例方法名(调用传参) # 或 类名.实例方法名(实例, 调用传参)
-
带有实例方法的简单的Dog类
# file: instance_method.py
class Dog:
"""这是一个种小动物的定义
这种动物是狗(犬)类,用于创建各种各样的小狗
"""
def eat(self, food):
'''此方法用来描述小狗吃东西的行为'''
print("小狗正在吃", food)
def sleep(self, hour):
print("小狗睡了", hour, "小时!")
def play(self, obj):
print("小狗正在玩", obj)
dog1 = Dog()
dog1.eat("骨头")
dog1.sleep(1)
dog1.play('球')
dog2 = Dog()
dog2.eat("窝头")
dog2.sleep(2)
dog2.play('飞盘')
>>> help(Dog) # 可以看到Dog类的文档信息
3.3 类属性
-
类属性是类的属性,此属性属于类,不属于此类的实例
-
作用:
- 通常用来存储该类创建的对象的共有属性
-
类属性说明
- 类属性,可以通过该类名直接访问
- 类属性,可以通过cls访问
- 类属性,可以通过类的实例直接访问,比如下面的self.total_count。原因:实例对象会首先查找它自己的命名空间,如果找不到对应的属性,就会向类的命名空间查找。
-
类属性示例
class Human: total_count = 0 # 创建类属性 self.name = name def __init__(self, name): self.name = name print(Human.total_count) h1 = Human("小张") print(h1.total_count)
3.4 类方法
-
类方法是用于描述类的行为的方法,类方法属于类,不属于该类创建的对象
-
说明
- 类方法需要使用@classmethod装饰器定义
- 类方法至少有一个形参,第一个形参用于绑定类,约定写为’cls’
- 类和该类的实例都可以调用类方法
- 类方法不能访问此类创建的对象的实例属性和实例方法
-
类方法示例1
class A: v = 0 @classmethod def set_v(cls, value): # def fun01(self) cls.v = value @classmethod def get_v(cls): return cls.v print(A.get_v()) A.set_v(100) print(A.get_v()) a = A() print(a.get_v())
-
类方法示例2
class MyClass:
class_attr = 0 # 类属性
def __init__(self, value):
self.instance_attr = value # 实例属性
@classmethod
def modify_class_attr(cls, new_value):
cls.class_attr = new_value
print(f"类属性已修改为: {cls.class_attr}")
@classmethod
def try_modify_instance_attr(cls):
try:
cls.instance_attr = 10 # 尝试修改实例属性(会失败)
except AttributeError as e:
print(f"错误: {e}")
def show_attrs(self):
print(f"实例属性: {self.instance_attr}")
print(f"类属性: {self.class_attr}")
# 创建类的实例
obj = MyClass(5)
# 调用类方法修改类属性
MyClass.modify_class_attr(20) # 输出: 类属性已修改为: 20
obj.show_attrs()
# 输出:
# 实例属性: 5
# 类属性: 20
# 调用类方法尝试修改实例属性
MyClass.try_modify_instance_attr()
# 输出: 错误: type object 'MyClass' has no attribute 'instance_attr'
# 尝试调用类方法修改实例属性
obj.try_modify_instance_attr()
# 输出: 错误: type object 'MyClass' has no attribute 'instance_attr'
cls
在Python中,cls
是一个约定俗成的名称,用于表示类本身。在类方法(使用 @classmethod
装饰的方法)中,cls
作为第一个参数传递给方法。这使得类方法可以访问和修改类属性以及调用其他类方法,而不需要引用具体的实例。
cls
的作用
- 访问类属性:类方法可以通过
cls
访问和修改类属性。 - 调用类方法:类方法可以通过
cls
调用其他类方法。 - 创建类实例:类方法可以使用
cls
来创建类的实例。
示例
class MyClass:
class_attr = 0 # 类属性
def __init__(self, value):
self.instance_attr = value # 实例属性
@classmethod
def modify_class_attr(cls, new_value):
cls.class_attr = new_value
print(f"类属性已修改为: {cls.class_attr}")
@classmethod
def show_class_attr(cls):
print(f"类属性当前值: {cls.class_attr}")
@classmethod
def create_instance(cls, value):
# 使用 cls 创建类实例
return cls(value)
# 调用类方法修改类属性
MyClass.modify_class_attr(20) # 输出: 类属性已修改为: 20
# 调用类方法显示类属性
MyClass.show_class_attr() # 输出: 类属性当前值: 20
# 使用类方法创建类的实例
new_instance = MyClass.create_instance(10)
print(f"新实例的实例属性: {new_instance.instance_attr}") # 输出: 新实例的实例属性: 10
print(f"新实例的类属性: {new_instance.class_attr}") # 输出: 新实例的类属性: 20
3.5 静态方法 @staticmethod
-
静态方法是定义在类的内部函数,此函数的作用域是类的内部
-
说明
- 静态方法需要使用@staticmethod装饰器定义
- 静态方法与普通函数定义相同,不需要传入self实例参数和cls类参数
- 静态方法只能凭借该类或类创建的实例调用
- 静态方法的访问可以用对象.静态方法也可以类名.静态方法
- 静态方法可以访问类属性但是不能访问实例属性
-
静态方法示例
class A: class_attr = 42 # 类属性 def __init__(self, value): self.instance_attr = value # 实例属性 @staticmethod def myadd(a, b): # 只能访问传递的参数,不能访问实例属性 return a + b # 创建类实例 a = A(10) # 调用静态方法 print(A.myadd(100, 200)) # 输出: 300 print(a.myadd(300, 400)) # 输出: 700 # 尝试在静态方法内访问实例属性(会导致错误) class B: class_attr = 42 def __init__(self, value): self.instance_attr = value @staticmethod def myadd(a, b): # return a + b + B.class_attr # 以下访问会导致错误 # return a + b + self.instance_attr return a + b # 创建类实例 b = B(10) # 调用静态方法 print(B.myadd(100, 200)) # 输出: 300 print(b.myadd(300, 400)) # 输出: 700
课堂练习
list01 = [
["00","01","02","03","04"],
["10","11","12","13","04"],
["20","21","22","23","34"],
["30","31","32","33","34"],
]
# 需求:30位置上向右获取3个元素 用面向对象的思想
4. 继承/派生
-
什么是继承/派生
- 继承是从已有的类中派生出新的类,新类具有原类的数据属性和行为,并能扩展新的能力。
- 派生类就是从一个已有类中衍生出新类,在新的类上可以添加新的属性和行为
-
为什么继承/派生
- 继承的目的是延续旧的类的功能
- 派生的目地是在旧类的基础上添加新的功能
-
继承/派生的作用
- 用继承派生机制,可以将一些共有功能加在基类中。实现代码的共享。
- 在不改变基类的代码的基础上改变原有类的功能
-
继承/派生名词:
- 基类(base class)/超类(super class)/父类(father class)
- 派生类(derived class)/子类(child class)
4.1 单继承
-
单继承的语法:
class 类名(基类名): 语句块
单继承说明:
-
单继承是指派生类由一个基类衍生出来的
-
单继承的示例1:
class Human: # 人类的共性 def say(self, what): # 说话 print("说:", what) def walk(self, distance): # 走路 print("走了", distance, "公里") class Student(Human): def study(self, subject): # 学习 print("学习:", subject) class Teacher(Human): def teach(self, language): print("教:", language) h1 = Human() h1.say("天气真好!") h1.walk(5) s1 = Student() s1.walk(4) s1.say("感觉有点累") s1.study("python") t1 = Teacher() t1.teach("面向对象") t1.walk(6) t1.say("一会吃点什么好呢")
4.2 多继承
Python支持多继承形式。多继承的类定义形如下例:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中参数位置排前父类的方法
4.3 覆盖 override
-
覆盖是指在有继承关系的类中,子类中实现了与基类同名的方法,在子类的实例调用该方法时,实际调用的是子类中的覆盖版本,这种现象叫覆盖
-
作用:
- 实现和父类同名,但功能不同的方法
-
覆盖示例
class A: def work(self): print("A.work 被调用!") class B(A): '''B类继承自A类''' def work(self): print("B.work 被调用!!!") pass b = B() b.work() # 请问调用谁? B a = A() a.work() # 请问调用谁? A
-
继承练习:
写一个类Bicycle类, 有run方法,调用时显示骑行里程km class Bicycle: def run(self, km): print("自行车骑行了", km, "公里") 再写一个类EBicycle,在Bicycle类的基础上,添加电池电量volume属性,有两个方法: 1. fill_charge(vol) 用来充电, vol 为电量 2. run(km)方法每骑行10km消耗电量1度,同时显示当前电量,当电量耗尽则,则调用Bicycle的run方法 class EBicyle(Bicycle): ...
5. 封装 enclosure
-
封装是指隐藏类的实现细节,让使用者不用关心这些细节;
-
封装的目的是让使用者通过尽可能少的方法(或属性)操作对象
-
Python的封装是假的(模拟的)封装
-
私有属性和方法
- python类中以双下划线(
__
)开头,不以双下划线结尾的标识符为私有成员,私有成员只能使用方法来进行访问和修改- 以
__
开头的属性为类的私有属性,在子类和类外部无法直接使用 - 以
__
开头的方法为私有方法,在子类和类外部无法直接调用
- 以
- python类中以双下划线(
-
私有属性和方法示例:
class A: def __init__(self): self.__p1 = 100 # 私有属性 def __m1(self): # 私有方法 print("__m1(self) 方法被调用") def showA(self): self.__m1() print("self.__p1 = ", self.__p1) class B(A): def __init__(self): super().__init__() def showB(self): self.__m1() # 出错,不允许调用 print("self.__p1 = ", self.__p1) # 出错,不允许调用 # self._A__m1() # 正常调用 # print("self.__p1 =", self._A__p1) # 正常访问 a = A() a.showA() a.__m1() # 出错,不允许调用 v = self.__p1 # 出错,不允许调用 b = B() b.showB() # 访问私有属性 print(a._A__p1) # 输出: 100 # 调用私有方法 a._A__m1() # 输出: __m1(self) 方法被调用 # 不推荐了解就行
6. 多态 polymorphic
-
什么是多态:
- 字面意思"多种状态"
- 多态是指在有继承/派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态
-
状态:
- 静态(编译时状态)
- 动态(运行时状态)
-
多态说明:
- 多态调用的方法与对象相关,不与类型相关
- Python的全部对象都只有"运行时状态(动态)“, 没有"C++语言"里的"编译时状态(静态)”
-
多态示例:
class Shape: def draw(self): print("Shape的draw()被调用") class Point(Shape): def draw(self): print("正在画一个点!") class Circle(Point): def draw(self): print("正在画一个圆!") def my_draw(s): s.draw() # 此处显示出多态 shapes1 = Circle() shapes2 = Point() my_draw(shapes1) # 调用Circle 类中的draw my_draw(shapes2) # Point 类中的draw
-
面向对象编程语言的特征:
- 继承
- 封装
- 多态
7. 方法重写
果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法
7.1 魔术方法
Python中的魔术方法(Magic Methods)是一种特殊的方法,它们以双下划线开头和结尾,例如__init__
,__str__
,__add__
等。这些方法允许您自定义类的行为,以便与内置Python功能(如+运算符、迭代、字符串表示等)交互。
以下是一些常用的Python魔术方法:
__init__(self, ...)
: 初始化对象,通常用于设置对象的属性。__str__(self)
: 定义对象的字符串表示形式,可通过str(object)
或print(object)
调用。例如,您可以返回一个字符串,描述对象的属性。__repr__(self)
: 定义对象的“官方”字符串表示形式,通常用于调试。可通过repr(object)
调用。__len__(self)
: 定义对象的长度,可通过len(object)
调用。通常在自定义容器类中使用。__getitem__(self, key)
: 定义对象的索引操作,使对象可被像列表或字典一样索引。例如,object[key]
。__setitem__(self, key, value)
: 定义对象的赋值操作,使对象可像列表或字典一样赋值。例如,object[key] = value
。__delitem__(self, key)
: 定义对象的删除操作,使对象可像列表或字典一样删除元素。例如,del object[key]
。__iter__(self)
: 定义迭代器,使对象可迭代,可用于for
循环。__next__(self)
: 定义迭代器的下一个元素,通常与__iter__
一起使用。__add__(self, other)
: 定义对象相加的行为,使对象可以使用+
运算符相加。例如,object1 + object2
。__sub__(self, other)
: 定义对象相减的行为,使对象可以使用-
运算符相减。__eq__(self, other)
: 定义对象相等性的行为,使对象可以使用==
运算符比较。__lt__(self, other)
: 定义对象小于其他对象的行为,使对象可以使用<
运算符比较。__gt__(self, other)
: 定义对象大于其他对象的行为,使对象可以使用>
运算符比较。__call__(self, other)
是一个特殊的方法(也称为“魔法方法”),它允许一个对象像函数一样被调用。
一些参考代码
1.__init__(self, ...)
: 初始化对象
class MyClass:
def __init__(self, value):
self.value = value
obj = MyClass(42)
2.对象转字符串函数重写方法
-
str() 函数的重载方法:
def __str__(self)
- 如果没有
__str__(self)
方法,则返回repr(obj)函数结果代替
- 如果没有
-
str函数重写示例
class MyClass:
def __init__(self, value):
self.value = value
def __str__(self):
return f"MyClass instance with value: {self.value}"
obj = MyClass(42)
print(obj) # 输出:MyClass instance with value: 42
3.__repr__(self)
: 官方字符串表示形式
class MyClass:
def __init__(self, value):
self.value = value
def __repr__(self):
return f"MyClass({self.value})"
#def __repr__(self):
#return f"Person(name={self.name}, age={self.age})"
obj = MyClass(42)
print(obj) # 输出:MyClass(42)
4.__len__(self)
: 定义对象的长度
class MyList:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
my_list = MyList([1, 2, 3, 4])
print(len(my_list)) # 输出:4
5.__getitem__(self, key)
: 索引操作
class MyDict:
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data.get(key)
my_dict = MyDict()
my_dict.data = {'key1': 'value1', 'key2': 'value2'}
print(my_dict['key1']) # 输出:value1
6.__setitem__(self, key, value)
: 赋值操作
class MyDict:
def __init__(self):
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
my_dict = MyDict()
my_dict['key1'] = 'value1'
print(my_dict.data) # 输出:{'key1': 'value1'}
7.__delitem__(self, key)
: 删除操作
class MyDict:
def __init__(self):
self.data = {}
def __delitem__(self, key):
del self.data[key]
my_dict = MyDict()
my_dict.data = {'key1': 'value1', 'key2': 'value2'}
del my_dict['key2']
print(my_dict.data) # 输出:{'key1': 'value1'}
8.__iter__(self)
: 迭代器
class MyIterable:
def __init__(self):
self.data = [1, 2, 3, 4]
def __iter__(self):
self.index = 0
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
my_iterable = MyIterable()
for item in my_iterable:
print(item)
# 输出:1, 2, 3, 4
9.__call__(self, *args, **kwargs)
class MyCallable:
def __call__(self, *args, **kwargs):
print("Called with arguments:", args, kwargs)
# 创建类的实例
my_callable = MyCallable()
# 像调用函数一样调用实例
my_callable(1, 2, 3, key="value")
7.2 内建函数重写
在自定义类内添加相应的方法,让自定义类创建的实例像内建对象一样进行内建函数操作
-
__abs__
abs(obj) 函数调用 -
__len__
len(obj) 函数调用 -
__reversed__
reversed(obj) 函数调用 -
__round__
round(obj) 函数调用 -
内建函数 重写示例
# file : len_overwrite.py class MyList: def __init__(self, iterable=()): self.data = [x for x in iterable] def __repr_(self): return "MyList(%s)" % self.data def __len__(self): print("__len__(self) 被调用!") return len(self.data) def __abs__(self): print("__len__(self) 被调用!") return MyList((abs(x) for x in self.data)) myl = MyList([1, -2, 3, -4]) print(len(myl)) print(abs(myl))
7.3 算术运算符重载
-
运算符重载是指让自定义的类生成的对象(实例)能够使用运算符进行操作
-
运算符重载的作用
- 让自定义类的实例像内建对象一样进行运算符操作
- 让程序简洁易读
- 对自定义对象将运算符赋予新的运算规则
-
运算符重载说明:
- 运算符重载方法的参数已经有固定的含义,不建议改变原有的意义
方法名 | 运算符和表达式 | 说明 |
---|---|---|
__add__(self, rhs) | self + rhs | 加法 |
__sub__(self, rhs) | self - rhs | 减法 |
__mul__(self, rhs) | self * rhs | 乘法 |
__truediv__(self, rhs) | self / rhs | 除法 |
__floordiv__(self, rhs) | self // rhs | 地板除 |
__mod__(self, rhs) | self % rhs | 取模(求余) |
__pow__(self, rhs) | self ** rhs | 幂 |
rhs (right hand side) 右手边
-
二元运算符重载方法格式:
def __xxx__(self, other): ....
-
算术运算符重载示例
class MyNumber: "此类用于定义一个自定义的类,用于演示运算符重载" def __init__(self, value): "构造函数,初始化MyNumber对象" self.data = value def __str__(self): "转换为表达式字符串" return "MyNumber(%d)" % self.data def __add__(self, rhs): "加号运算符重载" print("__add__ is called") return MyNumber(self.data + rhs.data) def __sub__(self, rhs): "减号运算符重载" print("__sub__ is called") return MyNumber(self.data - rhs.data) n1 = MyNumber(100) n2 = MyNumber(200) print(n1 + n2) print(n1 - n2)
8. super函数
super() 函数是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
如何解决问题
super()
解决多继承问题的关键在于 MRO(方法解析顺序),即 Python 按照某种顺序(通常是从左到右)依次调用继承链中的方法。super()
总是会调用下一个类的 process()
,而不会重复调用同一个类的方法。
使用 super()
时,Python 会动态查找类继承链中的下一个类。通过 MRO,避免了手动调用时可能发生的重复调用。
super() 方法的语法:
在子类方法中可以使用super().add()调用父类中已被覆盖的方法
可以使用super(Child, obj).myMethod()用子类对象调用父类已被覆盖的方法
class A:
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
print("子类方法")
super().add(x)
b = B()
b.add(2) # 3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child()# 子类实例
c.myMethod()# 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
super().init()
super().__init__()
是 Python 中用于调用父类(基类)构造函数的一种方式。它通常用于子类的构造函数中,以确保父类的构造函数被正确调用和初始化。这在继承(inheritance)中尤为重要,因为父类的初始化代码可能包含设置实例变量或执行其他重要的初始化任务。
class Parent:
def __init__(self, parent_param):
print("父类构造函数被调用")
self.parent_attribute = parent_param # 使用传入的参数初始化父类属性
class Child(Parent):
def __init__(self, parent_param, child_param):
super().__init__(parent_param) # 调用父类的构造函数并传递参数
print("子类构造函数被调用")
self.child_attribute = child_param # 使用传入的参数初始化子类属性
# 创建 Child 类的实例
child_instance = Child("I am a parent attribute", "I am a child attribute")
# 访问属性
print(child_instance.parent_attribute) # 输出: I am a parent attribute
print(child_instance.child_attribute) # 输出: I am a child attribute
注释
- Parent 类:
- 定义了一个构造函数
__init__()
,在构造函数中打印了一条消息,并初始化了一个属性parent_attribute
。
- 定义了一个构造函数
- Child 类:
- 继承自
Parent
类。 - 在其构造函数
__init__()
中,首先调用了super().__init__()
。这行代码会调用Parent
类的构造函数,确保Parent
类的初始化逻辑被执行。 - 然后打印了一条消息,并初始化了一个属性
child_attribute
。
- 继承自
- 实例化 Child 类:
- 创建
Child
类的实例时,首先执行Parent
类的构造函数,打印 “Parent class constructor called”,然后执行Child
类的构造函数,打印 “Child class constructor called”。
- 创建
为什么使用 super().__init__()
?
- 代码重用:避免在子类中重复父类的初始化代码。
- 正确初始化:确保父类的初始化逻辑(如设置属性、分配资源等)被执行。
- 支持多重继承:在多重继承情况下,
super()
可以确保所有基类的构造函数都被正确调用。
举例
class Attention(nn.Module):
def __init__(self, dim, heads=8, dim_head=64, dropout=0.):
super().__init__()
inner_dim = dim_head * heads # 计算内部维度
project_out = not (heads == 1 and dim_head == dim) # 判断是否需要投影输出
在之后的深度学习方法中经常见 **super().__init__()
**的用法
三、Python异常
-
作用
用作信号通知,通知上层调用者有错误产生需要处理
1. try 语句
- 语法
try:
可能发生异常的语句块
except 错误类型1 [as 变量名1]:
异常处理语句块1
except 错误类型2 [as 变量名2]:
异常处理语句块2
...
except 错误类型n [as 变量名n]:
异常处理语句块n
except:
异常处理语句块other
else:
未发生异常的语句
finally:
最终的处理语句
-
作用
尝试捕获异常,得到异常通知,将程序由异常状态变为正常状态
-
说明
except 子句可以有 1个或多个
except: 不给错误类型,可以匹配全部的错误类型
else 子句里的语句会在 没有错误发生时执行,当处于异常时不执行
finally 子句里的语句,无论何时都执行
-
示例
try:
x = int(input("请输入一个整数:"))
print('x=', x)
except ValueError:
print('您的输入不能转成整数')
print("程序结束")
2. raise 语句
-
问题
# 写一个函数, get_score 函数,读取用户输入的整数成绩, # 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间 # 报 ValueError类型的错误 def get_score(): x = int(input('请输入成绩:')) if 0 <= x <= 100: return x raise ValueError
-
语法
raise 异常类型 或 raise 异常对象
-
作用
- 抛出一个错误,让程序进入异常状态
- 发送错误通知给调用者
-
示例:
## 写一个函数, get_score 函数,读取用户输入的整数成绩,
## 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间
## 报 ValueError类型的错误
def get_score():
x = int(input('请输入成绩:'))
if 0 <= x <= 100:
return x
# raise ValueError
raise ValueError('用户输入的成绩不在 0~100 之间')
try:
score = get_score()
print(score)
except ValueError as err:
print("成绩输入有误 err=", err)
err的作用就是接收raise ValueError(‘用户输入的成绩不在 0~100 之间’)给出的提示信息
-
异常类型的可选种类
详见:
>>> help(__builtins__)
-
课后练习1
写一个猜拳游戏: 石头,剪刀,布, 让电脑随机生成一个, 你的输入如下: 0) 石头 1) 剪刀 2) 布 q) 退出 请选择: 0 电脑出的是 布 ,你输了 循环输入,知道输入q 为止 如果用户输入的不是题目要求的内容报错SyntaxError
-
课后练习2
写一个猜数字游戏 让电脑随机生成一个 0 ~ 100 的整数让用来猜 如果 您输入的数大于电脑生产的数,提示:“您猜大了”, 继续猜 如果 您输入的数小于电脑生产的数,提示:“您猜小了”, 继续猜 当 您输入的数等于电脑生产的数,提示:"恭喜您猜对了" 打印猜的次数后退出程序
3.Python全部的错误类型
错误类型 | 说明 |
---|---|
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
ValueError | 传入无效的参数 |
AssertionError | 断言语句失败 |
StopIteration | 迭代器没有更多的值 |
IndexError | 序列中没有此索引(index) |
IndentationError | 缩进错误 |
OSError | 输入/输出操作失败 |
ImportError | 导入模块/对象失败 |
NameError | 未声明/初始化对象 (没有属性) |
AttributeError | 对象没有这个属性 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
TypeError | 对类型无效的操作 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
OverflowError | 数值运算超出最大限制 |
FloatingPointError | 浮点计算错误 |
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
Exception | 常规错误的基类 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
WindowsError | 系统调用失败 |
LookupError | 无效数据查询的基类 |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError Python | 语法错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
以下为警告类型 | |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
详见:help(builtins)
课后练习
写一个函数 get_age() 用来获取一个人的年龄信息
此函数规定用户只能输入1~140之间的整数,如果用户输入其它的数则直接触发ValueError类型的错误!
四、Python迭代器与生成器
1. 迭代器 Iterator
什么是迭代器
- 迭代器是访问可迭代对象的工具
- 迭代器是指用 iter(obj) 函数返回的对象(实例)
- 迭代器可以用next(it)函数获取可迭代对象的数据
迭代器函数iter和next
函数 | 说明 |
---|---|
iter(iterable) | 从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象 |
next(iterator) | 从迭代器iterator中获取下一个记录,如果无法获取一下条记录,则触发 StopIteration 异常 |
迭代器说明
- 迭代器只能往前取值,不会后退
- 用iter函数可以返回一个可迭代对象的迭代器
迭代器示例:
# 示例 可迭代对象
L = [1, 3, 5, 7]
it = iter(L) # 从L对象中获取迭代器
next(it) # 1 从迭代器中提取一个数据
next(it) # 3
next(it) # 5
next(it) # 7
next(it) # StopIteration 异常
# 示例2 生成器函数
It = iter(range(1, 10, 3))
next(It) # 1
next(It) # 4
next(It) # 7
next(It) # StopIteration
迭代器的用途
- 迭代器对象能用next函数获取下一个元素
迭代器函数iter和next 示例:
L = [2, 3, 5, 7]
it = iter(L)
# 访问列表中的所有元素
while True:
try:
print(next(it))
except StopIteration:
print("迭代器访问结束")
break
L = [2, 3, 5, 7]
for x in L:
print(x)
else:
print("迭代器访问结束")
2. 生成器
生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。
-
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
-
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
-
每次使用 yield 语句生产一个值后,函数都将暂停执行,等待被重新唤醒。
-
yield 语句相比于 return 语句,差别就在于 yield 语句返回的是可迭代对象,而 return 返回的为不可迭代对象。
-
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。
生成器可以用算法动态的生成数据
生成器有两种
- 生成器函数
- 生成器表达式
生成器函数
含有yield 语句的函数是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象
yield 语句的语法
yield 表达式
生成器函数示例1:
## 定义一个生成器函数, 有 yield 的函数调用后回返回生成器对象
def myrange(stop):
i = 0
while i < stop:
、yield i # 为 遍历次生产器的for 语句提供数据
i += 1
for x in myrange(5):
print('x=', x)
# 创建一个生成器对象
gen = myrange(5)
# 使用 next() 函数迭代生成器
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
生成器函数示例2:
def Descendorder(n):
while n > 0:
yield n
n -= 1
# 创建生成器对象
generator = Descendorder(5)
# 通过迭代生成器获取值
print(next(generator))#5
print(next(generator))#4
# 使用 for 循环迭代生成器
for i in generator:
print('for循环:', i)#3 2 1
以上实例中,Descendorder 函数是一个生成器函数。它使用 yield 语句逐步产生从 n 到 1 的倒序数字。在每次调用 yield 语句时,函数会返回当前的倒序数字,并在下一次调用时从上次暂停的地方继续执行。
创建生成器对象并使用 next() 函数或 for 循环迭代生成器,我们可以逐步获取生成器函数产生的值。在这个例子中,我们首先使用 next() 函数获取前两个倒序数字,然后通过 for 循环获取剩下的三个倒序数字。
生成器函数的优势是它们可以按需生成值,避免一次性生成大量数据并占用大量内存。此外,生成器还可以与其他迭代工具(如for循环)无缝配合使用,提供简洁和高效的迭代方式。
生成器表达式
- 语法:
( 表达式 for 变量 in 可迭代对象 [if 真值表达式])
[] 内容代表可以省略
-
作用
用推导式的形式创建一个生成器
-
示例
>>> [x ** 2 for x in range(1, 5)] # 列表解析(列表推导式)
[1, 4, 9, 16]
>>>
>>> (x ** 2 for x in range(1, 5)) # 生成器表达式
<generator object <genexpr> at 0x7f41dcd30a40>
>>> for y in (x ** 2 for x in range(1, 5)):
... print(y)
...
1
4
9
16
练习
代码实现斐波那契数列(最少十个数)
五、python 函数式编程
定义:用一系列函数解决问题。
- 函数可以赋值给变量,赋值后变量绑定函数。
- 允许将函数作为参数传入另一个函数。
- 允许函数返回一个函数。
1. 函数作为参数
- 将核心逻辑传入方法体,使该方法的适用性更广。
示例1:
def func01():
print("func01执行")
# a = func01
# # print(a)
# a()
def func02():
print("func02执行")
# 通用
def func03(func):
print("func03执行")
func()
func03(func02)
func03(func01)
注释
a = func01
:
- 变量
a
现在指向func01
函数对象。 a
不是函数的返回值,而是函数对象本身
print(a)
:
- 打印
a
,输出<function func01 at 0x...>
,表示a
是一个函数对象,并显示其内存地址。
赋值语句 a = func01
并不会执行 func01
函数,只是将函数对象赋值给 a
。调用 a()
或 func01()
才会执行函数代码。
示例2:
list01 = [4, 54, 56, 65, 67, 7]
# 需求1:定义函数,在列表中查找所有大于50的数字
def find01():
for item in list01:
if item > 50:
yield item
# 需求2:定义函数,在列表中查找所有小于10的数字
def find02():
for item in list01:
if item < 10:
yield item
# “封装” -- 分
def condition01(item):
return item > 50
def condition02(item):
return item < 10
# 通用
# “继承” - 隔
def find(func):
for item in list01:
# if item < 10:
# if condition02(item):
if func(item):
yield item
# "多态" - 做
for item in find(condition01):
print(item)
for item in find(condition02):
print(item)
总结
1、什么时候使用函数式编程思想?
很多的逻辑或者说核心点是不变的,大多数就是一致的,这个时候我们就可以使用函数式编程思想,可以很好的去定位这个逻辑【函数 式编程思想相对于面向对象编程思想,它更接近于算法】。
2、函数式编程思想替代了面向对象思想?
如果需求中存在多个逻辑变化点时,可以使用类来进行,因为面向对象中存在继承、重写。而函数式编程思想则是将变化点提取到函数 中,实现简单的逻辑。
练习
"""
练习1:在美女列表中,查找颜值大于90的所有美女
练习2:在美女列表中,查找身高小于170的所有美女
"""
class Wife:
def __init__(self, name="", face_score=0, age=0, height=0):
self.name = name
self.face_score = face_score
self.age = age
self.height = height
list_girl = [
Wife("双儿", 96, 22, 166),
Wife("阿珂", 100, 23, 173),
Wife("小郡主", 96, 22, 161),
Wife("方怡", 86, 27, 166),
Wife("苏荃", 99, 31, 176),
Wife("建宁", 93, 24, 163),
Wife("曾柔", 88, 26, 170),
]
def find01():
for item in list_girl:
if item.face_score > 90:
yield item
def find02():
for item in list_girl:
if item.height < 170:
yield item
def condition01(item):
return item.face_score > 90
def condition02(item):
return item.height < 170
def find(func):
for item in list_girl:
# if item.face_score > 90:
# if condition01(item):
if func(item):
yield item
for item in find(condition01):
print(item.name)
for item in find(condition02):
print(item.name)
1.1.1 lambda 表达式
- 定义:是一种匿名函数
作用:
– 作为参数传递时语法简洁,优雅,代码可读性强。
– 随时创建和销毁,减少程序耦合度。
语法
# 定义:
变量 = lambda 形参: 方法体
# 调用:
变量(实参)
说明:
– 形参没有可以不填
– 方法体只能有一条语句,且不支持赋值语句。
# 1. 有参数有返回值
# def func01(a,b):
# return a > b
#
# print(func01(10,20))
func01 = lambda a,b:a > b
print(func01(10,20))
# 2. 无参数有返回值
# def func02():
# return "ok"
#
# print(func02())
func02 = lambda :"ok"
print(func02())
# 3. 无参数无返回值
# def func03():
# print("ok")
#
# func03()
func03 = lambda :print("ok")
func03()
# 4. 有参数无返回值
# def func03(a):
# print(a)
#
# func03(100)
func03 = lambda a:print(a)
func03(100)
# 5. lambda 不支持赋值语句
# def func05(iterable):
# iterable[0] = 100
#
# list01 = [1]
# func05(list01)
# print(list01)
# func05 = lambda iterable: iterable[0] = 100 报错
# 6. lambda 不支持多条语句
# def func06(a,b):
# print(a)
# print(b)
#
# func06(10,20)
# func06 = lambda a,b: print(a);print(b)
直接使用的函数ss
**直接使用的函数**
**zip**
**功能:** zip 函数用于将多个可迭代对象中的元素打包成元组,返回一个可迭代的 zip 对象。
```
示例:
result = zip([1, 2, 3], ['a', 'b', 'c'])
print(list(result)) # 输出: [(1, 'a'), (2, 'b'), (3, 'c')]
```
**sum**
**功能:** sum 函数用于对可迭代对象中的元素求和。
```
示例:
result = sum([1, 2, 3, 4])
print(result) # 输出: 10
```
**`eval`**
**功能**: `eval` 函数用于执行一个字符串表达式,并返回表达式的值。
```
result = eval('1 + 2 + 3')
print(result) # 输出: 6
```
**示例**
1.2 内置高阶函数
定义:将函数作为参数或返回值的函数。
常用:
(1)map(函数,可迭代对象)
- 使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
(2)filter(函数,可迭代对象)
- 根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
(3)sorted(可迭代对象, key=函数, reverse=True)
- 排序,返回值为排序后的列表结果。
(4)max(可迭代对象, key = 函数)
- 根据函数获取可迭代对象的最大值。
(5)min(可迭代对象,key = 函数)
- 根据函数获取可迭代对象的最小值。
示例
class Girl:
def __init__(self, name="", face_score=0, age=0, height=0):
self.name = name
self.face_score = face_score
self.age = age
self.height = height
def __str__(self):
return "%s-%d-%d-%d" % (self.name, self.face_score, self.age, self.height)
list_girl = [
Girl("双儿", 96, 22, 166),
Girl("阿珂", 100, 23, 173),
Girl("小郡主", 96, 22, 161),
Girl("方怡", 86, 27, 166),
Girl("苏荃", 99, 31, 176),
Girl("建宁", 93, 24, 163),
Girl("曾柔", 88, 26, 170),
]
2. 函数作为返回值
2.1 闭包 closure
什么是闭包?
-
闭包是指引用了此函数外部嵌套函数的变量的函数
闭包就是能够读取其他函数内部变量的函数。只有函数内部的嵌套函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数,同时这个函数又引用了外部的变量“。 -
在本质上,闭包是将内部嵌套函数和函数外部的执行环境绑定在一起的对象。
闭包必须满足以下三个条件:
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数中变量
- 外部函数返回值必须是内嵌函数。
思考全局变量和局部变量的区别
- 全局变量
- 一直存在,谁都可以访问和修改
- 局部变量
- 只是在调用时存在,只能在函数内部进行访问和修改
闭包的优缺点
优点
1. 逻辑连续,当闭包作为另一个函数调用参数时,避免脱离当前逻辑而单独编写额外逻辑。
2. 方便调用上下文的局部变量。
3. 加强封装性,是第2点的延伸,可以达到对变量的保护作用。
使用闭包的注意点(缺点)
1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包
2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
示例
# file : closure.py
def make_power(y):
def fn(x):
return x ** y
return fn
pow2 = make_power(2)
print("5的平方是:", pow2(5))
pow3 = make_power(3)
print("6的立方是:", pow3(6))
2.2 装饰器 decorators(专业提高篇)
什么是装饰器
- 装饰器是一个函数,主要作用是来用包装另一个函数或类
装饰器的作用:
- 在不修改被装饰的函数的源代码,不改变被装饰的函数的调用方式的情况下添加或改变原函数的功能。
函数装饰器的语法:
def 装饰器函数名(fn):
语句块
return 函数对象
@装饰器函数名 <换行>
def 被装饰函数名(形参列表):
语句块
用函数装饰器替换原函数myfun
def mydeco(fn):
fn()
print("装饰器函数被调用了,并返回了fx")
def fx():
print("fx被调用了")
# return fn()
return fx
@ mydeco
def myfun():
print("函数myfun被调用")
myfun()
myfun()
当使用@mydeco
语法装饰myfun
函数时,实际上发生的是:
myfun
函数作为参数传递给了mydeco
装饰器。- 在
mydeco
内部,首先调用了fn()
,即此时调用了myfun
函数,产生了输出:“函数myfun被调用”。 - 接着,打印了"装饰器函数被调用了,并返回了fx"。
- 然后,
mydeco
装饰器返回了新的函数fx
。
因此,此刻myfun
实际上被替换成了新的函数fx
。这样的行为正是Python装饰器的特性之一:装饰器可以修改函数的行为,甚至完全替换被装饰的函数。
2.2.1 基本装饰器
有参数的函数装饰器(在myfunc外加了一层)
def mydeco(fn):
def fx():
print("====这是myfunc被调用之前====")
ret = fn()
print("----这是myfunc被调用之后====")
return ret
return fx
@mydeco
def myfunc():
print("myfunc被调用.")
myfunc()
myfunc()
myfunc()
2.2.2 带参数的装饰器
def repeat(num):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3) # 应用装饰器,重复执行下面的函数3次
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 调用被装饰的函数
repeat
是一个接受参数的装饰器工厂函数,它返回一个装饰器。decorator
是真正的装饰器,它接受一个函数func
作为参数。wrapper
函数重复执行被装饰的函数num
次。- 使用
@repeat(3)
应用装饰器,使greet
函数被执行3次。
注意:带参数的装饰器需要三层函数,def wrapper(args, kwargs) 传入的是被修饰的函数的参数。
2.2.3 装饰器链
def uppercase(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def exclamation(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + "!"
return wrapper
@exclamation
@uppercase
def say_hello(name):
return f"Hello, {name}"
greeting = say_hello("Bob")
print(greeting) # 输出 "HELLO, BOB!"
具体的执行过程如下:
- 装饰器是从内到外依次应用的。在你的代码中,首先应用的是
@uppercase
,然后是@exclamation
。 @uppercase
装饰器会先包裹say_hello
函数,然后@exclamation
装饰器再包裹已经被@uppercase
包裹过的函数。
步骤详细如下:
- 首先
@uppercase
包装say_hello
函数:- 调用
say_hello("Bob")
返回"Hello, Bob"
。 @uppercase
装饰器的wrapper
函数将结果转换为大写,变为"HELLO, BOB"
。
- 调用
- 然后
@exclamation
包装已经被@uppercase
包装过的say_hello
函数:- 调用
wrapper
(即@uppercase
装饰器的wrapper
函数)返回"HELLO, BOB"
。 @exclamation
装饰器的wrapper
函数将结果加上一个感叹号,变为"HELLO, BOB!"
。
- 调用
say_hello("Bob") -> "Hello, Bob"
"Hello, Bob" -> @uppercase -> "HELLO, BOB"
"HELLO, BOB" -> @exclamation -> "HELLO, BOB!"
``
2.2.4 类装饰器
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Something is happening before the function is called.")
result = self.func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
@MyDecorator # 应用类装饰器
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Charlie") # 调用被装饰的函数
-
MyDecorator
是一个类装饰器,它接受一个函数func
作为参数并在__call__
方法中执行额外操作。 -
使用
@MyDecorator
应用类装饰器,它将包装say_hello
方法,使其在调用前后执行额外操作。 -
与基本装饰器类似
Python包和模块
当使用Python编程时,包(Packages)和模块(Modules)是两个关键的概念,它们有助于组织、管理和复用代码。
1. 模块(Modules)
1.1 什么是模块
一个.py 文件就是一个模块
模块是含有一系列数据,函数,类等的程序
-
作用
把相关功能的函数等放在一起有利于管理,有利于多人合作开发
-
模块的分类
- 内置模块(在python3 程序内部,可以直接使用)
- 标准库模块(在python3 安装完后就可以使用的 )
- 第三方模块(需要下载安装后才能使用)
- 自定义模块(用户自己编写)
模块名如果要给别的程序导入,则模块名必须是 标识符
-
实例
## file: mymod.py
'''
小张写了一个模块,内部有两个函数,两个字符串
... 此处省略 200字
'''
name1 = 'audi'
name2 = 'tesla'
def mysum(n):
'''
此函数用来求和
by weimingze
'''
print("正在计算, 1 + 2 + 3 + .... + n的和 ")
def get_name():
return "tarena"
调用模块
## file: test_mod.py
## 小李写的程序,小李想调用 小张写的 mymod.py 里的两个函数和两个字符串
## 用import 语句导入模块
import mymod
print(mymod.name1) # Audi
print(mymod.name2) # tesla
mymod.mysum(100) # 调用 mymod 模块里的 mysum 函数
print(mymod.get_name()) # 'tarena'
1.2 导入模块
- 语法
-
import 模块名 [as 模块新名字1]
导入一个模块到当前程序
-
from 模块名 import 模块属性名 [as 属性新名]
导入一个模块内部的部分属性到当前程序
-
from 模块名 import *
导入一个模块内部的全部属性到当前程序
-
示例
import mymod mymod.mysum(10) # 要加模块名 from mymod import get_name print(get_name()) # 调用get_name 时不需要加 "模块名." from mymod import * print(get_name()) print(name2)
-
模块的内部属性
__file__ 绑定模块的路径 __name__ 绑定模块的名称 如果是主模块(首先启动的模块)则绑定 '__main__' 如果不是主模块则 绑定 xxx.py 中的 xxx 这个模块名
-
示例
见: test_mymod.py 和 mymod.py
-
模块的
__name__
属性每个.py 模块文件都会有
__name__
属性-
当一个模块是最先运行的模块,则这个模块是主模块, 主模块的
__name__
属性绑定'__main__'
字符串 -
如果一个模块是用 三种 import 语句中的一个导入的模块,则此模块不是主模块。
不是主模块的模块的
__name__
绑定的 模块名
-
-
主模块 (
__name__
=='__main__'
): 当一个模块是直接运行的,即不是通过import
语句导入的,那么它的__name__
属性会被赋值为'__main__'
。例如:
# main_module.py
if __name__ == "__main__":
print("This is the main module.")
如果运行 python main_module.py
,输出将是:
This is the main module.
- 被导入的模块 (
__name__
== 模块名): 当一个模块被导入到另一个模块中时,它的__name__
属性会被赋值为它的模块名。例如:
# imported_module.py
print(f"This module's name is {__name__}") # 被其他模块导入时会自动运行
# main_module.py
import imported_module
if __name__ == "__main__":
print("This is the main module.")
如果运行 python main_module.py
,输出将是:
This module's name is imported_module
This is the main module.
这里 imported_module.py
被导入到 main_module.py
中,所以它的 __name__
是 'imported_module'
,而 main_module.py
是直接运行的,所以它的 __name__
是 '__main__'
。
python 的第三方模块
https://pypi.org/
- 使用导入的模块中的函数、变量等,可以通过模块名或从语句中导入的名称来访问。
1.3 Python 常用的内建模块
1.3.1 random 模块
先引入random库基础库:
import random
函数 | 描述 |
---|---|
random.choice(seq) | 从序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数。 |
random.randrange (start, stop,step) | 从指定范围内,按指定基数递增的集合中获取一个随机数,基数默认值为 1 |
random.random() | 随机生成下一个实数,它在[0,1)范围内。 |
random.shuffle(list) | 将序列的所有元素随机排序,修改原list |
uniform(x, y) | 随机生成实数,它在[x,y]范围内. |
生成随机数
文档位置: https://docs.python.org/zh-cn/3/library/random.html
>>> import random
>>> random.randint(1, 6) # random.randint(a,b) 生产 a~b的随机整数
3
>>> random.randint(1, 6)
4
>>> random.random() # random.random 生成包含0 但不包含1 的浮点数
0.5884109388439075
>>> random.choice("ABCD") # 从一个序列中,随机返回一个元素
'C'
>>> random.choice("ABCD")
'B'
>>> L = [1, 2, 3, 6, 9]
>>> random.choice(L)
6
>>> random.shuffle(L) # random.shuffer(x) # 把列表X 打乱
>>> L
[1, 6, 2, 9, 3]
- 课后练习
写一个程序, 生产6位由数字组成的随机密码
参考答案
import random
## 生成 n 位的数字密码
def get_random_password(n):
r_str = ''
for _ in range(n):
r_str += str(random.randint(0, 9))
return r_str
## 生成 n 位的数字和字母组成的密码
charactors = '0123456789abcdefghijklmnopqrstwuxyz'
def get_random_password2(n):
r_str = ''
for _ in range(n):
r_str += random.choice(charactors)
return r_str
print(get_random_password(6))
print(get_random_password(6))
import time
time.sleep(10)
print(get_random_password2(10))
1.3.2 time 模块
https://docs.python.org/zh-cn/3/library/time.html
时间戳:从 1970年1月1日 0:0:0 UTC 时间 开始计时到现在的秒数
UTC 时间 : 世界协调时间
struct_time 用 含有9个元素的元组来表示时间
>>> import time
>>> time.time() # 返回当前时间的时间戳
1617117219.0382686
>>> time.ctime() #返回当前的UTC 时间的字符串
'Tue Mar 30 23:14:48 2021'
>>> t1 = time.localtime() # 返回当前的本地时间元组
>>> t1
time.struct_time(tm_year=2021, tm_mon=3, tm_mday=30, tm_hour=23, tm_min=18, tm_sec=22, tm_wday=1, tm_yday=89, tm_isdst=0)
>>> t1.tm_year
2021
>>> t1.tm_yday
89
>>> time.sleep(3) # time.sleep(n) # 让程序睡眠 n 秒
>>> time.strftime("%Y-%m-%d", t1) # 格式化时间
'2021-03-30'
>>> time.strftime("%y-%m-%d", t1)
'21-03-30'
>>> time.strftime('%Y-%m-%d %H:%M:%S', t1)
'2021-07-21 17:37:41'
# 用时间元组来创建一个自定义的时间
>>> t2 = time.struct_time ( (2021,1, 1, 10, 11, 20, 0, 0, 0) )
1.3.3 math 模块
先引入math模块:
import math
- math模块中定义的函数
函数 | 返回值 ( 描述 ) |
---|---|
abs(x) | 返回数字的绝对值,如abs(-10) 返回 10 |
math.ceil(x) | 返回数字的上入整数,如math.ceil(4.1) 返回 5 |
cmp(x, y) | 如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。 Python 3 已废弃,使用 (x>y)-(x<y) 替换。 |
math.exp(x) | 返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045 |
math.fabs(x) | 以浮点数形式返回数字的绝对值,如math.fabs(-10) 返回10.0 |
math.floor(x) | 返回数字的下舍整数,如math.floor(4.9)返回 4 |
math.log(x) | 如math.log(math.e)返回1.0,math.log(100,10)返回2.0 |
math.log10(x) | 返回以10为基数的x的对数,如math.log10(100)返回 2.0 |
max(x1, x2,…) | 返回给定参数的最大值,参数可以为序列。 |
min(x1, x2,…) | 返回给定参数的最小值,参数可以为序列。 |
math.modf(x) | 返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。 |
math.pow(x, y) | x**y 运算后的值。 |
round(x ,n) | 返回浮点数 x 的四舍五入值,如给出 n 值,则代表舍入到小数点后的位数。其实准确的说是保留值将保留到离上一位更近的一端。 1.保留整数只有一个小数时:4舍6入5看齐,奇进偶不进 2.保留整数或小数超过一个小数时:看保留位的下下位是否存在 |
math.sqrt(x) | 返回数字x的平方根。 |
1. math.sqrt(x)
计算 x 的平方根。
import math
result = math.sqrt(16)
print(result) # 输出: 4.0
2. math.pow(x, y)
计算 x 的 y 次方。
import math
result = math.pow(2, 3)
print(result) # 输出: 8.0
3. math.exp(x)
计算 e 的 x 次方。
import math
result = math.exp(2)
print(result) # 输出: 7.3890560989306495
4. math.log(value,base)
计算以 base 为底的 value 的对数。如果没有指定 base,则计算e为底数的值。
import math
result = math.log(8, 2)
print(result) # 输出: 3.0
result = math.log(10)
print(result) # 输出: 2.302585092994046 (自然对数)
5. math.sin(x)
计算 x 的正弦值,x 以弧度表示。
import math
result = math.sin(math.pi / 2)
print(result) # 输出: 1.0
6. math.cos(x)
计算 x 的余弦值,x 以弧度表示。
import math
result = math.cos(0)
print(result) # 输出: 1.0
7. math.tan(x)
import math
result = math.tan(math.pi / 4)
print(result) # 输出: 0.9999999999999999 (接近于 1)
三角函数
函数 | 描述 |
---|---|
math.acos(x) | 返回x的反余弦弧度值。 |
math.asin(x) | 返回x的反正弦弧度值。 |
math.atan(x) | 返回x的反正切弧度值。 |
math.atan2(y, x) | 返回给定的 X 及 Y 坐标值的反正切值。 |
math.cos(x) | 返回x的弧度的余弦值。 |
math.sin(x) | 返回的x弧度的正弦值。 |
math.tan(x) | 返回x弧度的正切值。 |
math.degrees(x) | 将弧度转换为角度,如degrees(math.pi/2) , 返回90.0 |
math.radians(x) | 将角度转换为弧度 |
数学常量
常量 | 描述 |
---|---|
math.pi | 数学常量 pi(圆周率,一般以π来表示)约等于 3.141592653589793 |
math.e | 数学常量 e,e即自然常数(自然常数) 2.718281828459045 |
- 课后练习:
猜数字游戏: guess_number.py
随机生成一个0~100之间的一个整数,用变量x绑定
让用户输入一个数y,输出猜数字的结果,
如果y等于生成的数x,则提示"恭喜你猜对了",并退出程序
如果y大于x,则提示"您猜的数字大了"
如果y小于x,则提示"您猜的数字小了"
直到猜对为止,一共花了多少时间,显示用户猜数字的次数后退出程序.
import random
def guess_number():
x = random.randint(0, 100)
guess_count = 0
while True:
y = input("请输入一个0到100之间的数字: ")
# 检查输入是否为数字
if not y.isdigit():
print("请输入一个有效的数字")
continue
y = int(y)
guess_count += 1
if y == x:
print(f"恭喜你猜对了!你一共猜了 {guess_count} 次.")
break
elif y > x:
print("您猜的数字大了")
else:
print("您猜的数字小了")
if __name__ == "__main__":
guess_number()
- 课后练习 2
随机生成一个6位数字组成的验证码!
1.3.4 os 模块
os 模块
os
模块是Python标准库中的一部分,提供了一种与操作系统进行交互的方法。主要功能包括文件和目录的操作、路径处理、进程管理等。在使用os
模块之前,我们需要先导入它:
import os

举例
#1. os.getcwd(): 获取当前工作目录
import os
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
#2. os.chdir(path): 改变当前工作目录
import os
new_directory = "/path/to/new/directory"
os.chdir(new_directory)
print("工作目录已更改为:", os.getcwd())
#3. os.listdir(path='.'): 返回指定目录下的所有文件和目录列表
import os
directory_path = "."
files_and_dirs = os.listdir(directory_path)
print("指定目录下的文件和目录列表:", files_and_dirs)
#4. os.mkdir(path): 创建目录
import os
new_directory = "new_folder"
os.mkdir(new_directory)
print(f"目录 '{new_directory}' 已创建")
#5. os.rmdir(path): 删除目录
import os
directory_to_remove = "new_folder"
os.rmdir(directory_to_remove)
print(f"目录 '{directory_to_remove}' 已删除")
#6. os.remove(path): 删除文件
import os
file_to_remove = "example.txt"
os.remove(file_to_remove)
print(f"文件 '{file_to_remove}' 已删除")
os.path 模块
os.path
模块是 Python 标准库的一部分,专门用于处理文件和目录路径的操作。它提供了一系列函数,用于操作和处理文件路径,使得路径操作更加方便和跨平台。
#1.os.path.basename(path): 返回路径中最后的文件名或目录名
import os
path = "/path/to/some/file.txt"
print(os.path.basename(path)) # 输出: file.txt
#2.os.path.dirname(path): 返回路径中的目录部分
import os
path = "/path/to/some/file.txt"
print(os.path.dirname(path)) # 输出: /path/to/some
#3.os.path.join(*paths): 将多个路径合并成一个路径
import os
path1 = "/path/to"
path2 = "some/file.txt"
full_path = os.path.join(path1, path2)
print(full_path) # 输出: /path/to/some/file.txt
#4.os.path.split(path): 将路径分割成目录和文件名
import os
path = "/path/to/some/file.txt"
print(os.path.split(path)) # 输出: ('/path/to/some', 'file.txt')
#5.os.path.splitext(path): 将路径分割成文件名和扩展名
import os
path = "/path/to/some/file.txt"
print(os.path.splitext(path)) # 输出: ('/path/to/some/file', '.txt')
#6.os.path.exists(path): 检查路径是否存在
import os
path = "/path/to/some/file.txt"
print(os.path.exists(path)) # 输出: True 或 False
#7.os.path.isfile(path): 检查路径是否是文件
import os
path = "/path/to/some/file.txt"
print(os.path.isfile(path)) # 输出: True 或 False
#8.os.path.isdir(path): 检查路径是否是目录
import os
path = "/path/to/some/directory"
print(os.path.isdir(path)) # 输出: True 或 False
2. 包(Packages)
2.1 包的定义和作用
定义
- 包是将模块以文件夹的组织形式进行分组管理的方法,以便更好地组织和管理相关模块。
- 包是一个包含一个特殊的
__init__.py
文件的目录,这个文件可以为空,但必须存在,以标识目录为Python包。 - 包可以包含子包(子目录)和模块,可以使用点表示法来导入。
作用
- 将一系列模块进行分类管理,有利于防止命名冲突
- 可以在需要时加载一个或部分模块而不是全部模块
包示例:
mypack/
__init__.py
menu.py # 菜单管理模块
games/
__init__.py
contra.py # 魂斗罗
supermario.py # 超级玛丽 mario
tanks.py # 坦克大作战
office/
__init__.py
excel.py
word.py
powerpoint.py
2.2 导入包和子包
- 使用
import
关键字可以导入包和子包,以访问其中的模块和内容。
# 同模块的导入规则
import 包名 [as 包别名]
import 包名.模块名 [as 模块新名]
import 包名.子包名.模块名 [as 模块新名]
from 包名 import 模块名 [as 模块新名]
from 包名.子包名 import 模块名 [as 模块新名]
from 包名.子包名.模块名 import 属性名 [as 属性新名]
# 导入包内的所有子包和模块
from 包名 import *
from 包名.模块名 import *
参考案例:
# 导入包中的模块
import matplotlib.pyplot as plt
# 导入子包中的模块
from sklearn.linear_model import LinearRegression
2.3 使用包和子包
- 使用导入的包和模块的内容,可以通过包名和点表示法来访问。
参考案例:
# 使用包中的模块
import pandas as pd
data_frame = pd.DataFrame()
# 使用子包中的模块
from tensorflow.keras.layers import Dense
2.4 __init__.py
文件
__init__.py
文件的主要作用是用于初始化Python包(package)或模块(module),它可以实现以下功能:
- 标识包目录: 告诉Python解释器所在的目录应被视为一个包或包含模块的包。没有这个文件,目录可能不会被正确识别为包,导致无法导入包内的模块。
- 执行初始化代码: 可以包含任何Python代码,通常用于执行包的初始化操作,如变量初始化、导入模块、设定包的属性等。这些代码在包被导入时会被执行。
- 控制包的导入行为: 通过定义
__all__
变量,可以明确指定哪些模块可以被从包中导入,从而限制包的公开接口,防止不需要的模块被导入。 - 提供包级别的命名空间:
__init__.py
中定义的变量和函数可以在包的其他模块中共享,提供了一个包级别的命名空间,允许模块之间共享数据和功能。 - 批量导入模块: 可以在
__init__.py
文件中批量导入系统模块或其他模块,以便在包被导入时,这些模块可以更方便地使用。
以下是一个简单的 __init__.py
文件的代码示例,演示了上述功能的使用:
# __init__.py 文件示例
# 1. 批量导入系统模块
import os
import sys
import datetime
# 2. 定义包级别的变量
package_variable = "This is a package variable"
# 3. 控制包的导入行为
__all__ = ['module1', 'module2']
# 4. 执行初始化代码
print("Initializing mypackage")
# 注意:这个代码会在包被导入时执行
# 5. 导入包内的模块
from . import module1
from . import module2
在这个示例中,__init__.py
文件用于批量导入系统模块、定义包级别的变量、控制包的导入行为、执行初始化代码,以及导入包内的模块。这有助于包的组织、初始化和导入管理。
3. 第三方包
Python第三方包是由Python社区开发的,可用于扩展Python功能和解决各种问题的软件包。这些包提供了各种各样的功能,包括数据分析、机器学习、网络编程、Web开发、图形处理、自然语言处理等。
3.1 安装和使用
-
使用pip:pip是Python的包管理工具,用于安装、升级和管理第三方包。确保你的Python安装中包含了pip。
-
安装第三方包:
-
使用pip安装包:在命令行中运行以下命令来安装包,将"package-name"替换为要安装的包的名称。
pip install package-name
-
安装特定版本的包:如果你需要安装特定版本的包,可以使用以下命令:
pip install package-name==version
-
通过镜像安装,可以使用以下命令:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple package1 package2 package3 ...
-
从requirements文件安装:你可以将要安装的包及其版本记录在一个文本文件中,通常命名为requirements.txt,然后运行以下命令安装其中列出的所有包:
pip install -r requirements.txt
-
-
导入包:在Python脚本或交互式环境中,使用
import
语句导入已安装的包,以便在代码中使用它们。import package_name
-
使用包:每个第三方包都有不同的用法和功能,通常伴随着官方文档和示例代码。你可以查阅官方文档,或者使用
help()
函数来了解包的功能和方法。示例:import package_name help(package_name)
-
更新和卸载包:
-
更新包:使用以下命令来更新已安装的包:
pip install --upgrade package-name
-
卸载包:如果你想卸载包,可以使用以下命令:
pip uninstall package-name
-
3.2 依赖清单
可以使用pipreqs来维护requirements.txt文件,以便轻松地重建环境。
pipreqs
是一个用于管理Python项目依赖清单的工具,它会自动分析项目代码,并生成requirements.txt
文件,列出项目所需的所有依赖包及其版本。以下是使用pipreqs
管理依赖清单的步骤:
安装pipreqs:
如果你还没有安装pipreqs
,可以使用pip安装它(比较慢,可能会丢包):
pip install pipreqs
在项目目录中运行pipreqs:
进入你的项目目录,然后运行以下命令:
pipreqs .
这会分析项目代码,并在当前目录下生成一个名为requirements.txt
的文件,其中包含了项目所需的所有依赖包及其版本。
如果遇到编码错误UnicodeDecodeError,则将指定编码为utf8:
pipreqs ./ --encoding=utf8
pipreqs ./ --encoding=gbk
pipreqs ./ --encoding='iso-8859-1'
查看生成的requirements.txt文件:
打开requirements.txt
文件,你将看到列出的依赖包及其版本,类似于以下内容:
package1==1.0.0
package2==2.1.3
...
选择是否要修改requirements.txt文件:
pipreqs
生成的requirements.txt
文件可能包含一些不必要的依赖,或者可能需要手动指定特定版本。
你可以编辑requirements.txt
文件,根据项目的需要添加、删除或修改依赖项。
-
安装依赖:
一旦你准备好了
requirements.txt
文件,你可以使用pip
来安装项目的依赖:pip install -r requirements.txt
-
定期更新依赖:
定期使用
pipreqs
重新生成requirements.txt
文件,以确保依赖清单保持最新。你可以使用以下命令:pipreqs .
pipreqs
是一个方便的工具,它可以帮助你自动创建和维护项目的依赖清单。不过,需要记住,生成的依赖清单可能包含一些不必要的依赖,因此你应该仔细检查和编辑requirements.txt
文件以确保它反映了项目的真实需求。
Python的包和模块是组织、管理和重用代码的重要工具。它们有助于将代码划分为可管理的单元,提高了代码的可读性和可维护性。通过模块和包,你可以更有效地组织项目,减少命名冲突,以及在不同项目之间重用代码,从而更轻松地进行Python编程。通过上述参考案例,你可以更好地理解如何在实际项目中应用这些概念。
Python文件操作
文件操作是Python中常见的任务之一,用于创建、读取、写入和管理文件。以下是一些常见的文件操作任务的思路、总结和示例代码:
1. 打开文件
要执行文件操作,首先需要打开文件。使用open()
函数可以打开文件,指定文件名以及打开模式(读取、写入、追加等)。

# 打开一个文本文件以读取内容
file = open("example.txt", "r")
2. 读取文件
一旦文件被打开,可以使用不同的方法来读取文件内容。

# 读取整个文件内容
content = file.read()
# 逐行读取文件内容
for line in file: #直接遍历文件对象,每次读取一行。这种方式更内存友好,因为不需要将所有行读入内存。
print(line)
with open('example.txt', 'r') as file:
lines = file.readlines() # 读取文件的所有行,并将其作为一个列表返回。
for line in lines:
print(line, end='') 代码和file = open("example.txt", "r")for line in file:
print(line) 代码的区别
3. 写入文件
要写入文件,需要打开文件以写入模式(‘w’),然后使用write()
方法。
# 打开文件以写入内容
file = open("example.txt", "w")
# 写入内容
file.write("这是一个示例文本。")
4. 关闭文件
完成文件操作后,应该关闭文件,以释放资源和确保文件的完整性。
file.close()
5. 使用with
更安全的方法是使用with
语句,它会自动关闭文件。
with open("example.txt", "r") as file:
content = file.read()
# 文件自动关闭
6. 检查是否存在
可以使用os.path.exists()
来检查文件是否存在。
import os
if os.path.exists("example.txt"):
print("文件存在")
7. 处理异常
在文件操作中,可能会出现各种异常情况,例如文件不存在或没有权限。在文件操作中捕获这些异常是个好习惯。
try:
with open("example.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("文件不存在")
except Exception as e:
print(f"发生错误:{e}")
这些是文件操作的一些常见思路和示例代码。请根据你的具体需求和场景来调整代码。在进行文件操作时,要确保小心处理文件,以避免意外数据损坏或文件损坏。
除了打开、读取和写入文件之外,还有一些其他常见的文件操作,如复制、删除和改变文件名。以下是这些操作的思路和示例代码:
8. 复制文件
要复制文件,你可以使用shutil
模块的copy
方法。
import shutil
source_file = "source.txt"
destination_file = "destination.txt"
shutil.copy(source_file, destination_file)
9. 删除文件
要删除文件,可以使用os
模块的remove
方法。
import os
file_to_delete = "file_to_delete.txt"
if os.path.exists(file_to_delete):
os.remove(file_to_delete)
print(f"{file_to_delete} 已删除")
else:
print(f"{file_to_delete} 不存在")
10. 修改名称
要改变文件名,可以使用os
模块的rename
方法。
import os
old_name = "old_name.txt"
new_name = "new_name.txt"
if os.path.exists(old_name):
os.rename(old_name, new_name)
print(f"文件名已更改为 {new_name}")
else:
print(f"{old_name} 不存在")
Python JSON 数据解析
JSON(JavaScript Object Notation)是一种轻量级数据交换格式,它易于阅读和编写,同时也易于机器解析和生成。Python提供了内置的JSON模块,用于处理JSON数据。
1. 导入模块
import json
2. 序列化
import json
data = {
"name": "John",
"age": 30,
"city": "New York"
}
json_str = json.dumps(data) # json.dumps() 是 Python 的 json 模块中的一个函数,它的作用是将 Python 对象转换为 JSON 格式的字符串。
print(json_str)
3. 反序列化
json_str = '{"name": "John", "age": 30, "city": "New York"}'
data = json.loads(json_str) # json.loads() 是 Python json 模块中的一个函数,它的作用是将 JSON 格式的字符串转换为 Python 对象。
print(data)
4. 对象存文件
data = {
"name": "John",
"age": 30,
"city": "New York"
}
with open('data.json', 'w') as json_file:
json.dump(data, json_file)
5. 从文件加载
with open('data.json', 'r') as json_file:
data = json.load(json_file)
print(data)
6. 嵌套JSON数据
如果JSON数据包含嵌套结构,您可以使用递归来访
问和修改其中的值。
json_data = {
"name": "Alice",
"info": {
"age": 25,
"location": "Paris"
}
}
# 获取嵌套的值
age = json_data["info"]["age"]
# 修改嵌套的值
json_data["info"]["location"] = "New York"
# 将更改后的数据转换为JSON字符串
new_json_str = json.dumps(json_data)
7. JSON中列表
JSON可以包含列表,可以使用索引来访问列表元素。
json_data = {
"fruits": ["apple", "banana", "cherry"]
}
# 获取列表中的第一个水果
first_fruit = json_data["fruits"][0]
# 添加一个新水果到列表
json_data["fruits"].append("orange")
8. JSON中空值
JSON允许表示空值(null),在Python中,它通常转换为None
。
json_data = {
"value": None
}
字典和JSON格式不同之处
- 数据类型限制:
- JSON:支持的数据类型包括对象(类似于字典)、数组(类似于列表)、字符串、数字、布尔值和
null
。JSON 不支持 Python 特有的数据类型如tuple
、set
、bytes
等。 - Python 字典:可以包含多种 Python 特有的数据类型,比如
tuple
、set
、bytes
等。
- JSON:支持的数据类型包括对象(类似于字典)、数组(类似于列表)、字符串、数字、布尔值和
- 格式要求:
- JSON:数据必须以字符串的形式表示,键必须是双引号括起来的字符串,值可以是字符串、数字、布尔值、数组、对象或
null
。 - Python 字典:键可以是任意不可变的类型(如字符串、数字、元组),值可以是任意类型。键通常用单引号或双引号括起来,但 Python 允许在字典中使用不加引号的键。
- JSON:数据必须以字符串的形式表示,键必须是双引号括起来的字符串,值可以是字符串、数字、布尔值、数组、对象或
python csv文件
1. 什么是 CSV 文件?
CSV(Comma-Separated Values)是一种简单的文本文件格式,用于存储表格数据,文件中的每行表示一行数据,字段之间用逗号分隔。
2. 如何读取 CSV 文件?
使用 csv
模块
Python 内置的 csv
模块非常方便处理 CSV 文件。
示例代码:
import csv
# 打开 CSV 文件
with open('example.csv', mode='r', encoding='utf-8') as file:
reader = csv.reader(file) # 创建 CSV 读取器
for row in reader:
print(row) # 每行是一个列表
使用 pandas
读取前几行
pandas
提供了 head()
方法,可以直接读取前几行。
示例代码:
import pandas as pd
# 读取前 5 行数据
df = pd.read_csv('example.csv')
# 显示前 5 行
print(df.head(5))
head()
方法默认返回前 5 行,如果你想读取不同数量的行,可以传递一个参数,如 head(10)
。
3. 如何写入 CSV 文件?
写入简单数据
示例代码:
import csv
data = [
['Name', 'Age', 'City'],
['Alice', 25, 'New York'],
['Bob', 30, 'Los Angeles']
]
with open('output.csv', mode='w', encoding='utf-8', newline='') as file:
writer = csv.writer(file)
writer.writerows(data) # 一次写入多行
4.基本操作
- 读取所有数据
import pandas as pd
# 读取 CSV 文件
df = pd.read_csv('house.csv',header=None)
df
- 拿到每行的数据的具体值
# 遍历每一行数据
for index, row in df.iterrows():
print(f"行索引: {index}, Name: {row[0]}, Age: {row[1]}, City: {row[2]}")
5. 常见问题和注意事项
- 编码问题:打开文件时建议明确指定
encoding
参数(如utf-8
)。 - 换行问题:写入文件时使用
newline=''
,避免产生额外的空行。 - 大文件处理:对于超大文件,可以逐行读取以减少内存占用。
Python正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。re模块使 Python 语言拥有全部的正则表达式功能。正则表达式在网络爬虫、数据分析中有着广泛使用,掌握正则表达式能够达到事半功倍的效果。
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[…] | 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’ |
[^…] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0个或多个的表达式。 |
re+ | 匹配1个或多个的表达式。 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{n} | 匹配n个前面表达式。例如,"o{2}“不能匹配"Bob"中的"o”,但是能匹配"food"中的两个o。 |
re{n,} | 精确匹配n个前面表达式。例如,"o{2,}“不能匹配"Bob"中的"o”,但能匹配"foooood"中的所有o。"o{1,}“等价于"o+”。"o{0,}“则等价于"o*”。 |
re{n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
| | 匹配a或b |
(re) | 匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
(?: re) | 类似 (…), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#…) | 注释. |
(?= re) | 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。 |
(?> re) | 匹配的独立模式,省去回溯。 |
\w | 匹配数字字母下划线 |
\W | 匹配非数字字母下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]。 |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]。 |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
\n, \t, 等 | 匹配一个换行符。匹配一个制表符, 等 |
\1…\9 | 匹配第n个分组的内容。 |
\10 | 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
1.字符匹配
方法和功能
方法 | 功能 |
---|---|
match() | 判断一个正则表达式是否从开始处匹配一个字符串 |
search() | 遍历字符串,找到正则表达式匹配的第一个位置,返回匹配对象 |
findall() | 遍历字符串,找到正则表达式匹配的所有位置,并以列表的形式返回。如果给出的正则表达式中包含子组,就会把子组的内容单独返回,如果有多个子组就会以元组的形式返回。 |
finditer() | 遍历字符串,找到正则表达式匹配的所有位置,并以迭代器的形式返回 |
- hqyj匹配文本中的hqyj
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("hqyj",text)
print(data)#['hqyj', 'hqyj']
- [hqyj]匹配h或者q或者y或者j字符
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("[hqyj]",text)
print(data)#['h', 'q', 'y', 'j', 'h', 'q', 'y', 'j']
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("[hqyj]牛",text)
print(data)#['j牛']
- [^hqyj]匹配除了hqyj以外的其他字符
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("[^hqyj]",text)
print(data)#['牛', '皮', '6', '6', '6', '6', ',', '有', '个', '老', '师', '也', '牛', '皮', '6', '6', '6']
- [a-z]匹配a~z的任意字符([0-9]也可以)
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall("[a-z]hqyj",text)
print(data)#['chqyj']
- .匹配除了换行符以外的任意字符
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall(".hqyj",text)
print(data)#[',hqyj', 'chqyj']
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall(".+hqyj",text) #贪婪匹配(匹配最长的)
print(data)#['hqyj牛皮6666,hqyj有个老师abchqyj']
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall(".?hqyj",text)
print(data)#['hqyj', ',hqyj', 'chqyj']
特殊字符
特殊字符 | 含义 |
---|---|
\d | 匹配任何十进制数字;相当于类 [0-9] |
\D | 与 \d 相反,匹配任何非十进制数字的字符;相当于类 [^0-9] |
\s | 匹配任何空白字符(包含空格、换行符、制表符等);相当于类 [ \t\n\r\f\v] |
\S | 与 \s 相反,匹配任何非空白字符;相当于类 [^ \t\n\r\f\v] |
\w | 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9_] |
\W | 于 \w 相反 (注:re.ASCII 标志使得 \w 只能匹配 ASCII 字符) |
\b | 匹配单词的开始或结束 |
\B | 与 \b 相反 |
- \w 匹配字母数字下划线(汉字)
import re
text="华清_远见abc 华清hqyj远见 华清牛皮远见"
data=re.findall("华清\w+远见",text)
print(data)#['华清_远见', '华清hqyj远见', '华清牛皮远见']
- \d匹配数字
import re
text="hqyj66d6 a1h43d3fd43s43d4 "
data=re.findall("d\d",text) # 只匹配一个数字
print(data)#['d6', 'd3', 'd4', 'd4']
import re
text="hqyj66d6 a1h43d3fd43s43d4 "
data=re.findall("d\d+",text)
print(data)#['d6', 'd3', 'd43', 'd4']
- \s匹配任意空白符 包括空格,制表符等等
import re
text="hqyj666 jack karen 666"
data=re.findall("\sj\w+\s",text)
print(data)#[' jack ']
2.数量控制
*重复0次或者更多次
import re
text="华清远见 华清666远见"
data=re.findall("华清6*远见",text)
print(data)#['华清远见', '华清666远见']
+重复1次或者更多次
import re
text="华清远见 华清666远见 华清6远见"
data=re.findall("华清6+远见",text)
print(data)#['华清666远见', '华清6远见']
?重复1次或者0次
import re
text="华清远见 华清666远见 华清6远见"
data=re.findall("华清6?远见",text)
print(data)#['华清远见', '华清6远见']
{n}重复n次,n是数字
import re
text="华清远见 华清666远见 华清6远见"
data=re.findall("华清6{3}远见",text)
print(data)#['华清666远见']
{n,}重复n次或者更多次
import re
text="华清远见 华清666远见 华清6远见 华清66远见"
data=re.findall("华清6{2,}远见",text)
print(data)#['华清666远见', '华清66远见']
{n,m}重复n到m次
import re
text="华清远见 华清666远见 华清6远见 华清66远见"
data=re.findall("华清6{0,2}远见",text)
print(data)#['华清远见', '华清6远见', '华清66远见']
3.分组
- ()提取兴趣区域
import re
text="谢帝谢帝,我要迪士尼,我的电话号码18282832341,qq号码1817696843"
data=re.findall("号码(\d{10,})",text)
print(data)#['18282832341', '1817696843']
import re
text="谢帝谢帝,我要迪士尼,我的电话号码18282832341,qq号码1817696843"
data=re.findall("(\w{2}号码(\d{10,}))",text)
print(data)#['18282832341', '1817696843']
- (|)提取兴趣区域(| = or)
import re
text="第一名张三 第一名物理149分 第一名数学150分 第一名英语148分 第一名总分740分"
data=re.findall("第一名(\w{2,}|\w{2,}\d{2,}分)",text)
print(data)#['张三', '物理149分', '数学150分', '英语148分', '总分740分']
4.开始和结束
- ^开始
import re
text = "hqyj66abc hqyj123"
data = re.findall("^hqyj\d+", text)
print(data) #['hqyj66']
- $结尾
import re
text = "hqyj66abc hqyj123"
data = re.findall("hqyj\d+$", text)
print(data) #['hqyj123']
5.特殊字符
由于正则表达式中* . \ {} () 等等符号具有特殊含义,如果你指定的字符正好就是这些符号,需要用\进行转义
import re
text = "数学中集合的写法是{2}"
data = re.findall("\{2\}", text)
print(data) #['{2}']
6.re模块的常用方法
re.findall
获取匹配到的所有数据
import re
text="hqyj66d6 a1h43d3fd43s43d4 "
data=re.findall("d\d+",text)
print(data)#['d6', 'd3', 'd43', 'd4']
re.match
从字符串的起始位置匹配,成功返回一个对象否则返回none。
匹配成功返回对象,对象的方法:
方法 | 功能 |
---|---|
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
import re
# 在起始位置匹配,并返回一个包含匹配 (开始,结束) 的位置的元组
print(re.match('www', "www.python.com").span())#(0, 3)
print(re.match('www', "www.python.com").start())#0
print(re.match('www', "www.python.com").end())#3
# 不在起始位置匹配
print(re.match('com', "www.python.com"))# None
re.search
扫描整个字符串并返回第一个成功匹配的字符串。成功返回一个对象否则返回none
import re
# 在起始位置匹配
print(re.search('www', 'www.hqyj.com').span())#(0, 3)
# 不在起始位置匹配
print(re.search('com', 'www.hqyj.com').span())#(9, 12)
re.sub
替换匹配成功的字符
类似与字符串的replace函数
import re
text = "以前华清远见在四川大学旁边,现在华清远见在西南交大旁边"
data = re.sub("华清远见","北京华清远见科技集团成都中心", text)
print(data)#以前北京华清远见科技集团成都中心在四川大学旁边,现在北京华清远见科技集团成都中心在西南交大旁边
re.split
根据匹配成功的位置对字符串进行分割
import re
text = "python is very easy"
data = re.split("\s{1,}", text)
print(data)#['python', 'is', 'very', 'easy']
re.finditer
类似findall 但是不会全部返回出来 而是返回迭代器(比如匹配成功了10万个 全部返回就很吃内存了)
import re
text = "python is very easy"
data = re.findall("\w+", text)
print(data)#['python', 'is', 'very', 'easy']
import re
text = "python is very easy"
data = re.finditer("\w+", text)
print(data)
for el in data:
print(el.group())
7.常见的一些正则
QQ号:[1 - 9][0 - 9]{4, }(腾讯QQ号从10000开始)
帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
身份证号(15位、18位数字):^\d{15}|\d{18}$
短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
Python日期和时间
Python 的 time 模块下有很多函数可以转换
- 常见日期格式。
time 模块时间处理的和转换时间格式的常用API: [官网链接](time — 时间访问和转换 — Python 3.12.2 文档)
time.time() - 获取当前时间的时间戳(以秒为单位,浮点数形式,精确到小数点后若干位)
import time # 引入time模块
ticks = time.time()
print ("当前时间戳为:", ticks)#时间戳单位最适于做日期运算。但是1970年之前的日期就无法以此表示了。太遥远的日期也不行,UNIX和Windows只支持到2038年
time.sleep(secs) - 让程序暂停执行指定秒数。
import time
# 让程序暂停3秒
time.sleep(3)
print("3秒后执行到这里...")
time.ctime(timestamp=None) - 将时间戳转换为易读的本地时间格式。
import time
# 获取当前时间的ctime格式
current_time = time.ctime()
print("当前时间 (ctime):", current_time)
# 或者使用特定时间戳
timestamp = 1647708000 # 这是一个示例时间戳
converted_time = time.ctime(timestamp)
print("时间戳转ctime格式:", converted_time)
time.localtime([secs]) - 将时间戳转换为本地时区的struct_time元组。
import time
# 获取当前时间的struct_time元组
local_time_tuple = time.localtime()
print("当前时间 (struct_time):", local_time_tuple)
# 或者使用特定时间戳
timestamp = time.time()
converted_tuple = time.localtime(timestamp)
print("时间戳转struct_time:", converted_tuple)
time.strftime(format[, t]) - 格式化本地时间。
import time
# 获取当前时间并格式化为“年-月-日 时:分:秒”
formatted_time = time.strftime('%Y-%m-%d %H:%M:%S')
print("格式化当前时间:", formatted_time)
# 使用特定时间戳
timestamp = time.time()
custom_format = time.strftime("%Y%m%d_%H%M%S", time.localtime(timestamp))
print("格式化后的时间戳:", custom_format)
格式化符号:
- %y 两位数的年份表示(00-99)
- %Y 四位数的年份表示(000-9999)
- %m 月份(01-12)
- %d 月内中的一天(0-31)
- %H 24小时制小时数(0-23)
- %I 12小时制小时数(01-12)
- %M 分钟数(00=59)
- %S 秒(00-59)
- %a 本地简化星期名称
- %A 本地完整星期名称
- %b 本地简化的月份名称
- %B 本地完整的月份名称
- %c 本地相应的日期表示和时间表示
- %j 年内的一天(001-366)
- %p 本地A.M.或P.M.的等价符
- %U 一年中的星期数(00-53)星期天为星期的开始
- %w 星期(0-6),星期天为星期的开始
- %W 一年中的星期数(00-53)星期一为星期的开始
- %x 本地相应的日期表示
- %X 本地相应的时间表示
- %Z 当前时区的名称
- %% %号本身
属性(time模块本身没有属性,但可以通过其提供的函数生成的对象来访问属性)
对于struct_time对象(由time.localtime()或time.gmtime()等返回),它是一个元组,可以按索引访问各个时间元素:
属性 | 值 |
---|---|
tm_year | 年 |
tm_mon | 月:1 到 12 |
tm_mday | 日:1 到 31 |
tm_hour | 时:0 到 23 |
tm_min | 分:0 到 59 |
tm_sec | 秒:0 到 61 (60或61 是闰秒) |
tm_wday | 星期:0 到 6 (0是周一) |
tm_yday | 一年中的第几天,1 到 366 |
tm_isdst | 是否为夏令时,值有:1(夏令时)、0(不是夏令时)、-1(未知),默认 -1 |
import time
local_time = time.localtime()
# 访问struct_time的属性(索引)
year = local_time.tm_year
month = local_time.tm_mon
day = local_time.tm_mday
hour = local_time.tm_hour
minute = local_time.tm_min
second = local_time.tm_sec
print(f"当前日期和时间:{year}-{month}-{day} {hour}:{minute}:{second}")
Python网络
Python requests 是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。
使用 requests 发送 HTTP 请求需要先下载并导入 requests 模块:
import requests
# 导入 requests 包
import requests
response = requests.get('https://www.baidu.com')# 发送请求
print(response.content) # 获取响应内容
response2 = requests.get('http://localhost:7001/test')# 发送请求
print(response2.json()) # 获取json数据并解析
每次调用 requests 请求之后,会返回一个 response 对象,该对象包含了具体的响应信息,如状态码、响应头、响应内容等:
response的属性或方法 | 说明 |
---|---|
apparent_encoding | 编码方式 |
close() | 关闭与服务器的连接 |
content | 返回响应的内容,以字节为单位 |
cookies | 返回一个 CookieJar 对象,包含了从服务器发回的 cookie |
elapsed | 返回一个 timedelta 对象,包含了从发送请求到响应到达之间经过的时间量,可以用于测试响应速度。比如 r.elapsed.microseconds 表示响应到达需要多少微秒。 |
encoding | 解码 r.text 的编码方式 |
headers | 返回响应头,字典格式 |
history | 返回包含请求历史的响应对象列表(url) |
is_permanent_redirect | 如果响应是永久重定向的 url,则返回 True,否则返回 False |
is_redirect | 如果响应被重定向,则返回 True,否则返回 False |
iter_content() | 迭代响应 |
iter_lines() | 迭代响应的行 |
json() | 返回结果的 JSON 对象 (结果需要以 JSON 格式编写的,否则会引发错误) |
links | 返回响应的解析头链接 |
next | 返回重定向链中下一个请求的 PreparedRequest 对象 |
ok | 检查 “status_code” 的值,如果小于400,则返回 True,如果不小于 400,则返回 False |
raise_for_status() | 如果发生错误,方法返回一个 HTTPError 对象 |
reason | 响应状态的描述,比如 “Not Found” 或 “OK” |
request | 返回请求此响应的请求对象 |
status_code | 返回 http 的状态码,比如 404 和 200(200 是 OK,404 是 Not Found) |
text | 返回响应的内容,unicode 类型数据 |
url | 返回响应的 URL |
requests的方法
方法 | 描述 |
---|---|
delete(url, args) | 发送 DELETE 请求到指定 url |
get(url, params, args) | 发送 GET 请求到指定 url |
head(url, args) | 发送 HEAD 请求到指定 url |
patch(url, data, args) | 发送 PATCH 请求到指定 url |
post(url, data, json, args) | 发送 POST 请求到指定 url |
put(url, data, args) | 发送 PUT 请求到指定 url |
request(method, url, args) | 向指定的 url 发送指定的请求方法 |
requests.get(url, params ={key: value}, args)
- url 请求 url。
- **params ** 参数为要发送到指定 url 的 JSON 对象。
- args 为其他参数,比如 cookies、headers、verify等。
import requests
# 图片URL地址
image_url = 'http://localhost:7001/public/1.png'
# 发送GET请求获取图片数据
response = requests.get(image_url)
# 检查请求是否成功(HTTP状态码为200)
if response.status_code == 200:
# 将图片数据写入本地文件
with open('image.jpg', 'wb') as f:
f.write(response.content)
print("图片已成功下载并保存为 image.jpg")
else:
print(f"无法下载图片,响应状态码:{response.status_code}")
requests.post(url, data={key: value}, json={key: value}, args)
- url 请求 url。
- data 参数为要发送到指定 url 的字典、元组列表、字节或文件对象。
- json 参数为要发送到指定 url 的 JSON 对象。
- args 为其他参数,比如 cookies、headers、verify等。
import requests
headers = {'User-Agent': 'Mozilla/5.0'} # 设置请求头
params = {'key1': 'value1', 'key2': 'value2'} # 设置查询参数
data = {'username': 'jack', 'password': '123456'} # 设置请求体
response = requests.post('http://localhost:7001/test', headers=headers, params=params, data=data)
print(response.text)