python-学习
Python学习
第一章 Python入门
编程与编程语言
python是一门编程语言,作为学习python的开始,需要事先明白:编程的目的是什么?什么是编程语言?什么是编程?
编程的目的:
计算机的发明,是为了用机器取代/解放人力,而编程的目的则是将人类的思想流程按照某种能够被计算机识别的表达方式传递给计算机,从而达到让计算机能够像人脑/电脑一样自动执行的效果。
什么是编程语言?
能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质.在编程世界里,计算机更像人的奴隶,人类编程的目的就是命令奴隶去工作.
什么是编程:
编程即程序员根据需求把自己的思想流程按照某种编程语言的语法风格编写下来,产出的结果就是包含一堆字符的文件
强调:程序在未运行之前跟普通文件无异,只有程序在运行时,文件内所写的字符才有特定的语法意义
Python是语言,而学习语言的套路都是一的,以英语为例,你需要学单词,然后学语法,最后写作文
英语的单词 --------------------------------->Python中的关键字
英语的语法---------------------------------->Python中的语法
英语的作文---------------------------------->用Python语言写的程序
我不知道成功有没有捷径,但我确定学Python没有,没有几万行代码的洗礼,你不可能成为一名优秀的程序员,这就是我想对你说的。
编程的语言的发展经历了
#机器语言:站在计算机(奴隶)的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件;
#汇编语言:站在计算机(奴隶)的角度,简写的英文标识符取代二进制去编写程序,本质仍然是直接操作硬件;
#高级语言:站在人(奴隶主)的角度,说人话,即用人类的字符去编写程序,屏蔽了硬件操作
高级语言更贴近人类语言,因而造成了:它必须被翻译成计算机能读懂二进制后,才能被执行,按照翻译方式分为
#1. 编译型(需要编译器,相当于用谷歌翻译):如C,执行速度快,调试麻烦
#2. 解释型(需要解释器,相当于同声传译):如python,执行速度慢,调试方便
总结:
机器语言
#优点是最底层,执行速度最快
#缺点是最复杂,开发效率最低
汇编语言
#优点是比较底层,执行速度最快
#缺点是复杂,开发效率最低
高级语言
#编译型语言执行速度快,不依赖语言环境运行,跨平台差
#解释型跨平台好,一份代码,到处使用,缺点是执行速度慢,依赖解释器运行
#机器语言
由于计算机内部只能接受二进制代码,因此,用二进制代码0和1描述的指令称为机器指令,全部机器指令的集合构成计算机的机器语言,用机器语言编程的程序称为目标程序。只有目标程序才能被计算机直接识别和执行。但是机器语言编写的程序无明显特征,难以记忆,不便阅读和书写,且依赖于具体机种,局限性很大,机器语言属于低级语言。
用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。手编程序时,程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。这是一件十分繁琐的工作。编写程序花费的时间往往是实际运行时间的几十倍或几百倍。而且,编出的程序全是些0和1的指令代码,直观性差,还容易出错。除了计算机生产厂家的专业人员外,绝大多数的程序员已经不再去学习机器语言了。
机器语言是微处理器理解和使用的,用于控制它的操作二进制代码。
尽管机器语言好像是很复杂的,然而它是有规律的。
存在着多至100000种机器语言的指令。这意味着不能把这些种类全部列出来。
以下是一些示例:
指令部份的示例
0000 代表 加载(LOAD)
0001 代表 存储(STORE)
...
暂存器部份的示例
0000 代表暂存器 A
0001 代表暂存器 B
...
存储器部份的示例
000000000000 代表地址为 0 的存储器
000000000001 代表地址为 1 的存储器
000000010000 代表地址为 16 的存储器
100000000000 代表地址为 2^11 的存储器
集成示例
0000,0000,000000010000 代表 LOAD A, 16
0000,0001,000000000001 代表 LOAD B, 1
0001,0001,000000010000 代表 STORE B, 16
0001,0001,000000000001 代表 STORE B, 1[1]
#汇编语言
汇编语言的实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,更容易识别和记忆。它同样需要编程者将每一步具体的操作用命令的形式写出来。汇编程序的每一句指令只能对应实际操作过程中的一个很细微的动作。例如移动、自增,因此汇编源程序一般比较冗长、复杂、容易出错,而且使用汇编语言编程需要有更多的计算机专业知识,但汇编语言的优点也是显而易见的,用汇编语言所能完成的操作不是一般高级语言所能够实现的,而且源程序经汇编生成的可执行文件不仅比较小,而且执行速度很快。
汇编的hello world,打印一句hello world, 需要写十多行,也是醉了。
; hello.asm
section .data ; 数据段声明
msg db "Hello, world!", 0xA ; 要输出的字符串
len equ $ - msg ; 字串长度
section .text ; 代码段声明
global _start ; 指定入口函数
_start: ; 在屏幕上显示一个字符串
mov edx, len ; 参数三:字符串长度
mov ecx, msg ; 参数二:要显示的字符串
mov ebx, 1 ; 参数一:文件描述符(stdout)
mov eax, 4 ; 系统调用号(sys_write)
int 0x80 ; 调用内核功能
; 退出程序
mov ebx, 0 ; 参数一:退出代码
mov eax, 1 ; 系统调用号(sys_exit)
int 0x80 ; 调用内核功能
#高级语言
高级语言是大多数编程者的选择。和汇编语言相比,它不但将许多相关的机器指令合成为单条指令,并且去掉了与具体操作有关但与完成工作无关的细节,例如使用堆栈、寄存器等,这样就大大简化了程序中的指令。同时,由于省略了很多细节,编程者也就不需要有太多的专业知识。
高级语言主要是相对于汇编语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,像最简单的编程语言PASCAL语言也属于高级语言。
高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,按转换方式可将它们分为两类:
编译类:编译是指在应用源程序执行之前,就将程序源代码“翻译”成目标代码(机器语言),因此其目标程序可以脱离其语言环境独立执行(编译后生成的可执行文件,是cpu可以理解的2进制的机器码组成的),使用比较方便、效率较高。但应用程序一旦需要修改,必须先修改源代码,再重新编译生成新的目标文件(* .obj,也就是OBJ文件)才能执行,只有目标文件而没有源代码,修改很不方便。
编译后程序运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如C、C++、Delphi等
解释类:执行方式类似于我们日常生活中的“同声翻译”,应用程序源代码一边由相应语言的解释器“翻译”成目标代码(机器语言),一边执行,因此效率比较低,而且不能生成可独立执行的可执行文件,应用程序不能脱离其解释器(想运行,必须先装上解释器,就像跟老外说话,必须有翻译在场),但这种方式比较灵活,可以动态地调整、修改应用程序。如Python、Java、PHP、Ruby等语言。
主流编程语言的介绍
#C语言:
C语言是一种计算机程序设计语言,它既具有高级语言的特点,又具有汇编语言的特点。它由美国贝尔研究所的D.M.Ritchie于1972年推出,1978年后,C语言已先后被移植到大、中、小及微型机上,它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。它的应用范围广泛,具备很强的数据处理能力,不仅仅是在软件开发上,而且各类科研都需要用到C语言,适于编写系统软件,三维,二维图形和动画,具体应用比如单片机以及嵌入式系统开发。
#C++:
C++是C语言的继承的扩展,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计,因而C++就适应的问题规模而论,大小由之。
C++不仅拥有计算机高效运行的实用性特征,同时还致力于提高大规模程序的编程质量与程序设计语言的问题描述能力。
#JAVA:
Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaSE, JavaEE, JavaME)的总称。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。
#PHP:
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域
Ruby:
Ruby 是开源的,在Web 上免费提供,但需要一个许可证。[4]
Ruby 是一种通用的、解释的编程语言。
Ruby 是一种真正的面向对象编程语言。
Ruby 是一种类似于 Python 和 Perl 的服务器端脚本语言。
Ruby 可以用来编写通用网关接口(CGI)脚本。
Ruby 可以被嵌入到超文本标记语言(HTML)。
Ruby 语法简单,这使得新的开发人员能够快速轻松地学习 Ruby
#GO:
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。
Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。
由其擅长并发编程
#Python:
Python是一门优秀的综合语言, Python的宗旨是简明、优雅、强大,在人工智能、云计算、金融分析、大数据开发、WEB开发、自动化运维、测试等方向应用广泛,已是全球第4大最流行的语言。
Python介绍
Python是语言,而学习语言的套路都是一的,以英语为例,你需要学单词,然后学语法,最后写作文
英语的单词 --------------------------------->Python中的关键字
英语的语法---------------------------------->Python中的语法
英语的作文---------------------------------->用Python语言写的程序
我不知道成功有没有捷径,但我确定学Python没有,没有几万行代码的洗礼,你不可能成为一名优秀的程序员,这就是我想对你说的
python的创始人为吉多·范罗苏姆(Guido van Rossum)。1989年的圣诞节期间,Guido开始写能够解释Python语言语法的解释器。Python这个名字,来自Guido所挚爱的电视剧Monty Python’s Flying Circus。他希望这个新的叫做Python的语言,能符合他的理想:创造一种C和shell之间,功能全面,易学易用,可拓展的语言。
最新的TIOBE排行榜,Python赶超PHP占据第4, Python崇尚优美、清晰、简单,是一个优秀并广泛使用的语言。
Python可以应用于众多领域,如:数据分析、组件集成、网络服务、图像处理、数值计算和科学计算等众多领域。目前业内几乎所有大中型互联网企业都在使用Python,如:Youtube、Dropbox、BT、Quora(中国知乎)、豆瓣、知乎、Google、Yahoo!、Facebook、NASA、百度、腾讯、汽车之家、美团等。
Python主要应用领域
#1. WEB开发——最火的Python web框架Django, 支持异步高并发的Tornado框架,短小精悍的flask,bottle, Django官方的标语把Django定义为the framework for perfectionist with deadlines(大意是一个为完全主义者开发的高效率web框架)
#2. 网络编程——支持高并发的Twisted网络框架, py3引入的asyncio使异步编程变的非常简单
#3. 爬虫——爬虫领域,Python几乎是霸主地位,Scrapy\Request\BeautifuSoap\urllib等,想爬啥就爬啥
#4. 云计算——目前最火最知名的云计算框架就是OpenStack,Python现在的火,很大一部分就是因为云计算
#5. 人工智能——谁会成为AI 和大数据时代的第一开发语言?这本已是一个不需要争论的问题。如果说三年前,Matlab、Scala、R、Java 和 Python还各有机会,局面尚且不清楚,那么三年之后,趋势已经非常明确了,特别是前两天 Facebook 开源了 PyTorch 之后,Python 作为 AI 时代头牌语言的位置基本确立,未来的悬念仅仅是谁能坐稳第二把交椅。
#6. 自动化运维——问问中国的每个运维人员,运维人员必须会的语言是什么?10个人相信会给你一个相同的答案,它的名字叫Python
#7. 金融分析——我个人之前在金融行业,10年的时候,我们公司写的好多分析程序、高频交易软件就是用的Python,到目前,Python是金融分析、量化交易领域里用的最多的语言
#8. 科学运算—— 你知道么,97年开始,NASA就在大量使用Python在进行各种复杂的科学运算,随着NumPy, SciPy, Matplotlib, Enthought librarys等众多程序库的开发,使的Python越来越适合于做科学计算、绘制高质量的2D和3D图像。和科学计算领域最流行的商业软件Matlab相比,Python是一门通用的程序设计语言,比Matlab所采用的脚本语言的应用范围更广泛
#9. 游戏开发——在网络游戏开发中Python也有很多应用。相比Lua or C++,Python 比 Lua 有更高阶的抽象能力,可以用更少的代码描述游戏业务逻辑,与 Lua 相比,Python 更适合作为一种 Host 语言,即程序的入口点是在 Python 那一端会比较好,然后用 C/C++ 在非常必要的时候写一些扩展。Python 非常适合编写 1 万行以上的项目,而且能够很好地把网游项目的规模控制在 10 万行代码以内。另外据我所知,知名的游戏<文明> 就是用Python写的
Python在一些公司的应用
谷歌:Google App Engine 、code.google.com 、Google earth 、谷歌爬虫、Google广告等项目都在大量使用Python开发
# CIA: 美国中情局网站就是用Python开发的
# NASA: 美国航天局(NASA)大量使用Python进行数据分析和运算
# YouTube:世界上最大的视频网站YouTube就是用Python开发的
# Dropbox:美国最大的在线云存储网站,全部用Python实现,每天网站处理10亿个文件的上传和下载
# Instagram:美国最大的图片分享社交网站,每天超过3千万张照片被分享,全部用python开发
# Facebook:大量的基础库均通过Python实现的
# Redhat: 世界上最流行的Linux发行版本中的yum包管理工具就是用python开发的
# 豆瓣: 公司几乎所有的业务均是通过Python开发的
# 知乎: 国内最大的问答社区,通过Python开发(国外Quora)
# 春雨医生:国内知名的在线医疗网站是用Python开发的
# 除上面之外,还有搜狐、金山、腾讯、盛大、网易、百度、阿里、淘宝 、土豆、新浪、果壳等公司都在使用Python完成各种各样的任务。
Python的发展史
# 1989年,Guido开始写Python语言的编译器。
# 1991年,第一个Python编译器诞生。它是用C语言实现的,并能够调用C语言的库文件。从一出生,Python已经具有了:类,函数,异常处理,包含表和词典在内的核心数据类型,以及模块为基础的拓展系统。
# Granddaddy of Python web frameworks, Zope 1 was released in 1999
# Python 1.0 - January 1994 增加了 lambda, map, filter and reduce.
# Python 2.0 - October 16, 2000,加入了内存回收机制,构成了现在Python语言框架的基础
# Python 2.4 - November 30, 2004, 同年目前最流行的WEB框架Django 诞生
# Python 2.5 - September 19, 2006
# Python 2.6 - October 1, 2008
# Python 2.7 - July 3, 2010
# In November 2014, it was announced that Python 2.7 would be supported until 2020, and reaffirmed that there would be no 2.8 release as users were expected to move to Python 3.4+ as soon as possible
# Python 3.0 - December 3, 2008 (这里要解释清楚 为什么08年就出3.0,2010年反而又推出了2.7?是因为3.0不向下兼容2.0,导致大家都拒绝升级3.0,无奈官方只能推出2.7过渡版本)
# Python 3.1 - June 27, 2009
# Python 3.2 - February 20, 2011
# Python 3.3 - September 29, 2012
# Python 3.4 - March 16, 2014
# Python 3.5 - September 13, 2015
# Python 3.6 - 2016-12-23 发布python3.6.0版
Python的发展前景
#未来十年Python的前景会怎样? https://www.zhihu.com/question/22112542/answer/166053516
Python哪些种类
我们现在知道了Python是一门解释型语言,代码想运行,必须通过解释器执行,Python的解释器本身也可以看作是个程序(翻译官司是哪国人不重要),这个程序是什么语言开发的呢? 答案是好几种语言? what? 因为Python有好几种解释器,分别基于不同语言开发,每个解释器特点不同,但都能正常运行我们的Python代码,下面分别来看下:
#CPython:CPython是使用最广且被的Python解释器。本教程以CPython为准。
当我们从Python官方网站下载并安装好Python 2.7后,我们就直接获得了一个官方版本的解释器:CPython。这个解释器是用C语言开发的,所以叫CPython。在命令行下运行python就是启动CPython解释器。
#IPython
IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所增强,但是执行Python代码的功能和CPython是完全一样的。好比很多国产浏览器虽然外观不同,但内核其实都是调用了IE。
CPython用>>>作为提示符,而IPython用In [序号]:作为提示符。
#PyPy
PyPy是另一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。
绝大部分Python代码都可以在PyPy下运行,但是PyPy和CPython有一些是不同的,这就导致相同的Python代码在两种解释器下执行可能会有不同的结果。如果你的代码要放到PyPy下执行,就需要了解PyPy和CPython的不同点。
#Jython
Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。
#IronPython
IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。
安装Python解释器
Python目前已支持所有主流操作系统,在Linux,Unix,Mac系统上自带Python环境,在Windows系统上需要安装一下,超简单
打开官网 https://www.python.org/downloads/windows/ 下载中心
#测试安装是否成功
windows --> 运行 --> 输入cmd ,然后回车,弹出cmd程序,输入python,如果能进入交互环境 ,代表安装成功。
#多版本共存演示
注意:在安装目录下找到python.exe,拷贝一份,命名为python2.exe或python3.exe,一定要保留原版,因为pip工具会调用它。
变量
什么变量
变量是一种可以反应出状态变化的一种机制
为什么要有变量
程序的执行本质就是一系列状态的变化
变量的命名规范:
- 变量名只能是 字母,数字或下划线的任意组合
- 变量名的第一个字符不能是数字
- 关键字不能声明为变量名
定义方式:
驼峰体
AgeOfJinqiu = 26
下划线
age_of_jiniqu = 26
变量的三个特征:(重要)
id type value
#1 == 比较的是value,
#2 is 比较的是id
#强调:
#1. id相同,意味着type和value必定相同
#2. value相同type肯定相同,但id可能不同,如下
>>> x='Info Egon:18'
>>> y='Info Egon:18'
>>> id(x)
4376607152
>>> id(y)
4376607408
>>>
>>> x == y
True
>>> x is y
False
用户与程序交互
name=input('please input your name:')
passwd=input('please your passwd:')
print(name,passwd)
please input your name:jinqiu
please your passwd:123
jinqiu 123
注释
随着学习的深入,用不了多久,你就可以写复杂的上千甚至上万行的代码啦,有些代码你花了很久写出来,过了些天再回去看,发现竟然看不懂了,这太正常了。 另外,你以后在工作中会发现,一个项目多是由几个甚至几十个开发人员一起做,你要调用别人写的代码,别人也要用你的,如果代码不加注释,你自己都看不懂,更别说别人了,这产会挨打的。所以为了避免这种尴尬的事情发生,一定要增加你代码的可读性。
代码注释分单行和多行注释, 单行注释用#,多行注释可以用三对双引号""" """
代码注释的原则:
#1. 不用全部加注释,只需要在自己觉得重要或不好理解的部分加注释即可
#2. 注释可以用中文或英文,但不要用拼音
#选择内容,按Ctrl+/ 可以快速注释
文件头 (了解知识点)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
基本数据类型
数据即变量的值,如age=18,18则是我们保存的数据
变量是用来反映/保持状态以及状态变化的,毫无疑问针对不同的状态就应该用不同类型的数据取标识
数字
#int整型
定义:age=10 #age=int(10)
用于标识:年龄,等级,身份证号,qq号,个数
#float浮点型
定义:salary=3.1 #salary=float(3.1)
用于标识:工资,身高,体重,
字符串
#在python中,加了引号的字符就是字符串类型,python并没有字符类型。
定义:name='egon' #name=str('egon')
用于标识:描述性的内容,如姓名,性别,国籍,种族
字符串拼接(只能在字符串之间进行,且只能相加或相乘
#数字可以进行加减乘除等运算,字符串呢?让我大声告诉你,也能?what ?是的,但只能进行"相加"和"相乘"运算。
>>> name='egon'
>>> age='18'
>>> name+age #相加其实就是简单拼接
'egon18'
>>> name*5
'egonegonegonegonegon'
#注意1:字符串相加的效率不高
字符串1+字符串3,并不会在字符串1的基础上加字符串2,而是申请一个全新的内存空间存入字符串1和字符串3,相当字符串1与字符串3的空间被复制了一次,
#注意2:只能字符串加字符串,不能字符串加其他类型
列表
#在[]内用逗号分隔,可以存放n个任意类型的值
定义:students=['zhangsan','lisi','wangwu',] #students=list(['zhangsan','lisi','wangwu',])
用于标识:存储多个值的情况,比如一个人有多个爱好
列表嵌套、取值
#存放多个学生的信息:姓名,年龄,爱好
>>> students_info=[['jinqiu',18,['play',]],['alex',18,['play','sleep']]]
>>> students_info[0][2][0] #取出第一个学生的第一个爱好
'play'
字典
#在{}内用逗号分隔,可以存放多个key:value的值,value可以是任意类型
定义:info={'name':'egon','age':18,'sex':18} #info=dict({'name':'egon','age':18,'sex':18})
用于标识:存储多个值的情况,每个值都有唯一一个对应的key,可以更为方便高效地取值
字典相关的嵌套、取值
例子:
info={
'name':'jiniqu',
'hobbies':['play','sleep'],
'company_info':{
'name':'lixiang',
'type':'IT',
'emp_num':40,
}
}
print(info['company_info']['name']) #取公司名
2.
students=[
{'name':'zhangsan','age':38,'hobbies':['play','sleep']},
{'name':'lishi','age':18,'hobbies':['read','sleep']},
{'name':'wangwu','age':58,'hobbies':['music','read','sleep']},
]
print(students[1]['hobbies'][1]) #取第二个学生的第二个爱好
布尔
#布尔值,一个True一个False
#计算机俗称电脑,即我们编写程序让计算机运行时,应该是让计算机无限接近人脑,或者说人脑能干什么,计算机就应该能干什么,人脑的主要作用是数据运行与逻辑运算,此处的布尔类型就模拟人的逻辑运行,即判断一个条件成立时,用True标识,不成立则用False标识
>>> a=3
>>> b=5
>>>
>>> a > b #不成立就是False,即假
False
>>>
>>> a < b #成立就是True, 即真
True
接下来就可以根据条件结果来干不同的事情了:
if a > b
print(a is bigger than b )
else
print(a is smaller than b )
上面是伪代码,但意味着, 计算机已经可以像人脑一样根据判断结果不同,来执行不同的动作
布尔类型的重点知识!!!:
#所有数据类型都自带布尔值
1、None,0,空(空字符串,空列表,空字典等)三种情况下布尔值为False
2、其余均为真
可变与不可变类型
#1.可变类型:在id不变的情况下,value可以变,则称为可变类型,如列表,字典
#2. 不可变类型:value一旦改变,id也改变,则称为不可变类型(id变,意味着创建了新的内存空间
格式化输出
程序中经常会有这样场景:要求用户输入信息,然后打印成固定的格式
比如要求用户输入用户名和年龄,然后打印如下格式:
My name is xxx,my age is xxx.
很明显,用逗号进行字符串拼接,只能把用户输入的名字和年龄放到末尾,无法放到指定的xxx位置,而且数字也必须经过str(数字)的转换才能与字符串进行拼接。
这就用到了占位符,如:%s、%d
#%s字符串占位符:可以接收字符串,也可接收数字
print('My name is %s,my age is %s' %('egon',18))
#%d数字占位符:只能接收数字
print('My name is %s,my age is %d' %('egon',18))
print('My name is %s,my age is %d' %('egon','18')) #报错
#接收用户输入,打印成指定格式
name=input('your name: ')
age=input('your age: ') #用户输入18,会存成字符串18,无法传给%d
print('My name is %s,my age is %s' %(name,age))
#注意:
#print('My name is %s,my age is %d' %(name,age)) #age为字符串类型,无法传给%d,所以会报错
基本运算符
算数运算
比较运算
赋值运算
逻辑运算
身份运算
#is比较的是id
#而==比较的是值
python字符串转义符
在需要在字符中使用特殊字符时,python 用反斜杠 \ 转义字符。如下表:
转义字符 | 描述 | 实例 |
---|---|---|
\(在行尾时) | 续行符 | >>> print("line1 \ ... line2 \ ... line3") line1 line2 line3>>> |
\\ | 反斜杠符号 | >>> print("\\") \ |
\' | 单引号 | >>> print('\'')' |
\" | 双引号 | >>> print("\"")" |
\a | 响铃 | >>> print("\a") 执行后电脑有响声。 |
\b | 退格(Backspace) | >>> print("Hello \b World!")Hello World! |
\000 | 空 | >>> print("\000") >>> |
\n | 换行 | >>> print("\n") >>> |
\v | 纵向制表符 | >>> print("Hello \v World!")Hello World!>>> |
\t | 横向制表符 | >>> print("Hello \t World!")Hello World!>>> |
\r | 回车,将 \r 后面的内容移到字符串开头,并逐一替换开头部分的字符,直至将 \r 后面的内容完全替换完成。 | >>> print("Hello\rWorld!")World!>>> print('google runoob taobao\r123456')123456 runoob taobao |
\f | 换页 | >>> print("Hello \f World!")Hello World!>>> |
\yyy | 八进制数,y 代表 0~7 的字符,例如:\012 代表换行。 | >>> print("\110\145\154\154\157\40\127\157\162\154\144\41")Hello World! |
\xyy | 十六进制数,以 \x 开头,y 代表的字符,例如:\x0a 代表换行 | >>> print("\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21")Hello World! |
\other | 其它的字符以普通格式输出 |
|
Python字符串运算符
下表实例变量 a 值为字符串 "Hello",b 变量值为 "Python":
操作符 | 描述 | 实例 |
+ | 字符串连接 | a + b 输出结果: HelloPython |
* | 重复输出字符串 | a*2 输出结果:HelloHello |
[] | 通过索引获取字符串中字符 | a[1] 输出结果 e |
[ : ] | 截取字符串中的一部分,遵循左闭右开原则,str[0:2] 是不包含第 3 个字符的。 | a[1:4] 输出结果 ell |
in | 成员运算符 - 如果字符串中包含给定的字符返回 True | 'H' in a 输出结果 True |
not in | 成员运算符 - 如果字符串中不包含给定的字符返回 True | 'M' not in a 输出结果 True |
r/R | 原始字符串 - 原始字符串:所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。 原始字符串除在字符串的第一个引号前加上字母 r(可以大小写)以外,与普通字符串有着几乎完全相同的语法。 | print( r'\n' )print( R'\n' ) |
% | 格式字符串 | 请看下一节内容。 |
流程控制语句
if判断
if 条件1:
缩进的代码块
elif 条件2:
缩进的代码块
elif 条件3:
缩进的代码块
......
else:
缩进的代码块
练习
如果:成绩>=90,那么:优秀
如果成绩>=80且<90,那么:良好
如果成绩>=70且<80,那么:普通
其他情况:很差
score=input('>>: ')
score=int(score)
if score >= 90:
print('优秀')
elif score >= 80:
print('良好')
elif score >= 70:
print('普通')
else:
print('很差')
while循环
while 条件:
# 循环体
# 如果条件为真,那么循环体则执行,执行完毕后再次循环,重新判断条件。。。
# 如果条件为假,那么循环体不执行,循环终止
例子
#打印0-10
count=0
while count <= 10:
print('loop',count)
count+=1
#打印0-10之间的偶数
count=0
while count <= 10:
if count%2 == 0:
print('loop',count)
count+=1
#打印0-10之间的奇数
count=0
while count <= 10:
if count%2 == 1:
print('loop',count)
count+=1
死循环
import time
num=0
while True:
print('count',num)
time.sleep(1)
num+=1
break continue
#break用于退出本层循环
while True:
print( "123")
break
print ("456")
#continue用于退出本次循环,继续下一次循环
while True:
print "123"
continue
print "456"
用户登陆(三次机会重试)
count=0
while count < 3:
name=input('请输入用户名:')
password=input('请输入密码:')
if name == 'jinqi' and password == '123':
print('login success')
break
else:
print('用户名或者密码错误')
count+=1
for循环
for i in range(10):
缩进的代码块
嵌套循环
九九乘法表
for i in range(1,10):
...: for j in range(1,i+1):
...: print('%s*%s=%s' %(j,i,i*j),end=' ')
...: print()
金字塔
num=6
for cur in range(1,num+1):
...: for i in range(num-cur):
...: print(' ',end='')
...: for j in range(2*cur-1):
...: print('*',end='')
...: print()
数据类型 字符编码 文件处理
数据类型的操作
数字
(整形(int),长整形,浮点型(float),复数)
# int(...)调用创建整型数据的功能
# float(...)调用创建浮点型数据的功能
字符串
掌握操作
#1、strip,lstrip,rstrip (移除空白)
>>> str1 = '**tony***'
>>> str1.strip('*') # 移除左右两边的指定字符
'tony'
>>> str1.lstrip('*') # 只移除左边的指定字符
tony***
>>> str1.rstrip('*') # 只移除右边的指定字符
**tony
#2、lower,upper (大小写)
>>> str2 = 'My nAme is tonY!'
>>> str2.lower() # 将英文字符串全部变小写
my name is tony!
>>> str2.upper() # 将英文字符串全部变大写
MY NAME IS TONY!
#3、startswith,endswith
>>> str3 = 'tony jam'
# startswith()判断字符串是否以括号内指定的字符开头,结果为布尔值True或False
>>> str3.startswith('t')
True
>>> str3.startswith('j')
False
# endswith()判断字符串是否以括号内指定的字符结尾,结果为布尔值True或False
>>> str3.endswith('jam')
True
>>> str3.endswith('tony')
False
#4、format 格式化输出
format括号内在传参数时完全可以打乱顺序,但仍然能指名道姓地为指定的参数传值,name=‘tony’就是传给{name}
>>> str4 = 'my name is {name}, my age is {age}!'.format(age=18,name='tony')
>>> str4
'my name is tony, my age is 18!'
>>> str4 = 'my name is {name}{name}{name}, my age is {name}!'.format(name='tony', age=18)
>>> str4
'my name is tonytonytony, my age is tony!'
#5、split,rsplit 切分split
# split会按照从左到右的顺序对字符串进行切分,可以指定切割次数
>>> str5='C:/a/b/c/d.txt'
>>> str5.split('/',1)
['C:', 'a/b/c/d.txt']
# rsplit刚好与split相反,从右往左切割,可以指定切割次数
>>> str5='a|b|c'
>>> str5.rsplit('|',1)
['a|b', 'c']
#6、join
#从可迭代对象中取出多个字符串,然后按照指定的分隔符进行拼接,拼接的结果为字符串
>>> '%'.join('hello') # 从字符串'hello'中取出多个字符串,然后按照%作为分隔符号进行拼接
'h%e%l%l%o'
>>> '|'.join(['tony','18','read']) # 从列表中取出多个字符串,然后按照*作为分隔符号进行拼接
'tony|18|read'
#7、replace 用新的字符替换字符串中旧的字符
#8、isdigit 判断字符串是否是纯数字组成,返回结果为True或False
了解操作:
# 2.center,ljust,rjust,zfill
>>> name='tony'
>>> name.center(30,'-') # 总宽度为30,字符串居中显示,不够用-填充
-------------tony-------------
>>> name.ljust(30,'*') # 总宽度为30,字符串左对齐显示,不够用*填充
tony**************************
>>> name.rjust(30,'*') # 总宽度为30,字符串右对齐显示,不够用*填充
**************************tony
>>> name.zfill(50) # 总宽度为50,字符串右对齐显示,不够用0填充
0000000000000000000000000000000000000000000000tony
# 3.expandtabs
>>> name = 'tony\thello' # \t表示制表符(tab键)
>>> name
tony hello
>>> name.expandtabs(1) # 修改\t制表符代表的空格数
tony hello
# 4.captalize,swapcase,title
# 4.1 captalize:首字母大写
>>> message = 'hello everyone nice to meet you!'
>>> message.capitalize()
Hello everyone nice to meet you!
# 4.2 swapcase:大小写翻转
>>> message1 = 'Hi girl, I want make friends with you!'
>>> message1.swapcase()
hI GIRL, i WANT MAKE FRIENDS WITH YOU!
#4.3 title:每个单词的首字母大写
>>> msg = 'dear my friend i miss you very much'
>>> msg.title()
Dear My Friend I Miss You Very Mu
列表(list)
列表基本操作符
列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
如下所示:
Python 表达式 | 结果 | 描述 |
len([1, 2, 3]) | 3 | 长度 |
[1, 2, 3] + [4, 5, 6] | [1, 2, 3, 4, 5, 6] | 组合 |
['Hi!'] * 4 | ['Hi!', 'Hi!', 'Hi!', 'Hi!'] | 重复 |
3 in [1, 2, 3] | True | 元素是否存在于列表中 |
for x in [1, 2, 3]: print x, | 1 2 3 | 迭代 |
列表基本操作
# 定义:在[]内,用逗号分隔开多个任意数据类型的值
l1 = [1,'a',[1,2]] # 本质:l1 = list([1,'a',[1,2]])
# 1.按索引存取值(正向存取+反向存取):即可存也可以取
# 1.1 正向取(从左往右)
>>> my_friends=['tony','jason','tom',4,5]
>>> my_friends[0]
tony
# 1.2 反向取(负号表示从右往左)
>>> my_friends[-1]
5
# 1.3 对于list来说,既可以按照索引取值,又可以按照索引修改指定位置的值,但如果索引不存在则报错
>>> my_friends = ['tony','jack','jason',4,5]
>>> my_friends[1] = 'martthow'
>>> my_friends
['tony', 'martthow', 'jason', 4, 5]
# 2.切片(顾头不顾尾,步长)
# 2.1 顾头不顾尾:取出索引为0到3的元素
>>> my_friends[0:4]
['tony', 'jason', 'tom', 4]
# 2.2 步长:0:4:2,第三个参数2代表步长,会从0开始,每次累加一个2即可,所以会取出索引0、2的元素
>>> my_friends[0:4:2]
['tony', 'tom']
# 3.长度
>>> len(my_friends)
5
# 4.成员运算in和not in
>>> 'tony' in my_friends
True
>>> 'xxx' not in my_friends
True
# 5.添加
# 5.1 append()列表尾部追加元素
>>> l1 = ['a','b','c']
>>> l1.append('d')
>>> l1
['a', 'b', 'c', 'd']
# 5.2 extend()一次性在列表尾部添加多个元素
>>> l1.extend(['a','b','c'])
>>> l1
['a', 'b', 'c', 'd', 'a', 'b', 'c']
# 5.3 insert()在指定位置插入元素
>>> l1.insert(0,"first") # 0表示按索引位置插值
>>> l1
['first', 'a', 'b', 'c', 'd', 'a', 'b', 'c']
# 6.删除
# 6.1 del
>>> l = [11,22,33,44]
>>> del(l[2]) # 删除索引为2的元素
>>> l
[11,22,44]
# 6.2 pop()默认删除列表最后一个元素,并将删除的值返回,括号内可以通过加索引值来指定删除元素
>>> l = [11,22,33,22,44]
>>> res=l.pop()
>>> res
44
>>> res=l.pop(1)
>>> res
22
# 6.3 remove()括号内指名道姓表示要删除哪个元素,没有返回值
>>> l = [11,22,33,22,44]
>>> res=l.remove(22) # 从左往右查找第一个括号内需要删除的元素
>>> print(res)
None
# 7.reverse()颠倒列表内元素顺序
>>> l = [11,22,33,44]
>>> l.reverse()
>>> l
[44,33,22,11]
# 8.sort()给列表内所有元素排序
# 8.1 排序时列表元素之间必须是相同数据类型,不可混搭,否则报错
>>> l = [11,22,3,42,7,55]
>>> l.sort()
>>> l
[3, 7, 11, 22, 42, 55] # 默认从小到大排序
>>> l = [11,22,3,42,7,55]
>>> l.sort(reverse=True) # reverse用来指定是否跌倒排序,默认为False
>>> l
[55, 42, 22, 11, 7, 3]
# 8.2 了解知识:
# 我们常用的数字类型直接比较大小,但其实,字符串、列表等都可以比较大小,原理相同:都是依次比较对应位置的元素的大小,如果分出大小,则无需比较下一个元素,比如
>>> l1=[1,2,3]
>>> l2=[2,]
>>> l2 > l1
True
# 字符之间的大小取决于它们在ASCII表中的先后顺序,越往后越大
>>> s1='abc'
>>> s2='az'
>>> s2 > s1 # s1与s2的第一个字符没有分出胜负,但第二个字符'z'>'b',所以s2>s1成立
True
# 所以我们也可以对下面这个列表排序
>>> l = ['A','z','adjk','hello','hea']
>>> l.sort()
>>> l
['A', 'adjk', 'hea', 'hello','z']
# 9.循环
# 循环遍历my_friends列表里面的值
for line in my_friends:
print(line)
'tony'
'jack'
'jason'
4
5
元组
元组与列表类似,也是可以存多个任意类型的元素,不同之处在于元组的元素不能修改,即元组相当于不可变的列表,用于记录多个固定不允许修改的值,单纯用于取
>>> tuple1 = (1, 'hhaha', 15000.00, 11, 22, 33)
# 1、按索引取值(正向取+反向取):只能取,不能改否则报错!
>>> tuple1[0]
1
>>> tuple1[-2]
22
>>> tuple1[0] = 'hehe' # 报错:TypeError:
# 2、切片(顾头不顾尾,步长)
>>> tuple1[0:6:2]
(1, 15000.0, 22)
# 3、长度
>>> len(tuple1)
6
# 4、成员运算 in 和 not in
>>> 'hhaha' in tuple1
True
>>> 'hhaha' not in tuple1
False
# 5、循环
>>> for line in tuple1:
... print(line)
1
hhaha
15000.0
11
22
33
字典
#定义:在{}内用逗号分隔开多元素,每一个元素都是key:value的形式,其中value可以是任意类型,而key则必须是不可变类型,详见第八小节,通常key应该是str类型,
# 1、按key存取值:可存可取
# 1.1 取
>>> dic = {
... 'name': 'xxx',
... 'age': 18,
... 'hobbies': ['play game', 'basketball']
... }
>>> dic['name']
'xxx'
>>> dic['hobbies'][1]
'basketball'
# 1.2 对于赋值操作,如果key原先不存在于字典,则会新增key:value
>>> dic['gender'] = 'male'
>>> dic
{'name': 'tony', 'age': 18, 'hobbies': ['play game', 'basketball'],'gender':'male'}
# 1.3 对于赋值操作,如果key原先存在于字典,则会修改对应value的值
>>> dic['name'] = 'tony'
>>> dic
{'name': 'tony', 'age': 18, 'hobbies': ['play game', 'basketball']}
# 2、长度len
>>> len(dic)
3
# 3、成员运算in和not in
>>> 'name' in dic # 判断某个值是否是字典的key
True
# 4、删除
>>> dic.pop('name') # 通过指定字典的key来删除字典的键值对
>>> dic
{'age': 18, 'hobbies': ['play game', 'basketball']}
# 5、键keys(),值values(),键值对items()
>>> dic = {'age': 18, 'hobbies': ['play game', 'basketball'], 'name': 'xxx'}
# 获取字典所有的key
>>> dic.keys()
dict_keys(['name', 'age', 'hobbies'])
# 获取字典所有的value
>>> dic.values()
dict_values(['xxx', 18, ['play game', 'basketball']])
# 获取字典所有的键值对
>>> dic.items()
dict_items([('name', 'xxx'), ('age', 18), ('hobbies', ['play game', 'basketball'])])
# 6、循环
# 6.1 默认遍历的是字典的key
>>> for key in dic:
... print(key)
...
age
hobbies
name
# 6.2 只遍历key
>>> for key in dic.keys():
... print(key)
...
age
hobbies
name
# 6.3 只遍历value
>>> for key in dic.values():
... print(key)
...
18
['play game', 'basketball']
xxx
# 6.4 遍历key与value
>>> for key in dic.items():
... print(key)
...
('age', 18)
('hobbies', ['play game', 'basketball'])
('name', 'xxx')
需要掌握的操作
1.get()
>>> dic= {'k1':'jason','k2':'Tony','k3':'JY'}
>>> dic.get('k1')
'jason' # key存在,则获取key对应的value值
>>> res=dic.get('xxx') # key不存在,不会报错而是默认返回None
>>> print(res)
None
>>> res=dic.get('xxx',666) # key不存在时,可以设置默认返回的值
>>> print(res)
666
# ps:字典取值建议使用get方法
2.pop()
>>> dic= {'k1':'jason','k2':'Tony','k3':'JY'}
>>> v = dic.pop('k2') # 删除指定的key对应的键值对,并返回值
>>> dic
{'k1': 'jason', 'kk2': 'JY'}
>>> v
'Tony'
3.popitem()
>>> dic= {'k1':'jason','k2':'Tony','k3':'JY'}
>>> item = dic.popitem() # 随机删除一组键值对,并将删除的键值放到元组内返回
>>> dic
{'k3': 'JY', 'k2': 'Tony'}
>>> item
('k1', 'jason')
4.update()
# 用新字典更新旧字典,有则修改,无则添加
>>> dic= {'k1':'jason','k2':'Tony','k3':'JY'}
>>> dic.update({'k1':'JN','k4':'xxx'})
>>> dic
{'k1': 'JN', 'k3': 'JY', 'k2': 'Tony', 'k4': 'xxx'}
5.fromkeys()
>>> dic = dict.fromkeys(['k1','k2','k3'],[])
>>> dic
{'k1': [], 'k2': [], 'k3': []}
6.setdefault()
# key不存在则新增键值对,并将新增的value返回
>>> dic={'k1':111,'k2':222}
>>> res=dic.setdefault('k3',333)
>>> res
333
>>> dic # 字典中新增了键值对
{'k1': 111, 'k3': 333, 'k2': 222}
# key存在则不做任何修改,并返回已存在key对应的value值
>>> dic={'k1':111,'k2':222}
>>> res=dic.setdefault('k1',666)
>>> res
111
>>> dic # 字典不变
{'k1': 111, 'k2': 222}
#json 和字典的相互转换
1、字典(dict)转换为json
import json
# 定义一个字典结构的数据
data = {
'name': 'Bill',
'info': {'sex': 'male', 'age': 29, 'birth': '19900506'}
}
# 将字典转换为json格式
datajson = json.dumps(data)
#指定缩进
datajson = json.dumps(data,indent='\t')
# 查看json格式数据
print(datajson)
print('json数据的格式为:',type(datajson))
运行结果为:
2、json转换为字典结构
import json
# 定义一个json
data = '''
{"name": "Bill", "info": {"sex": "male", "age": 29, "birth": "19900506"}}
'''
# 将json字符串转换为字典
datadict = json.loads(data)
print(datadict)
print(type(datadict))
集合
集合、list、tuple、dict一样都可以存放多个值,但是集合主要用于:去重、关系运算
定义:在{}内用逗号分隔开多个元素,集合具备以下三个特点:
1:每个元素必须是不可变类型
2:集合内没有重复的元素
3:集合内元素无序
# 1.合集(|):求两个用户所有的好友(重复好友只留一个)
>>> friends1 | friends2
{'kevin', 'ricky', 'zero', 'jason', 'Jy', 'egon'}
# 2.交集(&):求两个用户的共同好友
>>> friends1 & friends2
{'jason', 'egon'}
# 3.差集(-):
>>> friends1 - friends2 # 求用户1独有的好友
{'kevin', 'zero'}
>>> friends2 - friends1 # 求用户2独有的好友
{'ricky', 'Jy'}
# 4.对称差集(^) # 求两个用户独有的好友们(即去掉共有的好友)
>>> friends1 ^ friends2
{'kevin', 'zero', 'ricky', 'Jy'}
# 5.值是否相等(==)
>>> friends1 == friends2
False
# 6.父集:一个集合是否包含另外一个集合
# 6.1 包含则返回True
>>> {1,2,3} > {1,2}
True
>>> {1,2,3} >= {1,2}
True
# 6.2 不存在包含关系,则返回True
>>> {1,2,3} > {1,3,4,5}
False
>>> {1,2,3} >= {1,3,4,5}
False
# 7.子集
>>> {1,2} < {1,2,3}
True
>>> {1,2} <= {1,2,3}
True
字符编码
文件处理
文件操作
#1. 打开文件,得到文件句柄并赋值给一个变量
f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r
#2. 通过句柄对文件进行操作
data=f.read()
#3. 关闭文件
f.close()
上下文管理器
with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
data=read_f.read()
write_f.write(data)
打开文件的模式
#1. 打开文件的模式有(默认为文本模式):
r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
a, 之追加写模式【不可读;不存在则创建;存在则只追加内容】
#2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb
wb
ab
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
#3. 了解部分
"+" 表示可以同时读写某个文件
r+, 读写【可读,可写】
w+,写读【可读,可写】
a+, 写读【可读,可写】
x, 只写模式【不可读;不存在则创建,存在则报错】
x+ ,写读【可读,可写】
xb
操作文件的方法
#掌握
f.read() #读取所有内容,光标移动到文件末尾
f.readline() #读取一行内容,光标移动到第二行首部
f.readlines() #读取每一行内容,存放于列表中
f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
#了解
f.readable() #文件是否可读
f.writable() #文件是否可读
f.closed #文件是否关闭
f.encoding #如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容从内存刷到硬盘
f.name
练习
练习,利用b模式,编写一个cp工具,要求如下:
1. 既可以拷贝文本又可以拷贝视频,图片等文件
2. 用户一旦参数错误,打印命令的正确使用方法,如usage: cp source_file target_file
提示:可以用import sys,然后用sys.argv获取脚本后面跟的参数
import sys
if len(sys.argv) != 3:
print('usage: cp source_file target_file')
sys.exit()
source_file,target_file=sys.argv[1],sys.argv[2]
with open(source_file,'rb') as read_f,open(target_file,'wb') as write_f:
for line in read_f:
write_f.write(line)
文件内光标移动
一: read(3):
1. 文件打开方式为文本模式时,代表读取3个字符
2. 文件打开方式为b模式时,代表读取3个字节
二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
注意:
1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
import time
with open('test.txt','rb') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
print(line.decode('utf-8'))
else:
time.sleep(0.2)
练习:基于seek实现tail -f功能
文件的修改
函数
函数的基础
什么是函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。
函数分类
#1、内置函数
为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max()
ps:我们将会在最后详细介绍常用的内置函数。
#2、自定义函数
很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。例如
定义函数
#语法
def 函数名(参数1,参数2,参数3,...):
'''注释'''
函数体
return 返回的值
#函数名要能反映其意义
调用函数
函数名()
函数的参数 重点知识
形参与实参
形参即变量名,实参即变量值,函数调用时将绑定到变量名上,函数调用结束,解除绑定
具体应用
- 位置参数:按照从左到右的顺序定义的参数
位置形参:必选参数
位置实参:按照位置给形参传值
- 关键字参数:按照key=value的形式定义的实参
无需按照位置为形参传值
注意的问题:
- 关键字实参必须在位置实参右面
- 对同一个形参不能重复传值
- 默认参数:形参在定义时就已经为其赋值
可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)
注意:
- 只在定义时赋值一次
- 默认参数的定义应该在位置形参右面
- 默认参数通常应该定义成不可变类型
- 可变长参数
可变长指的是实参值的个数不固定
而实参有按位置和按关键字两种形式,针对这两种形式的可变长,形参对应有两种解决方案来完整的存放他们。分别是*args **kwargs
========================*args===================
In [1]: def foo(x,y,*args):
...: print(x,y)
...: print(args)
In [2]: foo(1,2,3,4,5,6)
1 2
(3, 4, 5, 6)
解构
In [9]: def f(x,y,z):
...: print(x,y,z)
...:
In [6]: f(*[1,2,4,])
1 2 4
========================**kwargs================
In [9]: def foo(x,y,z,**kwargs):
...: print(x,y,z)
...: print(kwargs)
...:
In [12]: foo(1,2,3,a=4,b=5)
1 2 3
{'a': 4, 'b': 5}
In [9]: def foo(x,y,z,**kwargs):
...: print(x,y,z)
...: print(kwargs)
...:
解构
In [14]: foo(2,3,4,**{'a':1,'b':5})
2 3 4
{'a': 1, 'b': 5}
参数解构
例1
In [1]: def add(x,y):
...: print(x,y)
...:
In [2]: add(*{'a':1,'b':2})
a b
In [3]: add(*{'a':1,'b':2}.items())
('a', 1) ('b', 2)
In [4]: add(*{'a':1,'b':2}.values())
1 2
In [5]: add(*{'a':1,'b':2}.keys()
例2
In [18]: def get(x,y,*args):
...: print(max(x,y,*args))
...: print(min(x,y,*args))
...:
In [19]: get(1,2,4,5)
5
1
函数对象 难点
#1 可以被引用
#2 可以当作参数传递
#3 返回值可以是函数
#4 可以当作容器类型的元素
# 函数可以被引用
def add(x,y):
return x+y
fun = add
print(fun(1,2))
# 函数可以作为容器类型的元素
dic={'add':add,'max':max}
print(dic)
print(dic['add'](1,2))
# 函数可以做为参数传入另一个函数
def foo(x,y,fu):
return fu(x,y)
print(foo(1,2,add))
# 函数的返回值可以是一个函数
def bar():
return add
f=bar()
print(f(1,2))
函数嵌套
def max(x,y):
return x if x > y else y
def max4(a,b,c,d):
res1=max(a,b)
res2=max(res1,c)
res3=max(res2,d)
return res3
print(max4(1,2,3,4))
嵌套定义
In [17]: def f1():
...: def f2():
...: print('f2')
...: def f3():
...: print('f3')
...: f3()
...: f2()
...:
In [18]: f1()
f2
f3
名称空间和作用域
名称空间
名称空间:存放名字的地方,三种名称空间,
python test.py
#1、python解释器先启动,因而首先加载的是:内置名称空间
#2、执行test.py文件,然后以文件为基础,加载全局名称空间
#3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
局部名称空间--->全局名称空间--->内置名称空间
#需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例
# max=1
def f1():
# max=2
def f2():
# max=3
print(max)
f2()
f1()
print(max)
#1、作用域即范围
- 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
- 局部范围(局部名称空间属于该范围):临时存活,局部有效
#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
x=1
def f1():
def f2():
print(x)
return f2
x=100
def f3(func):
x=2
func()
x=10000
f3(f1())
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间
global与nonlocal关键字
#3、查看作用域:globals(),locals()
闭包函数
什么是闭包? 内部函数包含对外部作用域而非全局作用域的引用
函数被当做数据处理时,始终以自带的作用域为准。若内嵌函数包含对外部函数作用域(而非全局作用域)中变量的引用,那么该’内嵌函数’就是闭包函数,简称闭包(Closures)
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
#应用领域:延迟计算(原来我们是传参,现在我们是包起来)
x=1
def outer():
x=2
def inner():
print(x)
return inner
func=outer() func() # 结果为2
闭包函数的作用:
目前为止,我们得到了两种为函数体传值的方式,一种是直接将值以参数的形式传入,另外一种就是将值包给函数
import requests
#方式一:
def get(url):
return requests.get(url).text
#方式二:
def page(url):
def get():
return requests.get(url).text
return get
对比两种方式,方式一在下载同一页面时需要重复传入url,而方式二只需要传一次值,就会得到一个包含指定url的闭包函数,以后调用该闭包函数无需再传url
# 方式一下载同一页面
get('https://www.python.org')
get('https://www.python.org')
get('https://www.python.org')
……
# 方式二下载同一页面
python=page('https://www.python.org')
python()
python()
python()
……
闭包函数的这种特性有时又称为惰性计算。使用将值包给函数的方式,在接下来的装饰器中也将大有用处
装饰器
一 为何要用装饰器
#开放封闭原则:对修改封闭,对扩展开放
二 什么是装饰器
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
迭代器
迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动,其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代
生成器
内置函数
模块
os模块
import os
"""
os模块必会操作
os.path.join
os.path.basedir
os.path.abspath
os.path.basename
os.path.dirname
os.remove
os.rename
os.listdir
"""
# 将多个路径组合后返回
s = os.path.join('/home','jinqiu','data')
print(s)
#返回path最后的文件名
base = os.path.basename('/home/jinqiu/ip.py')
print(base)
##获取当前文件的绝对路径
abs = os.path.abspath('OS_module.py')
print(abs)
#返回path的目录
dirname = os.path.dirname('/Users/v_yuanjinqiu/python3/模块/OS_module.py')
print(dirname)
#如果path存在,返回True;如果path不存在,返回False
ex = os.path.exists('OS_module')
print(ex)
##将这个文件的绝对路径分成目录与文件,注意加r
sp = os.path.split('/Users/v_yuanjinqiu/python3/模块/OS_module.py')
print(sp[0],sp[1])
time
import time
#时间戳(time.time)
print(time.time())
#结构化时间(time.localtime)
print(time.localtime())
#字符串时间(time.strftime)
"""
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%x 本地相应的日期表示
%X 本地相应的时间表示
"""
print(time.strftime('%Y-%m-%d %H:%M:%S'))
'''
字符串时间————>结构化时间 strptime()
结构化时间————>时间戳 mktime()
时间戳 ————>结构化时间 localtime()
结构化时间————>字符串时间 strftime()
'''
'''
### 注意:
# strftime('格式','结构化时间') 格式可以少写
# strptime('字符串时间','格式') 格式必须跟字符串时间一一对应!
sys模块
import sys
# 命令行参数List,第一个元素是程序本身路径 ***
# 可以将文件后的内容传递到文件中使用
# 后端代码放在linux服务器上运行,接收cmd方式调用,后边的参数会传递过来
# 需要在terminal或者cmd终端里运行!
print(sys.argv[-1])
# 返回Python解释器加载的路径,模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 ******
# 自定义模块:先从sys.path里面去找
# 可以添加自定义模块的路径
print(sys.path)
# 获取Python解释程序的版本信息
print(sys.version)
# 返回操作系统平台名称
print(sys.platform)
# 退出!
# sys.exit()
random模块
import random
# random.random()
print(random.random())#获取的是0-1之间的随机小数
#0-2之间的整数,都包含,闭区间
print(random.randint(0,2))
#0--5之间的奇数,左闭右开区间
print(random.randrange(1,5,2))
lis = ['whw','wanghw','aaa']
#随机从列表中选择
print(random.choice(lis))
#随机选择两个,两次可以是重复的! ['whw', 'whw']
print(random.choices(lis,k=2))
#随机选2个,没有重复! ['wanghw', 'aaa']
print(random.sample(lis,k=2))
#变成随机排序的
print(random.shuffle(lis)) # 注意这是个操作!返回的是:None
print(lis)
#生成随机验证码
import string
s1 = string.ascii_lowercase
s2 = string.ascii_uppercase
s3 = string.ascii_letters
s4 = string.digits
print(s1)
print(s2)
print(s3)
print(s4)
con = s3+s4
print(con)
y = random.sample(con,6)
yzm = ''.join(y)
print(yzm)
input_yzm = input('请输入你的验证码:')
if input_yzm == yzm:
print('登录成功')
else:
print('验证码不正确')
序列化模块
import json
#dumps与loads
# dumps方法——将字典(主要)对象转换成字符串
dict1 = {
"name": 'jin',
"age": 30
}
print(type(dict1))
s1 = json.dumps(dict1)
print(s1)
print(type(s1))
# loads方法——将字符串转换成字典
s2 = '{"name": "jin", "age": 30}'
s3 = json.loads(s2)
print(s3)
print(type(s3))
#dump与load
#dump
#注意,手动在文件里写的话,文件里的键值如果是字符串的话必须用双引号!!!
# #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
json.dump(dict1,open('a.txt','a+'))
#Load
#load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
d = json.load(open('a.txt','r',encoding='utf8'))
print(d)
print(type(d))
面向对象
封装
继承
多态
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 | 匹配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个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
正则表达式实例
字符匹配
实例 | 描述 |
python | 匹配 "python". |
字符类
实例 | 描述 |
[Pp]ython | 匹配 "Python" 或 "python" |
rub[ye] | 匹配 "ruby" 或 "rube" |
[aeiou] | 匹配中括号内的任意一个字母 |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
[^0-9] | 匹配除了数字外的字符 |
正则表达式修饰符 - 可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
正则表达式函数
re.match函数
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志 |
匹配成功re.match方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
re.search函数
检索和替换
compile 函数
findall函数
异常处理
进程与线程
进程
multiprocessing模块
import multiprocessing
import time
def sing():
for i in range(3):
print('唱歌')
time.sleep(1)
def dance():
for i in range(3):
print('跳舞')
time.sleep(1)
def main():
sing_process = multiprocessing.Process(target=sing)
dance_process = multiprocessing.Process(target=dance)
sing_process.start()
dance_process.start()
if __name__ == '__main__':
main()
传参
"""
args:以元组方式传参
kwargs: 以字典方式传参
"""
def sing(num):
for i in range(num):
print('唱歌')
time.sleep(1)
def dance(name):
for i in range(3):
print('%s 跳舞' %name)
time.sleep(1)
def main():
sing_process = multiprocessing.Process(target=sing,args=(3,))
dance_process = multiprocessing.Process(target=dance,kwargs={"name":"xiaoming"})
sing_process.start()
dance_process.start()
if __name__ == '__main__':
main()
线程
threading 模块
import threading
import time
def sing():
for i in range(3):
print('唱歌')
time.sleep(1)
def dance():
for i in range(3):
print('跳舞')
time.sleep(1)
def main():
sing_thread = threading.Thread(target=sing)
dance_thread = threading.Thread(target=dance)
sing_thread.start()
dance_thread.start()
if __name__ == '__main__':
main()
传参与进程传参一样
协程
import asyncio
async \
def foo1():
print('hello')
await asyncio.sleep(2)
print('world')
async \
def foo2():
print('jin')
await asyncio.sleep(2)
print('qiu')
task = [
asyncio.ensure_future(foo1()),
asyncio.ensure_future(foo2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
/Users/v_yuanjinqiu/python3/venv/bin/python /Users/v_yuanjinqiu/python3/协程.py
hello
jin
world
qiu
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通