Python 基础知识及实战

Python是一门简单易学的编程语言,支持非常多的模块和功能,适合于初学者。Python属于解释型语言,这意味着你在运行时不需要进行编译,解释器会解释并运行你的代码。这虽然会降低运行速度(不到几秒),不过后期是可以自行编译的。同时,Python也有非常多的库可以让你支持其他语言,如C,Tcl,Cocos2d,OpenGL等。

本教程适用于完全没有基础,或是只了解过一点编程知识的新手,相信这能让你明白更多Python的知识。

1 初识Python

Hello,World!

1.1 Python的安装和管理

Python的官网是https://www.python.org/,Python的文档地址是https://docs.python.org/

安装比较简单,这里不再赘述,可以自行搜索或者看一下下面这篇教程。需要注意的是,Python有很多版本,建议使用Python3,即版本中以3.开头的。版本3.7以上最好。Python3 环境搭建 | 菜鸟教程Python3 环境搭建 本章节我们将向大家介绍如何在本地搭建 Python3 开发环境。 Python3 可应用于多平台包括 Windows、Linux 和 Mac OS X。 Unix (Solaris, Linux, FreeBSD, AIX, HP/UX, SunOS, IRIX, 等等。) Win 9x/NT/2000 Macintosh (Intel, PPC, 68K) OS/2 DOS (多个DOS版本) Pal..https://www.runoob.com/python3/python3-install.html

编程时,可以使用Python自带的IDLE编辑器。如果安装时没有勾选IDLE的框,IDLE编辑器就没有下载,后期可以在安装包更改。 

1.2 使用IDLE编辑器

使用非常简单,首先在电脑上找到IDLE的图标:

点开后出现这样一个窗口:

 这个是Python的交互界面(Python Shell),编程者在>>>的符号后面输入代码,获得响应。

不过大多数Python程序并不是这样的。在File菜单中选择New File或者按下Ctrl-N,可以新建一个Python文件窗口。通过Save(保存)或Save as(另存为)保存文件,文件的后缀名一般是*.py和*.pyw,默认是*.py。这两种格式是有区别的,后期会讲述,一般命名为*.py就好。

扫描二维码关注公众号,回复: 15012587 查看本文章

运行文件时,在Run菜单中选择Run Module或按下F5键。

对内容进行编辑,如查找、替换、前往第几行的功能都在Edit菜单,读者可以自行体会。

1.3 代码注释

几乎所有程序语言都支持注释,即在一段代码后面标注一些内容,方便编程者理解。Python中的注释以#井号开头。也可以用多行字符串进行注释。

print("sth") #在屏幕上打印"sth"

2 基础知识

在本环节,你将学习一些基础的理论,对于毫无基础的新手可能比较难懂,不过在后面的实战环节中你会更加理解。

新手需要注意一点:所有的语法格式中使用的符号都必须是英文符号,不能是中文符号!!

2.1 关键字

Python中有一些特殊的单词,被称作关键字或者保留字(Keyword),有一些特殊的功能,后面会讲到。如下:

False None True and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield

其中有一些,如async、await是低版本没有的。Python2中,还有一个print关键字,Python3改成了函数。

2.2 类和对象

基本知识

对象(Object)是指一个用代码定义,有实际的值,也有一些相关的属性的虚拟物。类(Class)可以解释为一个类型,用来创建一个对象。用瓶子来举例,在现实生活中,可以把类理解成能够创造一个瓶子的物品;通过类创建一个对象,就是把这个瓶子创造了出来,同时规定它的属性,比如颜色、形状等。

类是可以自己定义的,考虑到有些读者基础不够,这里暂且不提,放到后面讲述。

使用类定义一个对象的方法是在类的后面加上括号,括号中写上参数,关于参数将在函数的部分介绍:

<类名>(<参数>)

例如:object是一个类,而object()是一个对象。

我们可以调用类的属性(Attribute)或方法(Method),调用方法为:

<对象>.<属性>
<对象>.<方法>(<参数>)

比如有一个叫做obj的对象,调用里面的属性attr和方法met,写作:

obj.met()
obj.attr

类有继承的操作,可以创建一个类,让它继承一个类,继承的类叫做基类或父类(Parent),这个类(子类)会拥有父类的所有属性和方法,并且可以更改。

Python中有一些默认的类型,被称作基本数据类型,有str, int, float, tuple, list, dict, set, NoneType, bool等几种。

还有一种类型complex,用来表示数学上的复数概念,格式为

<实部>+<虚部>j

#如:5+3j

下面依次介绍其他几种类型:

str

被称作字符串(string),使用英文的单引号和双引号括起来,里面可以是任何字符。

"这是一句字符串,里面可以是任何东西。"
'这是一句字符串,里面可以是任何东西。'

如果想要在字符串中使用引号,但是外面用了引号,出现混淆的情况怎么办呢?可以使用转义字符"\",它是一个反斜杠,在键盘右上方,位于中括号的按键旁边。转义字符也可以组成换行符、制表符等等。

使用了转义字符的字符串 实际表示
\n 换行符,表示换一行
\t 制表符,表示一个tab键,一般相当于四个空格
\" 表示一个英文双引号,避免混淆
\' 表示一个英文单引号,避免混淆
\\ 表示一个反斜杠符号

如果想表示一段内容:

这是        ""哈哈哈

用字符串表示为:

"这是\t\"\"哈哈哈"

或者

'这是\t""哈哈哈'      这里混用了单双引号,就可以不用转义字符了。

字符串也可以是多行的,比如"abcde\nfghij"可以用三引号定义的多行字符串书写,如下:

"""abcde
fghij"""

int

被称为整数(Integer),和数学上的整数概念是一样的。定义整数也很简单,直接用数字表示即可。比如下面几行都是整数:

1
3444555566666
0
-22

float

被称为浮点数(Floating Number),即为数学上的小数。例如下面都是浮点数:

0.33
2.0
-4.5556

注:2.0不是整数,而是浮点数!但如果没有小数点,写作2的话它就是整数了。

tuple

被称作元组(Tuple),是一个序列,储存有各种Python对象。使用圆括号括在外面,然后里面的Python对象用逗号间隔(注意都要用英文的符号)。元组只能定义或调用,但是不能修改里面的部分内容,要改就全部改掉(与接下来介绍的list不同)。如下面的元组,里面储存了两个字符串和两个整数对象,之间用逗号分隔,每个对象称作元素。

("11", "22", 33, "11")

在元组定义时,如果里面只有一个对象,那么往往会在后面一个括号的前面加上一个逗号。因为()括号也有分组的意思,Python中的运算规则是先运算括号里的内容。如果不加逗号,解释器会误解,以为那是运算的意思,从而忽略括号。比如,正确的表示方法为:

("sth",)

而不是:

("sth")

list

被称作列表(List),定义方法和元组类似,区别是把圆括号换成了方括号。列表和元组不一样,里面的内容可以根据列表的位置进行修改。示例:

["11", "22", 33, "11"]

dict

被称作字典(Dictionary),可以包含一些对应对象,使用花括号进行定义:

{"name":"Tom", "age":1, "birthday":(2022, 1, 1)}

在上面这个字典中,"name" "age" "birthday"这种在引号前面的被称作键(Key),后面的对应对象被称作值(Value),键值之间用冒号分隔。一组键和值被称作一个键值对或是一个项(Item) ,键值对之间用逗号隔开。可以根据字典的键来访问值,也可以修改键值。但是,与元组和列表不同,字典的键是不能重复的,如果重复了将会删除前面的键值对,保留后面的键值对。

set

被称作集合(Set),和数学上的集合类似。也使用花括号进行定义:

{2, 3, "333", 0}

集合有这些特性:

1.集合中没有重复的元素。

2.集合没有顺序的概念,所以无法根据顺序去修改。

集合有自己的运算方式,交集&,并集|,差集-,交差补集^ 。比如<集合1> & <集合2>。

NoneType

NoneType是一个空值(None),记作None。None其实也是一个关键字。

None

bool

被称作布尔值(Bool),一共有两种:真(True)或者假(False)。每一个对象都有它的布尔值,空列表、空元组、空字符串、0、空值等的布尔值是False。

虽然布尔值只有两个,但是使用频率还是很高的。 True和False是两个关键字。

True
False

2.3 函数(调用)

函数(Function)和数学上的函数概念有一些类似。函数把大串的表达式简化,有时候允许编程者附上一些参数(Argument)调用,再根据参数进行运行函数里面的表达式。函数可以自己定义,调用方法和类的调用方法类似。

比如我要完成一些很复杂的功能,写了很多代码,并且在执行代码时会多次执行这些代码。如果我想重复调用,可以复制粘贴这段代码。但是我把它写到一个叫做func自定义的函数中,之后调用时,就可以直接运行func(),这样就避免了许多复杂的工作。

部分函数支持传递参数。参数分为必须参数、默认参数、可变参数、关键字参数。函数指定了参数后,编程者提供的参数会传递到函数内部运算。函数传递的顺序是:必须参数、可变参数、默认参数、关键字参数,传递顺序颠倒可能会发生错误。

参数 说明 传递方法 示例
必须参数

必须指定的参数

<参数值> f(1)
默认参数

可以不指定的参数,不指定会有一个默认值

<参数名>=<参数值> f(arg=1)
可变参数 可以传递不同数量的参数,也可以不传递 传递多个<参数值>,参数值之间用逗号隔开;也可以用元组形式传递 f(1,2,3..)
关键字参数 可以传递不同数量的参数,也可以不传递 传递多个<参数名>=<参数值>,键值对之间用逗号隔开;也可以用字典形式传递 f(a=1,b=2..)

Python有一些内置方法,包括类和函数,你可以调用它们。

2.4 变量和赋值

定义变量

所谓变量,指的是一个量,能够拥有一个值。你可以在程序中定义变量,可以改变变量,删除变量,当然也可以在程序中使用变量(即调用)。变量的值并不是什么都可以,必须符合Python语法,并且得是一个Python对象。定义变量的语法格式是:

<变量名> = <变量的值>

一般来说,定义一个变量的操作,习惯被称作赋值(Assignment)。

后期修改变量也是一样的,只要变量名不变,把变量的值替换就好了。

变量名遵从一定的命名规范,由字母、数字或下划线“_”组成。并不一定要是一个单词,因为解释器不会关注你的拼写。变量名也可以是中文,不过最好不要那样,因为从没有人用汉字命名过。

变量尽量不要太过复杂,比如skdjflsdkfjlskdf这种变量不好记又没有意义。变量应该具有描述性,如name, number,这样好记而且好懂。

变量的命名尽量不要用双下划线开头,双下划线结尾,比如__a__这种。有一些特殊变量带有双下划线开头,双下划线结尾,自动就存在,如__name__,__file__。

同时还有这样的禁忌,犯了这些变量命名错误,会被解释器解释为异常,抛出错误信息:

错误的命名方式 错误示例
出现除下划线之外的特殊符号 name$
变量名中间空格 na me
用关键字命名 lambda
以数字开头 2nd

赋值的好处有:

1.简化代码,增加代码的可读性。

2.使后期可以多次重复编辑,更改,调用。

比如下面的操作,都属于赋值:

do_something = True
value12 = 12
name = "XXX"
NUMBER = 3

赋值的等于号后面的内容都属于Python对象。

查看变量地址

每个变量都储存在一个Python地址(Id)中,可以使用id函数查看。

id(<变量名>)

2.5 运算符

Python的运算符是一些符号,也有是关键字,根据功能可以分类为算术、赋值、比较、逻辑、位、成员、身份几类,接下来介绍常用的几种。位运算符过于专业,不是很常用,故不再讲述。

算术运算符

符号 意义 示例
+ 表示相加 1+2得到3
- 表示相减 1-2得到-1
* 表示相乘 1*2得到2
/ 表示除以 1/2得到0.5
% 表示取模(返回除法运算后的余数) 4%3得到1
** 表示幂运算 3**3得到27
// 表示除法运算后取整数 5//3得到1

赋值运算符

赋值运算符和算术运算符的不同之处在于,它是算术运算符后面加上了一个等号,比如+=, -=, **=符号。最常用的赋值运算符是"="符号,之前讲赋值时介绍过了。其他的赋值运算符都很好理解,相当于变量进行算术计算后赋值。比如a = a + 1可以用赋值运算符简写成a += 1,简单了很多。

比较运算符

使用比较运算符进行运算,会返回一个布尔值。比较结果成立返回True,比较结果不成立返回False。 

符号 意义 示例
== 表示相等 "22" == "22"得到True
!= 表示不等于 "22" != "33"得到True
> 表示大于 4 > 1得到True
< 表示小于 4 < 10得到True
>= 表示大于等于 4 >= 1得到True
<= 表示小于等于 4 <= 10得到True

逻辑运算符

逻辑运算符其实是几个关键字,进行逻辑运算后返回True或False。

符号 意义 示例
and x and y中,如果x的bool是True并且y的bool是True,则返回True,否则返回False True and True得到True
or x and y中,如果x的bool是True或者y的bool是True,则返回True,否则返回False True or False得到True
not 返回相反的bool值 not True得到False,not False得到True

 成员运算符

成员运算符也是几个关键字,进行运算后返回True或False。

符号 意义 示例
in 在序列中找到返回True,否则返回False 1 in [1, 2, 3]得到True
not in 在序列中找到返回False,否则返回True 1 in [2, 3, 4]得到True

身份运算符

 这也是几个关键字,进行运算后返回True或False。

符号 意义 示例
is 储存地址一致返回True,否则返回False a is b中如果a和b地址一样返回True
is not 储存地址一致返回False,否则返回True a is b中如果a和b地址一样返回False

2.6 模块

基本知识

一个单独的Python文件,或者一个文件夹里的Python文件集被称作模块(Module)。在一个Python文件中引用其他模块的属性或方法,叫做模块的导入(Import)操作。调用模块的属性和在类中调用的方法类似:

<模块名>.<属性或方法>

Python有很多内置模块,又被称作标准库,你可以通过导入调用里面的方法和属性,导入的操作将在后面介绍。

常用模块

Python有很多常用的内置模块,比如os, sys, copy, functools, random, math等。

os用于处理文件和文件路径;sys支持一些与程序相关的操作,比如退出程序;copy用于复制对象,主要是为了避免对象id一致导致的问题;functools中有一些实用的与函数有关的方法;random用于随机生成;math中有很多的数学计算函数。

导入模块

导入模块有以下几种方式,下面以导入内置库sys为例。(import, as, from都是关键字)

import sys #导入sys
import sys as sys_new #导入sys并改名为sys_new
from sys import exit #从sys库中导入exit函数,所有导入的方法用逗号隔开
from sys import * #从sys库中导入所有内容

使用第一、第二种方法导入时,后期可以随意访问模块里的变量,但是访问时必须加上模块名称(或是自己通过as改过的名字),写作<模块名>.<变量>;使用第三种方法导入时,只能使用后面导入的变量,但是访问时可以不加模块名;使用最后一种方法导入时,可以随意访问模块里的变量,并且不需要加模块名称。

虽然第四种方法可能比较方便,但容易造成变量名的混淆,并不是很推荐。

使用pip工具安装第三方库

相对于Python内置模块,Python还有多的数不清的第三方模块,需要安装到计算机上才能使用。大多数Python程序都会用到它们。下面介绍使用pip工具安装第三方模块。(pip工具如果没有在安装Python的时候勾选,可以修改)

首先启动cmd(命令行界面),它是这样的

启动后,输入pip install 和需要安装的模块

这里以安装pyperclip库为例,这是一个进行复制粘贴操作的模块

输入完后按下回车,一般来说,等一会就安装好了,如果出现错误,请检查网络。安装的第三方模块被放进了lib/site-packages文件夹。

再次进入编辑界面,就可以导入pyperclip模块了。

2.7 异常

基本知识

异常(Exception)是指运行代码时遇到的错误,使解释器无法理解,从而报错。异常类型有很多,但并不是所有都会在编程时遇到。异常也可以自己抛出或定义,可以自己捕获并处理异常。异常发生时,会显示出来,被称作回溯(Traceback)。

如上面这个异常,第一行显示的是报错的提示,第二行显示的是出错位置,第三行显示的是出错代码,第四行显示的是异常名称以及报错信息。

每一个异常都是一个类,继承BaseException是所有异常的基类。在BaseException的下面,有Exception异常,几乎所有异常都继承它。有一些特殊异常,一般没有必要被捕获,所以不继承Exception,而是直接继承BaseException。

常见异常

下面介绍常见的异常:

异常名称 报错原因
NameError 调用了未定义的变量,导致解释器找不到变量的位置
TypeError 类型错误,一般是没能正确处理类型,比如将字符串和数字相加,这是不合理的操作
ValueError 参数错误,一般是传入参数不合理导致
UnboundLocalError 在函数中调用了未定义的变量(与局部变量有关,后面介绍)
AttributeError 属性或方法错误,一般是因为在类或模块中没有属性或方法
SyntaxError 语法格式错误,缩进不到位,错误搭配符号都会导致这个异常触发
ImportError 导入失败,一般是因为没有在模块中找到方法或属性
ModuleNotFoundError 导入模块失败,一般是因为没有找到模块
IndexError 提供了不合理的索引
RecursionError 递归深度不够(递归指的是方法中调用自身)

手动触发异常

raise关键字可以触发一个异常,语法是

raise <异常名>

 raise后面的异常名还可以有提示语句,语法是

raise <异常名>(<提示字符串>)

例如

raise Exception("你手动触发了一个异常!")

捕获异常

异常是可以捕获并且处理的,捕获异常需要使用try except finally else这四个关键字,不过一般不会全部用上。下面的这段代码可以让你理解四个关键字在捕获异常时的用处。

try:
    <代码>
except: #如果try语句中的代码中出现了异常
    print("检测到异常")
else: #如果没有异常
    print("没有异常")
finally: #不管有没有异常,这段代码都必须执行。
    print("不管有没有异常,这段代码都必须执行。")

try语句是不能单独出现的,必须与except,else或finally搭配使用。

如果想要对不同的异常进行不一样的处理,可以使用多个except代码块,如下:

try:
    <代码>
except ZeroDivisionError: #检测到0作除数造成的错误
    print("除数不能为0!")
except (TypeError, ValueError): #检测到TypeError或ValueError
    print("类型或参数错误!")

2.8 常见语法

缩进

缩进(Indent)指代码在开头空出一定距离,缩进一般是四格。比如下面的条件判断,if elif else后面的代码都用了缩进,目的是区分代码。缩进不当会导致异常发生。缩进的提示符是英文冒号。

条件判断

关键字if, elif, else用于条件判断。if指的是判断一个值是否为True,如果为True将执行一段代码。

elif指的是如果if中条件不成立,则再次进行判断,如果为True执行一段代码。else指的是如果上面的if elif判断都不成立,那么执行一段代码。

你可以只写if部分,省略elif和else的部分。

if <对象>:
    <执行代码>
elif <对象>:
    <执行代码>
else:
    <执行代码>

什么都不做

Python中的pass关键字表示什么都不做。如果在有冒号的结构后面没有想要的代码,可以写pass。

a = 1
if a == 1:
    pass #什么都不做

if a == 1: #如果后面不写任何东西,会报错

循环结构

如果想要重复执行代码,可以利用循环。循环有两种,分别是for循环和while循环。
for...in...结构:

for <变量名> in <序列>:
    <执行代码>
for i in [1, 2, 3, 4, 5]:
    print(i) #print是一个内置函数,表示在屏幕上显示一段内容

这就是一个for循环。循环的数量和后面提供的序列数量有关。后面的序列属于可迭代对象。每循环一次,变量i就被赋予一个新的值。在上面这个循环中,分别会在屏幕上显示1,2,3,4,5,都是后面提供的序列中的元素。这个操作也被称作遍历。

while循环结构:当对象为True,循环执行代码

while <对象>:
    <执行代码>
a = 1
while a:
    print("sth")

 如上面这个代码,当a为True的时候,代码一直执行,这会导致一个死循环,永远跳不出来。但如果代码中把a更改为0,也就是False,代码就可以跳出来了。

再循环中可以跳出循环。continue关键字表示跳出当前循环,break关键字表示跳出整个循环。

for num in [1, 2, 3, 4, 5]:
    if num == 3:
        continue
    print(num)

这段代码中,如果检测到num == 3,那么就跳出当前的循环。这样就不会执行到后面的print(num)。

这段代码会输出除去3以外,其他的列表元素。

for num in [1, 2, 3, 4, 5]:
    if num == 3:
        break
    print(num)

这里使用了break,那么检测到num == 3后整个循环都结束了,只会打印1和2.

有一种语法结构,将for循环和else搭配使用。如果循环是正常结束而不是中间调用了break,就会执行else后面的代码。

for i in [1, 2, 3, 4, 5, 6]:
    if i == 3:
        break
else:
    print("中途没有break,循环正常结束。")

这段代码中,如果i == 3,跳出循环,不会打印那一段内容。但如果设置成i == 7,列表中没有,中间就不会break,循环将会正常结束,答应else后面的内容。 

删除变量

删除变量使用del关键字

del <变量名>
a = 1
del a

变量删除后,之后调用就会报错NameError。 

断言

关键字assert是断言的意思,语法是

assert <bool>, <str>

如果<bool>是False, 会抛出一个AssertionError异常,后面的<str>是异常提示内容,强制终止程序。主要运用于代码调试。

2.9 元组、列表、字典

前面,我们已经介绍过元组、列表和字典。接下来,你将学习到一些关于它们的详细操作。

索引和切片

索引(Index)又称作下标(Subscript),是一个整数,表示一个序列中的位置。列表中的第一个,下标为0,第二个下标为1,以此类推。字符串包括元组也有下标引用的操作。 

"strs"
s的索引是0
t的索引是1
r的索引是2
s的索引是3

访问下标时,使用这样的语法:

<对象>[<下标>]

 比如"strs"[1]代表访问字符串"strs"中索引为1的字符。这个操作将会返回"t"

索引也可以是负数,代表从后往前数。序列中最后一个为-1,倒数第二个为-2,以此类推。

"strs"
s的索引是-4
t的索引是-3
r的索引是-2
s的索引是-1

将索引结合起来,以截取序列中某一片段,这被称作切片或分片。切片的语法是:

<对象>[<起始点>:<终止点>:<步长>]

 起始点表示序列中开始截取的那个点,终止点表示终止截取的点,步长代表截取的间隔长。有一些是可以省略不写的

"strs"[0:3]

这个代表截取"strs"中从索引0到索引2的部分,注意:不包括3!这个操作返回"str"。如果要截取一直到索引3,那么应该写作"strs"[0:4]。

起止点也是可以省略的,比如"strs"[:]中间只有一个冒号,表示从头截到尾,返回"strs"。写作"strs"[1:],表示截取从1到结尾的内容,返回"trs"。写作"strs"[:-1],表示从开头截到倒数第二个索引位置,返回"str"。

步长如果不写,那就默认为1,表示以索引依次+1的顺序获取切片。如果设置为2,写作"strs"[0:3:2],表示为从0截取到2,中间截取时间隔2,返回"sr",截取时中间空开了。步长如果为负数,就表示倒序截取。利用这个原理,"strs"[::-1]可以把字符顺序倒过来。

列表添加、删除元素

列表有append,insert方法,可以用来添加元素。append的作用时在列表末尾添加元素,insert需要给定一个索引,在索引前面插入元素。

lst = ["a", "b"]
lst.append("c") #在列表末尾添加元素"c"
lst.insert(0, "a-1") #在列表索引为0的元素前面添加"a-1"

删除列表元素有三种方式,使用列表的remove, pop方法或者del关键字。

lst = ["a", "b"]
lst.remove("a") #删除列表中的"a"这个元素
lst.pop(0) #删除列表中索引为0的元素
del lst[0] #删除列表中索引为0的元素
del lst[0:2] #删除列表中索引为0到1的元素

获取、修改字典值

dic = {"a":1, "b":2, "c":3}
dic["a"] #获取字典值
dic["a"] = 2 #修改字典值

删除字典键值对

使用del关键字可以删除字典的键值对

dic = {"key":"value"}
del dic["key"]

2.10 常用内置函数

虽然习惯叫做内置函数,但有一些方法并不是函数。所有内置函数储存在模块__builtins__里面,这个模块会自动导入,所以无需要导入它。这个模块是不是用Python编写的,所以你在lib里面是找不到的。

str, int, float, tuple, list, dict, set, bool, complex

这几个类用于类型转换,比如把数字3转换成字符串写作str(3),返回"3"。如果你不记得这几个类代表的意思,可以回到前面看看。

print

作用是把一串内容打印到屏幕上,调试时很常用的一个函数,在制作CLI程序(后面讲述)时少不了。使用方法:

print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

 value是输出的值(是一个可变参数),sep是值之间的间隔,end是输出末尾的内容,file和flush暂时不提。

len

返回序列的元素数量,比如len([1, 2])返回2。

max, min

作用分别是返回序列中的最大值和最小值。

sum

返回对一个序列求和的值。

type

返回对象的类型,比如type(1)返回int类。

round

返回对一个浮点数保留指定位数的小数,比如round(0.12345, 2)返回0.12345保留2位小数的结果。

range

可以生成从一个数到一个数之间的数,达到数数的功能,主要与for循环结合使用。有以下几种用法。

range(3) #表示从0(默认)数到2,步长默认为1。转换成列表为:[0, 1, 2]
range(1, 3) #表示从1数到3,步长默认为1。转换成列表为:[1, 2]
range(1, 4, 2) #表示从1数到4,步长设置为2。转换成列表为:[1, 3]

与for循环搭配使用:

for num in range(5):
    print("循环次数:", end="")
    print(num+1)

 这样,刚好循环5次。

help

用来查看某个对象的帮助文档,使用方法是help(thing)。比如想要查看int函数的使用方式,只需要在Shell执行help(int),就会出现以下内容。

2.11 整数、浮点数

之前已经提到过整数和浮点数的概念了。运用之前运算符的知识,我们可以对数进行运算。

a = 1
b = a + 1
print(b)

#输出:2

需要注意一点:对数字进行运算时,确认数字是否为整数或浮点数类型。如果是字符串,那么先要把字符串转换成数字。使用之前讲过的int()或float()方法。

2.12 字符串

之前讲过关于字符串的内容,这里提醒一句,字符串可以以下标或切片形式调用。

字符串拼接

字符串是可以拼接的,使用+符号就可以完成。比如"ab"+"cd"得到"abcd"。

字符串也可以复制,使用*符号完成。比如"ab"*4把字符串"ab"复制成"abababab",重复了4次。

字符串格式化

格式化指的是将某个对象使用一种简便形式添加到字符串中的操作。

字符串有两种格式化方式,一种是使用%,另一种是使用format方法,这里介绍%的方法,format暂不讲述。

%s表示插入字符串,如下,string的值格式化后变成了"abcdefgh"

ins = "ef"
string = "abcd%sgh"%ins

%d表示插入数字,如下,string的值格式化后变成了"1234567" 

ins = 23
string = "1%d4567"%ins

%.<整数>f 表示插入浮点数,并且保留<整数>位小数。如下,string的值变成了"num:1.23"

ins = 1.2333333333
string = "num:%.2f"%ins

后面的插入内容可以有多个,但是需要用元组的形式,如下,string的值变成了"插入1插入2" 

string = "插入%d插入%d"%(1, 2)

 如果后面有%的格式化,但是文本中又有百分号,这会造成弄混。避免这样的事情发生,只需要把文本形式的%写作%%双百分号,就会以字符形式呈现在字符串中。

常用字符串方法

split方法返回将字符串以某个字符为分界拆分成的一个列表。如下,string的值变成了["a", "b", "c", "d"]。

string = "a,b,c,d"
string = string.split(",")

replace方法将替换字符串中的内容。如下,string的值变成了"全新的12345" 。

string = "旧的12345"
string = string.replace("旧的", "全新的") #把"旧的"替换成"全新的"

lower和upper分别返回字符串的小写和大写形式。

2.13 函数(定义)

定义函数

前面简要介绍过函数,现在详细讲述一下定义函数以及注意事项。

def关键字用来定义一个函数,格式是这样的:

def <函数名>(<参数>):
    <函数内容>

 示例:

def pr(): #定义一个名字为pr的函数,它没有参数
    print("这是pr函数中的代码")
    print("你好")

运行的时候,执行pr()

pr()

"""
输出:
这是pr函数中的代码
你好
"""

全局变量和局部变量

在函数中定义的变量,被称作局部变量。相对于局部变量,在主代码里面定义的叫做全局变量。

局部变量是不能在当前函数外面调用的,所以下面这段代码会报一个错误,显示找不到变量var:

def func():
    var = 2

func()
print(var) #报错:NameError

但是函数中可以访问函数外面的全局变量,但是不能修改。如果修改全局变量,会报错UnboundLocalError,显示找不到变量。

如果想要在函数中修改全局变量,那么应该怎么办呢?Python中提供了global关键字,可以实现这个功能。把源代码改成这样就不会出错:

def func():
    global var #设置var为全局变量
    var = 2

func()
print(var)

 函数的返回值

函数可以有一个返回值,即为运行后返回的对象。return关键字可以实现返回值操作。

def func():
    return "in func"

a = func()

运行这段代码后,变量a的值就变成了func函数的返回值"in func"。需要注意的是,函数return之后,就会退出函数,如果代码在return后面就没法执行到了。所以return也有退出函数的作用。

如果函数不规定返回值,那么就返回None。 

定义函数的参数

函数中定义参数的方式和调用的方式略有不同,是这样的:

def func(a, b=None, *c, **d):
    pass

这些参数可以作为局部变量在函数内部进行处理。

其中a表示的是必选参数;b是默认参数,后面的None代表了它的默认值;*c是可变参数,调用函数时,一系列个可变参数都作为元组的形式传递到局部变量c;**d是关键字参数,调用时,所有的键值对以列表形式传递到局部变量d。

内层函数和外层函数

函数有内外层之分。在函数里面定义的函数被称作内层函数。在内层函数中不能修改外层函数的变量,在外层函数中不能调用内层函数的变量。但是可以使用nonlocal关键字达到这个目的,用法和global一致。

递归函数

在函数中调用函数本身,这叫做递归。递归是有限度的,一般只能递归1000次,超过就会报错RecursionError。

递归深度是可以自己设置的,sys.setrecursionlimit方法可以设置递归深度。

import sys
sys.setrecursionlimit(2000) #设置递归深度为2000

如果代码有问题,设定递归深度是没有用的,下面就是几个会导致递归出错的代码: 

def func():
    func()

func()
def func1():
    func2()

def func2():
    func1()

func1()

2.14 类和对象(定义)

定义类和对象

class关键字用于定义类,在class的缩进底下定义类变量和方法。

class <变量名>:
    <类属性、方法>
class Obj:
    class_name = "obj" #类变量

    def run(self): #类的方法
        print("obj run") 

 根据类,可以定义一个对象,这个之前介绍过,方法是<类名>(<参数>)。这个过程被称作类的实例化过程。

类的属性和方法

每个类中可以定义方法,相当于在类中定义函数。一般这个函数会有一个参数,放在类的前面,运行类的方法时会自动传递这个参数,这个参数代表类的本身,我们习惯上把这个变量写作self。

通过self这个参数,我们可以在方法中定义类的实例属性,定义方法是这样的:

class Obj:
    def func(self):
        self.attr = 1

在这段代码中,在func方法里面定义了类的attr属性赋值为1。这种变量被称作实例属性,和类变量是有区别的。类变量是公用的,写在方法外面。如果运行func方法,就会添加这个实例属性。生成后,在外面也可以调用实例属性。

self也可以用来调用类的方法。类中的func函数,调用方法就是self.func()

特殊方法__init__

类中有一些特殊方法,通常以双下划线开头双下划线结尾,其中最常用的是__init__方法。__init__方法规定实例化类时需要提供的参数,实例化类的时候会自动运行这个方法。

class Person:
    def __init__(self, name):
        self.name = name

这段代码定义了一个Person类。实例化类的时候,必须传递一个参数name,然后__init__方法处理这个name变量,将自己的实例变量name赋值为name。注意:实例变量定义后,可以在类的所有方法中调用,而参数中的name只是一个局部变量而已。

特殊方法__str__

__str__返回类的字符串形式。

class Person:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return "类str"

将实例化的类转换成字符串,将会返回"类str" 

类的私有属性和方法

私有属性、方法,指的是只能在类的内部访问,不能在类的外面访问的属性或方法,和实例属性和普通方法不同。定义类的私有属性或方法很简单,只要在实例属性或方法的变量名前面加上双下划线"__"即可。

类的继承

如果想要定义一个类,功能是一个类的扩展,那么就可以使用继承操作。继承的语法是:

class <子类名>(<父类名>):
    <子类内容>

使用继承后,子类会拥有父类的所有类变量和方法。这些类变量和方法可以进行更改。只要重新定义一遍方法就能实现。

在子类中调用父类的方法,可以使用<父类名>.<父类方法>(<参数>)的格式。

class Parent:
    def run(self):
        print("run in parent")

class Child(Parent):
    def run(self):
        Parent.run() #调用父类的方法
        print("run in child")

如果想要在父类的__init__上面扩展属性,也需要调用父类的__init__,被称作初始化父类。

3 实战

在这一节中,你将在一些有趣的程序实例中巩固你的知识。

3.1 CLI和GUI

CLI

CLI指的是命令行用户交互界面(Command line User Interface)。运行python程序时,出现一个黑色的类似于cmd的窗口就是CLI窗口。Python CLI程序中,主要使用print等函数。缺点是难看,不能显示图片,只能显示一些简单的文字。

GUI

GUI指的是图形用户交互界面(Graphical User Interface)。强烈推荐读者编程时使用这种类型。运行Python时,可以出现单个或多个窗口,上面可以绘制图片、文字,接收用户的按键、鼠标事件,比如用户按下按钮,输入一段内容。

3.2 猜数游戏(CLI)

在制作程序时,先分析程序的逻辑,这是非常重要的。这个程序的逻辑大致是这样的:电脑随机生成一个0-9之间的数字,用户有三次机会猜这个数字;每次猜数结束后,询问用户是否再玩一次。完整代码如下:

import random

while True:
    print("猜数游戏现在开始!")
    
    correct = random.randint(0, 9) #生成一个0-9之间的随机数
    
    for count in range(3): #循环执行3次
        guess = input("请输入你的猜测(0-9): ") #等待用户输入
        if guess == str(correct): #因为input获取到字符串,而correct是一个整数,所以要转换一下类型
            print("恭喜你猜对了!")
            break
        else:
            print("很遗憾,猜错了,再猜一次吧!")

    else:
        print("你失败了!正确数字是: %d"%correct)

    askyesno = input("你还要再玩一次吗?(y/n)")
    if askyesno == "y":
        print()
    else:
        break

运行效果:

在代码的开头,导入了random库,里面有一个函数randint,可以返回随机整数。

游戏使用了一个while True循环,我们之前提到过,while循环后面的条件如果是True就执行代码,这是一个无限的循环。因为我们并不知道玩家会玩多少次这个游戏,所以使用无限循环最好。

游戏开始时,打印“猜数游戏现在开始”,然后定义一个correct变量,赋值一个随机整数。

接下来,进行三次循环。input是一个内置函数,它可以获取用户的输入内容,返回输入的字符串。然后是一个条件判断,如果guess和正确的数字是相等的,那么就恭喜玩家猜对了。这里需要注意,类型不同之间进行比较,永远返回False,应该先把类型切换过来。

在这个3次的for循环中,使用了for...else...结构,else中是机会用完时的处理。当玩家猜对时,中途使用break退出了循环,所以else后面的代码不会执行;如果机会用完,循环3次结束,是自然结束的,所以执行else后面的内容。

最后询问玩家是否再玩一次。如果玩家输入y,那么print(),这样的目的是发送一个换行符,和上一次游戏的打印内容分隔开来;如果玩家输入的不是y,那么就break,跳出while True,游戏也随之结束。

这段代码是比较简单,很好理解的。如果你还是没有懂,建议复习一下基础,结合代码一步一步地推进,构想解释器是如何往后运行的。

3.3 txt文字替换工具(CLI)

在这个程序中,你将了解在Python中操作文本文档(*.txt)的办法,并制作一个替换txt中文本的工具。下面是完整的代码:

import os

while True:
    filename = input("请输入你的文件名: ")

    if not os.path.exists(filename): #判断文件是否存在
        print("文件不存在,请重新输入!\n")
        continue #跳出本次循环,返回while True开头

    str_old = input("需要替换的字符: ")
    str_new = input("替换为: ")

    with open(filename, "r") as f: #打开文件并命名为f,r表示读取文件
        file_old = f.read() #返回读取文件的字符串
        file_new = file_old.replace(str_old, str_new)
        
    print("读取: ")
    print(file_old)
    print("替换: ")
    print(file_new)

    with open(filename, "w") as f: #写入文件
        f.write(file_new)

    print("替换完毕!\n")

运行效果:

再次打开name.txt,发现文件被成功替换。

3.4 使用tkinter(GUI)

Python tkinter(GUI编程)模块全解(上)_Python zzy的博客-CSDN博客

猜你喜欢

转载自blog.csdn.net/qq_48979387/article/details/125014945