人生苦短,我学python

提示:本文主要讲解的是python的基础知识,参考的书籍是张健、张良均主编的《Python编程基础》

文章目录


前言

提示:这里可以添加本文要记录的大概内容:

本文是基于Windows系统平台安装的Python3.6.0版本,代码主要是在pycharm上编写。关于Python版本的安装和配置环境变量,请参考张健、张良均主编的《Python编程基础》。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Python基础知识

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

1.1创建应声虫程序

1.1.1输出

  • print函数
    print()函数中若有多个表达式,则表达式之间用逗号隔开,输出格式上每个表达式之间默认有一个空格,语法格式如下
print('hello world')
print('hello','world')
character = 'hello world'
print(character)

运行结果如下:
在这里插入图片描述

1.1.2输入

  • input函数
    input()函数的形参是一个字符串,用于提示用户输入数据。(特别注意的是:input函数的返回值是字符型的***),语法格式如下。
character = input("input your character:")
print(character)
x = input('first:')
y= input('second:')
print(x+y)#输出是没有空格的
character = input("input your character:")
print(character)```

运行结果如下:
在这里插入图片描述

1.2 掌握Python的固定语法

1.2.1 声明Python编码

  • 为python的源文件指定特定的字符编码,需要在文件的首行或者在第二行插入一行特殊的注释行,通常使用的编码声明格式如下。
#-*-coding:utf-8-*-
#coding:utf-8
#coding=utf-8 

  • 在编写Python脚本时,有时还需要注意路径声明(目的是告诉OS调用了该目录下的Python解释器执行文件,一般放在脚本首行),路径声明的格式如下。
#!e:/python/python36  声明路径

1.2.2 加入代码注释

  • 单行注释:通常以井号(#)开头
#这是一个使用#号的单行注释
  • 多行注释
    1.#号注释
#这是一个使用#号的多行注释
#这是一个使用#号的多行注释
#这是一个使用#号的多行注释

2.单引号注释

'''
该多行注释使用的是3个单引号
该多行注释使用的是3个单引号
该多行注释使用的是3个单引号
'''

3.双引号注释

"""
该多行注释使用的是3个双引号
该多行注释使用的是3个双引号
该多行注释使用的是3个双引号
"""

1.2.3 使用多行语句

  • 一条语句多行:语句太长, 使用反斜杠(\)可以实现一条长语句的换行(特别地,[]、{}、()里面的多行语句在换行时是不需要使用反斜杠(\)的***)。
a = 'welcome '
b = 'to '
c = 'HuaXian'
total = a + \
        b + \
        c
print(total)
print("Welcome "
      "to "
      "HuaXian")
  • 一行多条语句:语句太短,使用分号(;)可以对多条语句实现隔离。
a = 'welcome ';b = 'to ';c = 'HuaXian'
print(a+b+c)

1.2.4.缩进代码

Python最具有特色的就是以缩进的方式来标识代码块,不需要使用大括号,代码看起来更加简洁明朗(同一个代码块的语句必须保证相同的缩进空格数,至于缩进的空格数Python并没有硬性要求***)。

1.2.5命名标识符与保留字符

标识符有以下规定:

  • 可以由字母、数字和下划线组成。
  • 不能以数字开头。
  • 以下划线开头的标识符具有特殊的意义:
    (1)以单下划线(foo)开头:不能直接访问的类属性,需通过类提供的接口进行访问,不能用”from xxx import *“导入。
    (2)以双下划线开头(foo)开头:代表类的私有成员。
    (3)以双下划线开头和结尾(如__foo
    )(csdn中打出这个字体就会加黑)的标识符是Python特殊方法专用的标识符,如__init
    _()代表类的构造函数。
  • 标识符字母区分大小写。
  • 标识符禁止使用Python中的保留字。keyword.iskeyword():查看字符是否为保留字;keyword.kwlist():查看所有保留字。
import keyword
print(keyword.iskeyword("chenxiaoda"))  # 得加输出
print(keyword.kwlist)  # 查看python中所有的保留字

1.3 创建字符串变量并提取里面的数值

1.3.1 Python变量

在python中,变量不需要提前声明,但是一旦创建了一个变量,就必须要给该变量赋值(在C,JAVA中,必须提前声明变量)

  • 可以简单理解:变量好比一个标签,指向内存空间的一块特定的地址。创建一个变量时,在机器的内存中,系统会自动给该变量分配一块内存,用于存放变量值,如下图所示。
    在这里插入图片描述
    通过id函数可以具体查看创建变量和变量重新赋值时内存空间的变化过程;len函数可以返回字符串长度
x = 4
print(id(x))  # id():查看变量的地址
strExample = "我是一个字符串"
print(len(strExample))  # len():查看字符串长度
  • 变量名
    变量的命名必须严格遵循标识符的规则。不仅要避免python中的保留字,还要避开具有特殊作用的非保留字(如内置函数名),以免发生一些不必要的错误。
  • 变量值
    变量值就是赋给变量的数据,python中有6个标准的数据类型,分别为:
    数字(Number)
    字符串(String)
    列表(List)
    字典(Dictionary)
    集合(Sets)
  • 变量赋值
    可以把一个变量值赋给一个变量名;也可以将一个值同时赋给多个变量。
a = b = c = 1
print(a, b, c)  # 一个值赋给多个变量
a, b, c = 1, 2, "abc"
print(a, b, c)  # 多个变量同时赋值

1.3.2 相互转化数值型变量

数值型数据类型中文解释(示例)
int整数类型 (10、100、1000)
float浮点型 (1.0,0.11、1e-12)
bool布尔型(True:1、False:0)
complex复数(1+1j、0.123j、1+0j)
print(int(1.56), int(0.123), int(-1.2), int())  # 浮点型转化成整形
print(int(True), int(False))  # 布尔型转化成整形
# print(int(1+23j))   #TypeError: can't convert complex to int:复数没有办法转化
print(bool(1), bool(2), bool(0))  # 整形转化成布尔型         非0的数值转化为布尔型都为True
print(bool(1.0), bool(2.5), bool(0.0))  # 浮点型转化成布尔型   数值0转化为布尔型为False
print(bool(1 + 23j), bool(23j))  # 复数转化成布尔型
# 用bool函数分别对空、空字符、空列表、空元组、空字典(或者集合)进行转化时都为空,如果是非空,结果时True(除去非数值0的情况)
print(bool(), bool(''), bool(""), bool([]), bool({}))

运行结果如下:
在这里插入图片描述

1.3.3 字符型数据的创建与基本操作

字符型数据可以理解成是一种文本。
- 一、标识字符串
1.单引号(’ ‘);2.双引号(" ");3.三引号(’‘’ ‘’')

print('hello world')  # 单引号标识字符串
print("hello world")  # 双引号标识字符串(与单引号功能相同,但不能混合使用)
print('''hello \
world''')  # 三引号标识字符串 \:字符串在下一行继续,而不是开始一个新行

- 二、转义字符

print('What\'s happened', 'and quotes(\\)')  # 反斜杠\:还可以进行字符转义 (单引号中不能直接出现单引号,输出\也需要加\:即\\ )
print("What's happened", "and Double quotes(\")")  # (双引号中可以直接出现单引号,但不可以直接出现双引号,也需要反斜杠\)
print('D:\name\python')
print(r'D:\name\python') #还可以给字符串前加r后者R来指定原始字符串。

运行结果如下:
在这里插入图片描述
- 三、字符串索引

类型实列
字符串P Y T H O N
索引0 1 2 3 4 5 6
负索引-6 -5 -4 -3 -2 -1

- 四、字符串基本操作
(1)提取指定位置的字符( [x] )

word = 'python'  # python中的字符串数组没有固定的约束格式
print(word[1], word[0], word[-1])  # 正约束:第一个字母从0开始,往右查    负约束:从1开始,从左查

运行结果为:
在这里插入图片描述
(2)字符串切片 ( [x:y] )
特别的:
第2个索引越界:将将被切片字符串实际长度替代;
第1个索引越界:返回空字符串 第1个索引值大于第2个索引值:返回空字符串

print(word[0:3], word[:3], word[4:])  # 截取第1~3个字符、截取第1~3个字符、截取第5~最后一个字符

运行结果为:
在这里插入图片描述
(3)字符串拼接

print('python is' + 3 * ' good', '  python is ''good')  # 加号拼接字符串  相邻字符串自然拼接
sentence = 'Life is short,you need something.'
print(sentence[:23] + 'python')  # 字符串的修改:只能找到要修改的索引位置 然后加修改值(目前的知识)

运行结果为:
在这里插入图片描述

1.4 Python常用操作运算符

1.4.1 算数运算符

运算符描述(示例)
+加(10+20,结果为30)
-减(20-10,结果为10)
*乘(10*20,结果为200)
/除:不管商为整数还是浮点数,结果始终为浮点数(20/10,结果为2.0)
%取模(23%10,结果为3)
**幂(2**3,结果为8)
//取整除:返回商的整数部分(23//10,结果为2)

python提供了type(x)函数,可以来查看x的数据类型。

print(2 / 1, type(2 / 1))  # python中的/:不管商为整数还是浮点数,结果始终为浮点数
print(2 // 1, type(2 // 1))  # python中的//:取整除,即返回商的整数部分

运行结果为;
在这里插入图片描述

1.4.2 比较运算符

运算符描述(示例)
==等于:比较两个对象是否相等(1==2,返回False)
!=不等于:比较两个对象是否不相等(1!=2,返回True)
>大于:返回x是否大于y(1>2,返回False)
<小于:返回x是否小雨y(1<2,返回True)
>=大于等于:返回x是否大于等于y(1>=2,返回False)
<=小于等于:返回x是否小于等于y(1<=2,返回True)

Python还提供了两个可以进行字符与编码转换的函数。

  • ord()函数:将ASCLL字转换为对应的数值。
  • chr()函数:将数值转换成对应的ASCLL字符。
print(1 == 1, 1 != 2)  # 比较运算符
print('a' == 'b', 'a' != 'b');
print('a' < 'b', 'a' > 'b')
print(ord('a'), ord('b'))  # ord():将ASCLL字符转换为对应的数值
print(chr(97), chr(98))  # chr():将数值转换为对应的ASCLL字符
print('#' < '$')  # ASCLL字符的比较就是对应的数值大小的比较

运行结果为:
在这里插入图片描述

1.4.3 赋值运算符

运算符描述(示例)
=简单赋值(c=a+b等效于将a+b的运算结果赋值给c)
+=加法赋值(a+=b等效于a=a+b)
-=减法赋值(a-=b等效于a=a-b)
*=乘法赋值(a*=b等效于a=a*b)
/=除法赋值(a/=b等效于a=a/b )
%=取模赋值(a%=b等效于a=a%b)
**=幂赋值(a**=b等效于a=a**b)
//=整除赋值(a//=b等效于a=a//b)
# 赋值运算与c,java语言类似:= 、+=、-=、*=、/=、%=、**=、//=
a = 1 + 2;
print(a)
print("a: ", a);
a += 4;
print("a += 4 特殊赋值运算后,a=: ", a);

运行结果为:
在这里插入图片描述

1.4.4按位运算符

通常,数字是使用十进制的,按位运算符会自动将输入的十进制数转为二进制数,在进行相应的运算。

  • a = 60 = 0011 1100
  • b = 13 = 0000 1101
运算符描述(示例)
&位与运算:对应的两个值为1,则为1,否则则为0(a&b= 000 1100 =12)
l位或运算:对应的两个值只要有一个为1,则为1(alb= 0011 1101=61)
^异或运算:对应的两个值相异,则为1(a^b= 0011 0001 =49)
~取反运算:对应的每个值取反:1变成0;0变成1((若开头为0:是正数,正数的补码是他本身;若开头为1:是负数,负数的补码需要减1取反)~a=1100 0011,:减1:1100 0010、符号位不变再取反:1011 1101= -61)
<<左移运算:对应的值全部左移若干位,高位丢弃,低位补0(a<<2=1111 0000=240)
>>右移运算:对应的值左移若干位(a>>2=0000 1111)
# 位运算  二进制位数1111 1111 :128|64|32|16 8|4|2|1
a = 60  # a对应的二进制:a =  0011 1100
b = 13  # b对应的二进制: b = 0000 1101
print(a & b)  # 按位与运算 &:按位运算,都为1则为1;否则为0       a&b=0000 1100=12
print(a | b)  # 按位或运算 |: 按位运算,只要有一个为1则为1,否则为0  a|b=0011 1101=61
print(a ^ b)  # 按位异或运算 ^: 按位运算,当两对应的二进制位相异时为1,否则为0 a^b=0011 0001=49
print(~a)  # 按位取反运算符~: 对应的每个二进制位取反,1变为0,0变为1 ~a=1100 0011=128+64+2+1=195
print(a << 2)  # 左移运算符<<: 运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0 a<<2 = 1111 0000=
print(a >> 2)  # 右移运算符>>:运算数的各二进位全部右移若干位,由“>>”右边的数指定移动的位数 a>>2 =0000 1111=15

运行结果如下:

1.4.5逻辑运算符

  • a=11,b=22
运算符描述(示例)
and布尔“与”(x and y):若x为False,则为False;否则返回y的计算值。(a and b,返回22)
or布尔“或”(x or y):若x是Ture,则为True;否则返回y的计算值。(a or b,返回11)
not布尔“非”(not(x)):若x为Ture,则为False;若x为False,则为True。(not (a and b),返回False
# 逻辑运算符 and、or、not     (不是很懂)
a = 11;
b = 12;
print('a=11,b=22')
print('a and b =', a and b)  # (布尔“与”)x and y,如果x为False,返回False;否则它返回y的计算值
print('a or b =', a or b)  # (布尔”或“)x or y,如果x是True,他返回True;否则它返回y的计算值
print('not(a and b) = ', not (a and b))  # (布尔”非“)not(x),如果x为True,返回False,如果x为False,它返回true
print(True & True, True and True)  # 按位&,逻辑 and
print(True & False, True and False)
print(True | False, True or False)  # 按位|、逻辑or
print(False | False, False or False)

运行结果如下:
在这里插入图片描述

1.4.6 成员运算符

成员运算符包括:字符串、列表或元组。其作用是判断某指定值是否存在于某一序列中。

运算符描述(示例)
in若在指定的序列中找到值,返回True,否则返回False(x in y:x在y序列中,返回True)
not in如果在指定的序列中没有找到值,返回True,否则返回False (x not y,x不在y序列中,返回True)
List = [1, 2, 3, 0, [4,5], 'Python3']
print(List)
print(1 in List)
print([1] in List)
print(3 in List)
#print([4,5] in list)  #这句程序有点问题,会出错 TypeError: argument of type 'type' is not iterable
#print('Python' in list) #这句程序有点问题
#print('Python3' in list) #这句程序有点问题

运行结果如下:
在这里插入图片描述

1.4.7 身份运算符

身份运算符用于比较两个对象的内存地址。

运算符描述(示例)
is用于判断两个标识符是不是引用自一个对象(x is y,如果id(x)等于id(y),返回结果1)
is not用于判断两个标识符是不是引用自不同对象(x is not y,如果id(x)不等于id(y),返回1)
a = 11; b = 11; print('a=11,b=11')
print(a is b); print(a is not b)
print(id(a),id(b)) #查看id地址

运行结果如下:
在这里插入图片描述

1.4 Python常用操作运算符

在python的应用中、通常运算的形式是表达式。表达式由运算符和操作数组成。

运算符描述
**指数(最高运算符)
~ + -按位翻转、一元加号和减号
* / % //乘、除、取模和取整除
+ -加法减法
>> <<右移、左移运算符
&按位与运算符
^按位或运算符
<= < > >=比较运算符
<> == !=等于运算符
= %= /= //= -= += *= **=赋值运算符
is is not身份运算符
in not in成员运算符
not or and逻辑运算符

二、python数据结构

python的数据结构主要分为以下两个部分

  • 认识序列(如列表和元组)、映射(如字典)及集合3种基本的数据结构类型。
  • 掌握可变数据类型和不可变数据类型的区别。

2.1创建列表(list)并进行增删改查操作

2.1.1列表的概念与特性

  • 列表(list)是Python对象作为其元素并按顺序排列构成的有序集合,列表中的每个元素都有各自的位置编号,称为索引。
  • 列表当中的元素可以是各种类型的对象,无论是数字、字符串、元组、字典 ,还是列表类型本身,都可以作为列表当中的一个元素。
  • 此外,列表当中的元素可以重复出现。列表是可变数据类型,因此可以对列表对象自身进行内容修改(增、删、改)。

2.1.2创建列表

  • 使用方括号[]创建
#创建一个列表(list)并进行增删改查操作
mylist=[1,2.0,['three','four',5],6.5,True]  #创建混合数据类型的嵌套列表
print(mylist)
empty_list = []  #创建一个空列表
print(empty_list)

运行结果如下:
在这里插入图片描述

  • 使用list函数创建
    list函数:将传入的数据结构对象转换成列表类型。(使用时可以用圆括号或方括号吧元素按顺序包括起来,元素之间可以用逗号隔开);如果字符串传入list函数,list函数会将字符串中的每个字符元素作为一个列表元素,然后将这些元素放入一个列表。
mylist1 = list((1,2.0,['three','four',5],6.5,True))  #list():将传入的数据结构对象转换为列表类型   注意:得用圆括号和方括号把元素括起来
print(mylist1)
print(type(mylist1))    #type():查看对象类型
mylist2 = list(['one','two','three'])    #向函数list传入一个列表对象
print(mylist2)
mylist3 = list('one')    #向函数list传入一个字符串
print(mylist3)

运行结果如下:
在这里插入图片描述

2.1.3列表的基本操作

  • 序列类型的数据结构都可以通过索引和切片操作对元素进行提取。
  • 字符串、列表和元组都属于序列类型。
  • 列表元素的提取方法有两种:索引访问提取和列表切片操作提取。
    1.列表索引访问提取—sequence_name[index]
mylist4 = ['Sunday','Monday','Tuesday','Wednesday','Thrusday','Friday']
print(mylist4[1])     #正索引:从0开始(从左到右)
print(mylist4[-3])    #负索引:从-1开始(从右到左)

运行结果如下:
在这里插入图片描述
2.列表的切片操作提取—sequence_name[start:end:step]

  • start(起始索引):默认从0开始 (闭区间)
  • end(终止索引):切片操作不包含终止元素。(开区间)
mylist5 = [10,20,30,40,50,60,70,80,90,100]    #0,1,2,3,,,,,,,
print(mylist5[2:7])  #提取从第3~8个元素之间的元素   左闭右开
print(mylist5[1:9:2])  #提取从第1~10元素之间的元素,步长为2
print(mylist5[-2:-8:-2]) #提取倒数第1~8个元素之间的元素,步长为2

运行结果如下:
在这里插入图片描述

  • 若省略起始索引,切片操作会默认使用开头或结尾的索引(0或-1)
  • 若省略终止索引,切片操作会安提取方向搜索到序列一端的最后一个元素,包含那一端的最后一个元素。(开区间)
  • 若两者同时省略,切边操作会对全体元素搜索提取(从哪端开始视具体方向而定)。
  • list_name[::-1]可以实现列表反转。
#省略起始索引
print(mylist5[:-7:-2])   #提取从结尾向左到倒数第7个元素前的所有元素,步长为2
#省略终止索引
print(mylist5[6:])    #提取从第7个元素到列表右端最后一个元素之间的所有元素
#同时省略起始和终止索引
print(mylist5[::2])   #提取所有元素,步长为2
print(mylist5[::-1])   #####列表反转

运行结果为:
在这里插入图片描述

2.1.4列表常用函数和方法

  1. 添加列表元素
    (1)append:向append传入需要添加到列表对象的一个元素,则该元素会被追加到列表尾部。(append一次只能追加一个元素
##添加列表元素   append():此函数一次只能追加一个元素
month = ['January','February','March','April','May','June']
month.append('Jury')
print(month)

运行结果如下:
在这里插入图片描述
(2)extend:使用extend能够将另一个列表添加到列表末尾,相当于两个列表进行拼接。(extend可以追加多个元素,得到的效果与使用自增运算(+=)相同

#添加多个元素 extend():能够将另一个列表添加到列表末尾
month_copy = month.copy() #创建一个元素副本,在修改列表元素部分解释
print(month_copy)
others = ['Augest','September','Novermber','December']
month.extend(others)
print(month)
month_copy+=others
print(month_copy)  #extnd()与+=的效果一样

运行结果如下:
在这里插入图片描述
(3)insert:使用insert也能够向列表中添加一个元素,若插入位置超出列表尾端,则会插入列表最后,这相当于append的效果。(特别的,insert可以在指定位置添加

#insert():向列表中添加一个元素
month.insert(9,'October') #特别的::insert可以在指定位置添加,就想在列表某个位置插入一个元素一样。
print(month)
month.insert(20,'None') #插入位置超出列表尾端,则会插入列表最后,相当于append的效果
print(month)

运行结果如下:

['January', 'February', 'March', 'April', 'May', 'June', 'Jury', 'Augest', 'September', 'October', 'Novermber', 'December']
['January', 'February', 'March', 'April', 'May', 'June', 'Jury', 'Augest', 'September', 'October', 'Novermber', 'December', 'None']
  1. 删除元素
    (1)使用del语句删除列表元素:实质上del语句是赋值语句(=)的逆过程,即将一个对象与它的变量名进行分离操作。
#del:实质是赋值语句(=)的逆过程
month_copy = month.copy()
del month_copy[-1]
print(month_copy)

运行结果如下:
在这里插入图片描述
(2)使用pop语句删除列表元素:利用元素位置对元素进行删除操作。将元素传入pop语句中,将会获取该元素,并将其在列表中删除,相当于把列表中的元素抽离出来。(若不指定元素位置,默认使用索引-1)

#pop():利用元素位置可以对元素进行删除操作    pop语句将默认使用索引-1
month_copy = month.copy()
print(month_copy.pop(3))  #获取并删除第4个元素
del_element = month_copy.pop() #将最后一个元素赋值给一个变量并在副本中删除
print(del_element)  #查看删除元素
print(month_copy)   #查看副本

运行结果如下:
在这里插入图片描述
(3)使用remove语句删除列表元素:将指定元素传入remove语句。则列表中第一次出现的该元素会被删除。

#remove():可以将指定元素进行删除   列表中第一个出现的该元素会被删除
month.remove('None')
print(month)

运行结果如下:
在这里插入图片描述

  1. 修改列表元素

最简单的方法就是提取该元素并进行赋值操作。

month[0]='一月'
print(month)

运行结果如下;
在这里插入图片描述

为什么要创建一个副本?
对于可变类型的数据结构,直接在对象上进行元素的增删改查等操作,处理结果将直接影响对象本身。**

#为什么要创建副本
a=[1,2,3,4]
b=a
a.append(5)
print(a)
print(b)

运行结果如下:
在这里插入图片描述

copy方法作用
如果不希望修改操作直接作用于列表对象本身,可以使用copy函数创建一个完全一样的“副本”,实质上,这个“副本”已经是另一个列表对象,只是内容上与原列表对象完全相同而已
除了copy方法外 ,使用切片操作和list函数 也能达到同样的效果。

#copy方法操作
a = [10,20,30,40,50]
b=a.copy()  #使用copy方法创建副本
c=a[:]     #使用切片操作创建副本
d=list(a)  #使用list函数创建副本
print(id(a),id(b),id(c),id(d))
b[2]='three'
print(b);print(a);print(c);print(d)

运行结果如下:
在这里插入图片描述

  1. 查询列表元素位置
  • 可以利用列表方法index,来查询指定元素在列表中第一次出现的位置索引。
  • 也可以使用**in函数,**来判断列表是否包含某个元素。
#index():查询指定元素在列表中第一次出现的位置索引
letter = ['A','B','C','D','A','D','C','B']
print(letter.index('C')) #若查询的字符不在列表中,则会报错
print('A' in letter)

运行结果如下:
在这里插入图片描述
5. 其他常用操作

列表方法和函数说明
list.count记录某个元素在列表中出现的次数
list.sort对列表中的元素进行排序(默认升序);reverse=True:降序。结果会改变原列表内容
sorted与list。sort作用一样。但不改变原列表内容
list.reverse反转列表中的各元素
len获得列表长度,即元素个数
+将两个列表合并成一个列表
*重复合并同一个列表多次
letter = ['A','B','C','D','A','D','C','B']
#count():记录某个元素在列表中出现的次数
print(letter.count('A'))
#sort():对列表中的元素进行排数,默认为升序,sort(reverse = True):降序排序
#sorted():与sort()的作用一样,但不改变列表内容
sorted(letter);print(letter)
letter.sort();print(letter)
letter.sort(reverse=True);print(letter)
#reverse:反转列表中的元素
season = ['sprint','summer','autumn','winter']
season.reverse()
print(season)
#len: 获取列表的长度,即元素个数
print(len(season))
#+:将两个列表合并成一个列表  *:重复合并同一个列表多次
print([1,2,3]+[4,5,6])
print([11,22,33]*3)

运行结果如下:
在这里插入图片描述

2.2将列表为元组(tuple)并进行取值操作

2.2.1区分元组和列表

  • 相同点:元组和列表都是有序元素的组合。
  • 不同点:元组是不可变的。 元组使用圆括号创建元素,
    列表是可变的,列表使用方括号。
  • 元组一旦创建后就不能修改,即不能对元组对象中的元素进行增、删、改等操作。

2.2.2创建元组

  1. 使用圆括号()创建
  • 使用圆括号将有序元素括起来,并用逗号隔开,可以创建元组。
  • 逗号是必须存在的,即使元组当中只有一个元素,后面也需要有逗号。
  • 定于元组的关键是都逗号,圆括号可以省略。
# 使用圆括号()创建元组           将列表转换为元组
mytuple1 = (1, 2.4, ('three', 'four'), [True, 5], False)
print(mytuple1)
mytuple2 = 2, True, 'five', 3.5
print(mytuple2)

运行结果为:
在这里插入图片描述

  1. 使用tuple函数创建
    tuple函数能够将其他数据结构对象转换为元组类型。(在tuple函数中传入元组需要加上与圆括号)
# 使用tuple函数创建              将列表转换为元组
mytuple1 = tuple([1, 2.4, ('three', 'four'), [True, 5], False])
print(mytuple1)
mytuple2 = tuple((2, True, 'five', 3.5))
print(mytuple2)
empty_list = tuple()
print(empty_list)  # 注意:元组使用圆括号来包括元素,,,,列表使用方括号

运行结果如下:
在这里插入图片描述

2.2.3元组常用函数和方法

  1. 元组元素提取(跟列表类似)
    (1)元组索引访问提取
    (2)元组切片操作提取
# 元组索引访问提取
mytuple3 = ('china', 'Americal', 'England', 'France')
print(mytuple3[0])  # 若传入的索引超出元组索引范围,则结果会返回一个错误
# 元组切片操作
print(mytuple3[-2::-1])  # 提取元组倒数第2个元素到左端之间的所有元素
print(mytuple3[1:10])  # 超出元素索引范围

运行结果如下:
在这里插入图片描述

  1. 元组解包
  • 含义:将元组中的各个元素赋值给多个不同变量的操作。
  • 使用格式:a,b,c,d=tuple
  • 由于创建元组时可以省略括号,因此元组解包可以看成时多条赋值语句的集合。
### 元组解包
A, B, C, D = mytuple3  # 将元组中的各元素分别赋值给对应的变量
print(A, B, C)
x, y, z = 1, True, 'one'  # 利用元组解包进行多个变量赋值
print(x, y, z)  # z输出的是one,而不是‘one'

运行结果如下:
在这里插入图片描述

  1. 元组常用方法和函数
元组方法和函数说明
tuple.count记录某个元素在元组中出现的次数
tuple.index获取元素在元组当中第1次出现的位置索引
sorted创建对元素进行排序后的列表(不仅仅是元组的排序)
len获取元组长度,即元组元素个数
+将两个元组合并为一个元组
*重复合并同一个元组为一个更长的元组
# 使用count函数进行元素计数
mytuple4 = ('A', 'D', 'C', 'A', 'C', 'B', 'B', 'A')
print(mytuple4.count('B'))
# 使用index函数获取元素在元组中第一次出现的位置索引
mytuple4.index('C')
# 使用sorted函数对元组元素进行排序
print(sorted(mytuple4))
# 使用len函数获取元组长度
print(len(mytuple4))
# +:合并两个元组,*:重复合并元组
print((1, 2, 3) + (4, 5, 6))
print((10, 20, 30, 40) * 3)

运行结果如下:
在这里插入图片描述

2.2.3任务实现

步骤如下:

  1. 使用方括号创建列表对象[‘pen’,‘paper’,10,False,2.5]。
  2. 使用type函数查看此时变量的数据类型。
  3. 使用tuple函数将变量转换成元组类型。
  4. 再次使用type函数确定是否完成转换。
  5. 使用元组方法index分别查询元素False的位置索引
  6. 提取元素False并赋值。
# -*-coding:utf-8-*-
task_tuple = ['pen', 'paper', 10, False, 2.5]  # 创建一个列表
print(type(task_tuple))  # 查看对象的数据类型
task_tuple = tuple(task_tuple)  # 转换列表对象为元组类型
print(type(task_tuple))  # 查看对象的数据类型
Index = task_tuple.index(False)  # 查询元素位置索引
bool = task_tuple[Index]  # 提取元组元素
print(bool)  # 查看提取元素

运行结果如下:
在这里插入图片描述

2.3创建字典(dict)并进行增删改查等操作

2.3.1字典的概念与特性

  • 字典是属于映射类型的数据结构。字典中包含任意类型的数据结构作为元素,并且各元素都有与之对应且唯一的键。
  • 字典与列表、元组的区别:字典主要通过键来访问对应的元素;后两者则使用索引来对应元素。
  • 字典的元素都拥有各自的键,并且每个键值对都可以看成是一个映射对应关系。
  • 字典没有严格的顺序关系字典是可变的,可以对其元素进行增删改查等操作。

字典的键与值:
1.字典的每个元素都有对应的键,元素就是键所对应的值。
2.键与值共同构成一个映射关系:键—值(key:value),称为键值对。字典中会包含多个键值对。
3.键必须使用不可变数据类型的对象,如数字、字符串、元组等。并且键不允许重复。
4.值可以是任意类型,并且在字典中可以重复。

2.3.1创建字典

对于重复创建的键,采用最后出现的对应值

  1. 使用花括号{}创建
mydict1 = {'myint': 1, 'myfloat': 3.14, 'mystr': 'name',
           'myint': 100, 'mytuple': (1, 2, 3),'mydict': {}}  # 对于重复的键,采用最后出现的对应值
print(mydict1)
empty_dict = {}
print(empty_dict)

运行结果如下:
在这里插入图片描述

  1. 使用dict函数创建
  • python中dict函数的作用实质上主要是将包含双值子序列的序列对象装换为字典类型,其中双值子序列中的第1个元素作为字典的键,第2个元素作为对应的值。

双值子序列:实际上就是只包含两个元素的序列

  • 除了转换,还可以直接向dict函数传入键和值进行创建,其中必须通过“=”将键和值隔开。(这种创建方式不允许键重复,否返回错误)
mydict1 = dict([('myint', 1), ('myfloat', 3.14), ('mystr', 'name'),
            ('myint', 100), ('mytuple', (1, 2, 3)), ('mydict', {})])
print(mydict1)
mydict2 = dict(zero=0, one=1, two=2)
print(mydict2)
empty_dict = dict()
print(empty_dict)

运行结果如下:
在这里插入图片描述

2.3.2提取字典元素

  • 与序列元素不同,字典作为映射类型数据结构,并没有索引的概念,也没有切片操作等处理方法。
  • 字典的提取主要是利用这种映射关系来实现。具体格式:dict[key]:字典[键](传入的键必须存在在字典中
mydict3 = {'spring': (3, 4, 5), 'summer': (6, 7, 8), 'autumn': (9, 10, 11), 'winter':'冬天'}
print(mydict3['autumn'])
print(mydict3['winter'])

运行结果如下:
在这里插入图片描述
为了避免传入键不存在而导致出错,python提供了两种处理方法:

  1. 提取前使用in语句测试键是否存在
print('Winter' in mydict3)
运行结果为:False
  1. 使用字典方法get

get能够灵活第处理元素的提取:

  • 若之传入键,当键存在于字典中时,函数会返回对应的值;当键不存在时,函数会返回None
  • 传入键,同时也传入代替值,当键存在与字典中时,返回对应的值(而不是替代值);当键不存在时,返回这个传入的代替值,而不是None。
print(mydict3.get('summer'))
print(mydict3.get('Winter'))
print(mydict3.get('winter', 'Not in this dict'))
print(mydict3.get('Winter', 'Not in this dict'))

运行结果如下:
在这里插入图片描述

2.3.3字典常用函数和方法

在Python的内置数据结构中,字典和列表时最为灵活的数据类型。他们都是可变的数据结构:都能进行增、删、改、查等操作。

  1. 添加字典元素。
    (1).使用键访问赋值添加(添加一个元素),利用字典元素提取方法传入一个新的键,并对这个新键进行赋值操作,格式:dict_name[newkey]=new_value。(但是这赋值操作可能会因为键存在而出现错误)
country = dict(China = 'Beijing',
               America = 'Washington',
               Britain = 'London',
               French = 'Paris',
               Canada = 'Ottawa')
country_copy = country.copy()
country_copy['Russian'] = 'Moscow'
print(country_copy)

运行结果如下:

{'China': 'Beijing', 'America': 'Washington', 'Britain': 'London', 'French': 'Paris', 'Canada': 'Ottawa', 'Russian': 'Moscow'}

(1).update:将两个字典中的键值对进行合并,传入字典中的键值对会复制添加到调用函数的字典对象中。若两个字典中存在相同键,传入字典中的键所对应的值会替换掉函数字典对象中的原有值,实现值更新的效果。

others = dict(Australia = 'Canberra',
              Japan = 'tokyo',
              Canada = 'OTTAWA')
country.update(others)
print(country)

运行结果如下:

{'China': 'Beijing', 'America': 'Washington', 'Britain': 'London', 'French': 'Paris', 'Canada': 'OTTAWA', 'Australia': 'Canberra', 'Japan': 'tokyo'}
  1. 删除字典元素
    (1). 使用del语句删除字典元素:del dict_name[key]。
    (2). 使用pop语句删除字典元素:向pop语句传入需要删除的键,则会返回对应的值,并在字典当中移除相应的键值对
    (3). 使用clear删除字典元素:clear会删除字典中的所有元素,最终会返回一个空字典。
# del
country_copy = country.copy()
del country_copy['Canada']
print(country_copy)
# pop
old_value = country.pop('Canada')
print(old_value)
print(country)
# clear
country_copy=country.copy()
country_copy.clear()
print(country_copy)

运行结果如下:

{'China': 'Beijing', 'America': 'Washington', 'Britain': 'London', 'French': 'Paris', 'Australia': 'Canberra', 'Japan': 'tokyo'}
OTTAWA
{'China': 'Beijing', 'America': 'Washington', 'Britain': 'London', 'French': 'Paris', 'Australia': 'Canberra', 'Japan': 'tokyo'}
{}
  1. 修改字典元素
    可以使用赋值操作来修改字典中的某个元素,格式为:dict_name[key]=new_value。赋值操作在字典当中使用是十分灵活,无论键是否存在在字典中,所赋予的新值都会覆盖或添加到字典当中,这极大地方便了对字典对象的处理。
# 修改字典元素
country['Japan'] = 'Tokyo'  # 键值已有,覆盖新值
print(country)
country['Henan'] = 'Huaxian'  # 键值没有,添加新值
print(country)

运行结果如下:

{'China': 'Beijing', 'America': 'Washington', 'Britain': 'London', 'French': 'Paris', 'Australia': 'Canberra', 'Japan': 'Tokyo'}
{'China': 'Beijing', 'America': 'Washington', 'Britain': 'London', 'French': 'Paris', 'Australia': 'Canberra', 'Japan': 'Tokyo', 'Henan': 'Huaxian'}

  1. 查询和获取字典元素信息

查询某个键是否在字典中,也可以使用之前讲的in进行判断。

字典方法中有3种方式用于提取键值信息(返回的结果均是各自的迭代形式、可以通过list将返回结果转换为列表类型,同时配合in的使用,半段值和键值对是否存在与字典中):

  1. keys:用于获取字典中的所有键。
  2. values:用于获取字典中的所有值。
  3. items:得到字典中的所有键值对。
# 判断键知否存在于字典当中
print('Canada' in country)
# 获取所有键
all_keys = country.keys()
print(all_keys)
# 判断值是否存在于字典当中
all_values = country.values()
print(all_values)
print(list(all_values))
print('Beijing' in all_values)
# 判断键值对是否存在于字典当中
all_items = country.items()
print(all_items)
print(('America', 'Washington') in all_items)
print(list(all_items))

运行结果为:

False
dict_keys(['China', 'America', 'Britain', 'French', 'Australia', 'Japan', 'Henan'])
dict_values(['Beijing', 'Washington', 'London', 'Paris', 'Canberra', 'Tokyo', 'Huaxian'])
['Beijing', 'Washington', 'London', 'Paris', 'Canberra', 'Tokyo', 'Huaxian']
True
dict_items([('China', 'Beijing'), ('America', 'Washington'), ('Britain', 'London'), ('French', 'Paris'), ('Australia', 'Canberra'), ('Japan', 'Tokyo'), ('Henan', 'Huaxian')])
True
[('China', 'Beijing'), ('America', 'Washington'), ('Britain', 'London'), ('French', 'Paris'), ('Australia', 'Canberra'), ('Japan', 'Tokyo'), ('Henan', 'Huaxian')]

可以利用值查询键
因为提取完的全体键和值的索引正好是一一对应,构成原字典中的键值对

# 提取字典中值为True所对应的值
test = {'A': 100, 'B': 300, 'C': True, 'D': 'Python'}
print(test)
keys = list(test.keys())
values = list(test.values())
print(keys); print(values)
print(keys[values.index(True)])  # 先查询True对应的索引值,因为一一对应,然后按其索引,可提取对应的键

运行结果为;
在这里插入图片描述

2.3.4任务实现

步骤如下:

  1. 使用花括号{}创建某血汗俄国各科成绩组成的字典对象,并赋值给变量。
  2. 使用键访问赋值方式向字典增添键值对{‘History’:88}。
  3. 使用del语句删除键“Physics”。
  4. 利用键“Chinese”访问对应元素,并使用round函数进行四舍五入后取整。
  5. 将取整结果进行赋值来覆盖字典中键“Chinese”的对应值。
  6. 直接使用“Math“查询对应值。
    代码如下:
# -*-coding:utf-8-*-
score = {'Math': 96, 'English': 86, 'Chinese':95.5,
         'Biology': 86, 'Physics': None}
score['History'] = 88
del score['Physics']
new_value = round(score['Chinese'])
score['Chinese'] = new_value
print(score['Math'])
print(score)

运行结果如下:
在这里插入图片描述

2.4将两个列表转换为集合(set)并进行集合运算

2.4.1集合的概念与特性

  • 概念:将各不相同的不可变数据对象无序地集中起来的容器,就像是将值抽离,仅存在键的字典。
  • 特性集合中的元素都是不可重复的,并且是属于不可变类型,元素之间没有排列顺序
  • 集合是集合类型的数据结构,既不是序列类型,也不是映射类型。

2.4.2创建集合

集合类型数据结构包括可变集合不可变集合

  1. 可变集合
  • 可以进行元素的增、删等处理,处理结果直接作用在对象上。
  • 传入的元素对象必须是不可变的(不能传入列表、字典等)
  • set函数能够将数据结构对象转换为可变集类型。
  • 在创建集合时,不用担心传入的元素食肉重复,结果会将重复元素删除。
myset1 = {'A', 'B', '1', '2', '数学', 'A', '数学'}
print(myset1)
myset2 = set([2, 3, False, 2.5, 'one', 2, 'one'])
print(myset2)
empty_set = set()
print(empty_set)
print(type(empty_set))

运行结果如下;
在这里插入图片描述

  1. 不可变集合
  • 不可变集合不能对其中的元素进行修改处理。
  • 使用frozenset函数创建不可变集合。
  • 与可变集合一样,其传入元素必须为不可变数据类型。
#  创建不可变集合
myset3 = frozenset([2, 3, 2, 'one', frozenset([1, 2]), True])
print(myset3)
empty_frozenset = frozenset()
print(empty_frozenset)
prin(type(empty_frozenset))

运行结果如下;
在这里插入图片描述

2.4.2集合运算

  1. 并集:A|B={x|x属于A或y属于B}
  2. 交集: A&B={x|x属于A且x属于B}
  3. 差集:A - B={x|x属于A,但x不属于B}
  4. 异或:(A|B)-(A%B)={x|x属于A或属于B,但不同时属于A和B的元素所组成的集合}
A = {'足球', '游泳', '羽毛球', '乒乓球'}
B = {'篮球', '乒乓球', '羽毛球', '排球'}
print('A=', A, '\nB=', B)
print('A | B = ', A | B)
print(A.union(B))  # 使用集合方法union函数获取并集
print('A & B=', A & B)
print(A.intersection(B))  # 使用集合方法intersection函数获取交集
print('A - B=', A - B)
print(A.difference(B))  # 使用集合方法difference函数获取差集
print('A ^ B=', A ^ B)
print(A.symmetric_difference(B))  # 使用集合方法symmetric_difference函数获取异或集合
**

运行结果如下:
在这里插入图片描述
5. 集合关系常用函数和符号

集合关系常用函数和符号函数说明
<=或issubset()判断一个集合是否为另一个集合的子集,如过是,则集合A中所有元素都是集合B中的元素
<判断一个集合是否为另一个集合的真子集。如果是,则集合B中除了包含集合A中的所有元素,还包括A中没有的其他元素
>=或issuperset()判断一个集合是否为另一个集合的超集。如果是,则集合A包含了B中所有元素
判断一个集合是否为另一个集合的真超集。如果是,则集合B中除了包含集合A中的所有元素,还包括B中没有的其他元素
# 关于集合,子集,真子集,超集,真超集的运算
C = {'足球', '乒乓球', '游泳'}
print('A=', A, '\nB=', B, '\nC=', C)
print("C是否为A的子集:", C <= A)
print(C.issubset(A))
print('C是否为A的真子集:', C < A, '\nA是否为A的真子集:\n', A < A)
print("C是否为A的超集:", A >= C)
print(A.issuperset(C))
print('C是否为A的真超集:', C < A, '\nC是否为C的真超集:', A < A)

运行结果如下:
在这里插入图片描述

2.4.3可变集合的常用函数和方法

set.add向可变集合增添一个元素。
set.update向可变集合添加其他集合的元素,即合并两个集合
set.pop删除可变集合中的一个元素,当集合对象是空集时,则返回错误。
set.remove删除可变集合中指定的一个元素
set.clear清空可变集合中的所有元素,返回空集
in查询元素是否存在于集合当中
len获取集合当中元素的个数
set.copy复制可变集合的内容并创建一个副本对象
# 可变集合的常见操作
myset4 = {'red', 'green', 'blue', 'yellow'}
myset4_copy = myset4.copy()
others = {'black', 'white'}
myset4.add('orange')
myset4.update(others)
print(myset4)
print(myset4.pop())
print(myset4)
myset4.remove('yellow')
myset4_copy.clear()
print(myset4_copy)
print('green' in myset4)
print(len(myset4))

运行结果如下:
在这里插入图片描述

2.4.4 任务实现

步骤如下:

  1. 使用方括号创建列表[‘apple’, ‘pear’, ‘watermelon’, ‘peach’],并赋值给变量set1。
  2. 使用list函数创建列表[‘pear’, ‘banana’, ‘orange’, ‘peach’, ‘grape’],并赋值给set2。
  3. 使用set函数将创建的各个列表对象分别转换为可变集合类型。
  4. 使用type函数查看对象转换后的数据类型。
  5. 使用符号’|‘求出两个集合的并集。
  6. 使用符号’$‘求出两个集合的交集。
  7. 使用符号’-‘求出两集合的差集set1-set2。
  8. 使用differentce函数求出差集set2-set1。
    代码如下:
# -*-coding:utf-8-*-
set1 = ['apple', 'pear', 'watermelon', 'peach']
set2 = list(('pear', 'banana', 'orange', 'peach', 'grape'))
set1 = set(set1)
set2 = set(set2)
print(type(set1))
print(type(set1))
print(set1)
print(set2)
print(set1 | set2)
print(set1 & set2)
print(set1 - set2)
print(set2.difference(set1))

运行结果如下:
在这里插入图片描述

三、程序流程控制语句

3.1实现考试成绩等级划分

  • 任务描述:
    运用python流程控制语句的if语句和else语句编写程序,实现对考试成绩进行等级划分:分数>=90, 等级为A;90>分数>=80,等级为B;80>分数>=70,等级为C;70>分数>=60,等级为D;60>分数,等级为E。

3.1.1 if语句的基本结构

  1. if语句的分支
    注意:python中不用括号等来划分语句块,相同缩进的语句组成一个语句块。
if 表达式1 :
	分支
  1. 实现多路分支(else、elif)
    注意:python中没有switch和case语句,多路分支只能通过if-elif-elif-···-else控制流语句来实现;同样的整个分支结构中是有严格的退格缩进要求;。
if 布尔表达式1 :
	分支一
elif 布尔表达式2 :
	分支二
else :
	分支三

3.1.2 任务实现

步骤如下:

  1. 创建score变量来存放成绩数据。
  2. 设置if语句分支。
  3. 通过else与elif语句添加分支。
  4. 打印结果。
# -*- coding:utf-8 -*-

score = eval(input('请输入成绩:'))
if score >= 90:
    print('恭喜,您的成绩等级为A')
elif 80 <= score < 90:
    print('恭喜,您的成绩等级为B')
elif 70 <= score < 80:
    print('加油,您的成绩等级为C')
elif 60 <= score < 70:
    print('加油,您的成绩等级为D')
else:
    print('请下次好好努力,您的成绩等级为E')

运行结果如下:
在这里插入图片描述

3.2 实现一组数的连加与连乘

3.1.1 编写for循环语句

  • fo循环在python中是一个通用的序列迭代器,可以遍历任何有序的序列,如字符、列表、元组等。
  • python中的for语句接收可迭代对象,如序列和迭代器作为其参数,每次循环取其中一个元素。
  • python的for循环看上去像伪代码,非常简洁。
for a in ['e', 'f', 'g']:
    print('\t', a)
for a in 'string':
    print(a)

运行结果如下:
在这里插入图片描述

3.2.2 编写while循环语句

  • while循环也是常用的循环之一:只要布尔表达时为真,程序段就会被执行。
  • 对于正在执行的无限次循环可以使用“Ctrl + C”组合键来中断执行(不管用)。
  • 来由两个重要的语句continue、break:continue用于跳过该次循环,break则是用于退出循环。(3.2.4详细详解)
  • 布尔表达式加不加括号都可以。
while 布尔表达式:
	程序段
s = 0
while s <= 1:
    print('计数:',s)
    s = s+1
'''
s = 1
while (s <= 1):
    print('无限次循环')
'''

3.2.3 range函数

  • 在python中,for i in range(5)的执行效果相当于C中for(i=0;i<5;i++)
  • range(5)或者range(0,5):构造了序列0,1,2,3,4。(注意,这里包括0,但不包括5
  • range(a,b):能够返回列表[a,a+1,···,b-1]。
  • range函数经常和len函数可以快速通过索引访问序列并对其进行修改。len函数能够返回一个序列的长度,for i in range(len(L))能够迭代整个列表L的元素索引。
  • 直接使用for循环难以改变序列元素, 结合range与len函数来遍历序列并修改元素
for i in range(0, 5):
    print(i)
for i in range(0, 6, 2):  # 2可以理解为i=i+2
    print(i)
# 直接使用for循环难以改变序列元素
L = [1,2,3]
for a in L:
    a += 1
print(L)
# 结合range与len函数来遍历序列并修改元素
for i in range(len(L)):
    L[i] += 1
print(L)

运行结果如下:
在这里插入图片描述

3.2.4 运用break、continue、pass语句

  1. break
  • break语句用在while和for循环中,用来终止循环语句,即使循环条件没有False条件或者序列还被完全递归完,也会停止执行循环语句。
  • 如果在嵌套循环中,break语句可以停止执行最深层的循环,并开始执行下一行代码。
# break
s = 0
while True:
    s +=1
    if s == 6:
        break
print(s)
for i in range(0,10):
    print(i)
    if i == 1:
        break

运行结果如下:
在这里插入图片描述

  1. continue
    continue语句的作用是跳出本次循环,继续进行下一轮的循环。continue语句也是用在while和for循环中。
# continue
s = 3
while s >= 0:
    s -= 1
    if s == 1:
        continue
    print(s)
for i in range(0, 3):
    if i == 1:
        continue
    print(i)

运行结果如下:
在这里插入图片描述

  1. pass
    pass是空语句,作用是保持程序结构的完整性。pass不做任何事情,一般是用作占位符
# pass
for i in range(0,3):
    if i == 1:
        pass
        print('pass块在0·1之间占位,不做任何事情')
    print(i)

运行结果如下:
在这里插入图片描述

3.2.4 任务实现

  1. 创建一个列表vec
  2. 连加时,创建一个赋值为0的变量m;连乘时,创建一个赋值为1的变量n。
  3. 编写for循环语句。
  4. 编写连加或者连乘公式。
  5. 打印结果
# -*- coding:utf-8 -*-
# 连加
vec = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
m = 0
for i in vec:
    m = m + 1
print(m)
# 连乘
n = 1
for i in vec:
    n = n * i
print(n)

运行结果如下;
在这里插入图片描述

3.3 使用冒泡排序法排序

3.3.1嵌套循环

嵌套循环就是在一个循环中嵌入另一个循环。python语言是允许在一个循环体里面嵌入另一个循环。例如:

  1. for循环中嵌入for循环。
  2. while循环中嵌入for循环。
  3. while循环中嵌入while循环。

关于如何创建一个n*n,元素全为0的数组
参考网址1:python-Numpy学习之(二) numpy库(ones,zeros,eyes函数)
参考网址2:numpy中的zeros函数

# for-for循环的嵌套
import numpy as np
num = np.zeros((3, 3))  #用mp。zeros()函数创建一个3*3的元素为0的数组。
print('初始数组为:\n', num)
for i in range(0, 3):
    for j in range(0, 3):
        num[i, j] = i * j
print('改变后的数组为:\n', num)
# for-while循环的嵌套
for i in range(0, 11):
    while i > 8:
        print(i * 10)
        break

运行结果如下:
在这里插入图片描述

3.3.2 组合条件与循环

在循环中放入条件语句,才可以使得循环能够做更多的事情。

  1. for循环与条件语句的组合。
  2. while循环与条件语句的组合。
# for循环与条件语句的组合
print('10~15之间:')
for x in range(10, 15):  # 判断10·15之前的质数
    for i in range(2, x):
        if x % i == 0:
            j = x / i
            print('%d 等于%d * %d' % (x, i, j))
            break
        else:
            print('%d是一个质数' % x)
            break
# while循环与条件语句的组合
count = 0
print('打印0~5的数:count>3时,打印其平方')
while count < 5:   # 打印0~5:count>3时,打印其平方
    if count > 3:
        print(count**2)
    else:
        print(count)
    count = count + 1

运行结果如下:
在这里插入图片描述

3.3.3 任务实现

  1. 创建列表mppx
  2. 编写for循环与for循环的嵌套,外循环i的取值为length(len(mppx))。内循环j的取值为range(i+1)。
  3. 设置条件语句,当列表中的后一个元素比前一个元素大时,将他们的位置互换。
  4. 打印结果。
# -*- coding: utf-8 -*-
# 冒泡排序
# python中互换两个元素可直接使用:a,b = b,a
mppx = [1, 8, 2, 6, 3, 9, 4, 12, 0, 56, 45]
for i in range(len(mppx)):
    for j in range(i+1):
        if mppx[i] < mppx[j]:
            mppx[i], mppx[j] = mppx[j], mppx[i]
print(mppx)

运行结果如下:
在这里插入图片描述

3.4 输出数字金字塔

3.4.1 多变量迭代

  • 如果给定一个list或tuple,通过for循环可以遍历整个list或tuple,这种遍历称为迭代。在python中,迭代是通过for in 语句来完成的。
  • python中的for循环不仅可以用在list或tuple上,还可以作用在其他可迭代的对象上(如字典,由于dict的存储不是按照list的方式顺序排列,所以迭代出的结果顺序可能不一样)。
  • 在python中,for循环也可同时引用两个变量和三个变量。
# dict的迭代
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
    print(key)
# for循环同时引用两个变量
for x, y in [(1, 1), (2, 4), (3, 9)]:
    print(x, y)
# for循环同时引用三个变量
for x, y, z in [(1, 2, 3), (4, 5, 6), (7, 8, 9)]:
    print(x, y, z)

运行结果如下:
在这里插入图片描述

3.4.2 创建列表解析

  • 列表解析是一种高效创建新列表的方式,可以用来动态的创建列表。
  • 列表解析也可以称为列表推导式。

map的用法:
map(函数,列表):map根据提供的函数对指定序列做映射。如果要对列表中所有元素依次进行函数处理,都是靠for循环实现,map就是定义来实现循环的,但是map实现出来的是一个生成器,所以还要用list转出来。
filter的用法:
filter(函数,列表):filter是筛选函数。
lambde的用法:
lambda(参数,函数返回): lambda是一个匿名函数。;。

lambda(参数,函数返回);map(函数,列表)

# 创建列表解析
list00 = list(map(lambda x: x**3, range(6)))
print(list00)
list1 = [x ** 3 for x in range(6)]
print(list1)
seq = [1, 2, 3, 4, 5, 6, 7, 8]
list01 = list(filter(lambda x: x % 2 ==1, seq))
print(list01)
list2 = [x for x in seq if x % 2==0]
print(list2)
# 列表解析式的嵌套循环
list3 = [(i, j) for i in range(0, 3) for j in range(0, 3)]
print(list3)
list4 = [(i, j) for i in range(0, 3) if i < 1 for j in range(0, 3) if j > 1]
print(list4)

运行结果如下:
在这里插入图片描述

3.4.3 任务实现

  1. 利用eval函数与input函数设置输入语句,输入数字。
  2. 创建变量level来存放金字塔的层数。
  3. 编写嵌套循环,创建变量kk来存放每一层长度,设置t等于金字塔层数,设置length存放2*t-1。内循环中划分k等于1时与k不等于1时的情况。
  4. 设置一个公式来打印每一行输出的数字,这里可以利用format函数。
  5. 打印结果。

python中format函数用于字符串的格式化

# -*- coding: utf-8 -*-
# 完整的数字金字塔
num = eval(input('请输入一个整数:'))
print('数字金字塔显示如下:')
level = 1  # level表示金字塔的高度,即层数
while level <= num:  # 高度不超过层数
    kk = 1  # 每一层计数
    t = level
    length = 2 * t - 1
    while kk <= length:
        if kk == 1:
            if kk == length:
                print(format(t, str(2 * num - 1) + 'd'), '\n')
                break
            else:
                print(format(t, str(2 * num + 1 - 2 * level) + 'd'), '', end='')
                t -= 1
        else:
            if kk == length:
                print(t, '\n')
                break
            elif kk <= length / 2:
                print(t, '', end='')
                t -= 1
            else:
                print(t, '', end='')
                t += 1
        kk += 1
    level += 1

运行结果如下:
在这里插入图片描述

四、函数

4.1 自定义函数实现方差输入

  • 函数:将一些数据(参数)传递进程序进行处理,然后返回一些数据(返回值),也可以没有返回值,但它跟一个对象相关联。
  • 方法:方法和函数大致上是相同的,都是通过名字来进行调用的。方法与函数也有两个主要的不同之处:1. 方法中的数据是隐式传递的(函数的数据是显式传递的);2. 方法可以操作类内部的数据(而函数不行)。
  • 方法和对象相关(函数和对象无关):C语言和R语言只有函数,Java中只有方法,而C++和Python的方法和函数取决于是否在面向对象编程的类中使用。(C语言是面向过程的语言;C++、Java、Python为面向对象的语言。

R语言 是用于统计分析、绘图的语言和操作环境。R是属于GNU系统的一个自由、免费、源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具。

4.1.1 认识自定义函数

Python的函数中,参数不需要声明数据类型(但是这有利也有弊(不清楚参数的数据类型而输入错误的参数))。
自定义函数的格式如下:

def 函数名(形参):
	函数体
	renturn 结果

4.1.2 设置函数参数

Python中的函数参数主要有4种:位置参数、关键字参数、默认参数、可变参数。

  1. 默认参数:默认函数为设置函数的参数提供了参考(某人函数的值可传可不传)。
# -*- coding: utf-8 -*-
def interest(money, day=1, interest_rate=0.05):
    income = 0
    income = money*interest_rate * day/365
    print(income)
interest(5000)  # 默认参数的值可传可不传
interest(10000, 1, 0.05)

运行结果如下:
在这里插入图片描述

  1. 任意数量的位置可变函数:通常情况下,函数中参数个数表示函数可调用的参数个数的上限。但是在定义函数时若无法得知参数个数的情况,在Python中使用*args和 *kwargs 可以定义可变参数。
  • 在可变参数之前可以定义0到任意多个参数,但是可变参数永远放在参数的最后面。
  • 在定义任意数量的位置参数时需要一个前缀来表示,这些参数将会被放在元组*内并传入函数。
# 任意数量的位置可变参数
def exp(x, y, *args):
    print('x:', x)
    print('y:', y)
    print('args:', args)
exp(1, 5, 66, 55, 'abc')

运行结果如下:
在这里插入图片描述

  1. 任意数量的关键字可变参数:参数名称前面需要有前缀**, 这些参数会被传到 字典内并传入函数中。带前缀* *的参数必须在所有带默认值的参数之后,顺序不可以调转。
# 任意数量的关键字可变参数
def exp(x, y, *args, **kwargs):
    print('x:', x)
    print('y:', y)
    print('args:', args)
    print('kwargs:', kwargs)
exp(1, 2, 2, 4, 66, a='c', b=1)

运行结果如下:
在这里插入图片描述

4.1.3 返回函数值

  • print函数仅仅打印对象,打印出来的对象无法保存或者调用,而return函数返回的运行结果可以保存为一个对象供其他函数调用。
  • Python对函数返回值的数据类型没有限制,包括列表和字典等复杂的数据结构。
  • 当程序执行到函数中的return语句时,就会将指定的值返回并结束函数,后面的语句不会被执行。
# 返回函数值
def interest_r(a, b):
    A = a+1
    B = b+1
    print("方法中A的值为:", A)
    return B
A = 1
B = 1
print('A的初值为:%d,B的初值为:%d' % (A, B))
B = interest_r(A, B)
print('A的现值为:%d,B的初值为:%d' % (A, B))

运行结果如下:
在这里插入图片描述

4.1.4 调用自定义函数

  1. 位置参数调用:函数的参数严格按照函数定义时的位置传入。顺序不可以调换没否则会直接影响输入结果或者直接报错。
list1 = list(range(0, 10, 2))  # 将start = 0,stop = 10,step = 2的顺序传入
print(list1)
list2 = list(range(10, 0, 2))  # 调转start与stop的顺序后传入
# print(list2)  运行结果为:[]
list3 = list(range(10, 2, 0))  # 调转全部参数的顺序后传入
# print(list3) 运行结果出错
list4 = list(range(0, 10, 1))
print(list4)
list5 = list(range(10))  # range只有stop时,默认从start=0开始,步长step=1.
print(list5)

运行结果如下:
在这里插入图片描述
在这里插入图片描述

  1. 关键字参数调用:使用关键词参数时,可以不严格按照位置,因为解释器会自动按照关键字进行匹配。(关键字参数也可以与位置参数混用,但关键字参数必须跟在位置参数后面,并且位置关键字与参数位置应一一对应,关键字参数随意)
# 关键字参数调用
interest(money=5000, day=7, interest_rate=0.06)
interest(day=7, money=5000, interest_rate=0.06)
interest(5000, day=7, interest_rate=0.06)  # 位置参数与关键字参数混合使用
interest(5000, interest_rate=0.06, day=7)
interest(7, money=5000, interest_rate=0.06)  # 混用时,位置参数对应的位置不能改变 结果变错
# interest(money=5000, 7, interest_rate=0.05) #关键字参数在位置参数前面,结果报错

运行结果如下:
在这里插入图片描述

  1. 可变参数调用
  • 使用*arg可变参数列表可以直接将元组或者列表转换为参数,然后传入函数。
  • 使用** kwargs关键字参数列表可以直接将字典转换为关键字参数,然后传入函数中。
# 可变参数调用
arg = [0, 10, 2]
arg = list(range(*arg))
print(arg)

def user(username, age, **kwargs):
    print('username:', username,
          'age:', age,
          'other:', kwargs)
user('john', 27, city='guangzhou', job='Data Analyst')
kw = {'age': 27, 'city': 'guangzhou', 'job': 'Data Analyst'}
user('john', **kw)

运行结果如下:
在这里插入图片描述

4.1.5 嵌套函数

  • python中允许在函数中定义另外一个函数,即函数嵌套。
  • 定义在其他函数内部的函数称为内建函数,而包含有内建函数的函数称为外部函数。
  • 内建函数中的局部变量独立于外部函数,如果想要使用外部函数的变量,则需要声明该变量为全局变量。
  • python将函数是为对象,因此允许外部函数在返回结果时直接调用函数的结果,所以可对求平均值函数做简化,令其直接返回求和函数的结果。
# 嵌套函数
def mean(*args):
    #    m = 0
    def sum(x):
        sum1 = 0
        for i in x:
            sum1 += i
        return sum1
    #    m = sum(args) / len(args)
    #    return m
    return sum(args) / len(args)
ave = mean(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(ave)

运行结果为:
在这里插入图片描述

4.1.6 区分局部变量和全局变量

  • python创建、改变或查找变量名都是在命名空间中进行的,更准确地说,都是在特定域下进行的。
  • 由于python不能声明变量,所以变量第一次被赋值的时候即与一个特定作用域绑定了。定义在函数内部的变量拥有一个局部作用域,定义在函数外部的变量拥有全局作用域。
  1. 局部变量:定义函数时,往往需要在函数内部对变量进行定义和赋值,在函数体内定义的变量为局部变量。(所有针对局部变量的操作仅在函数体内有效)
# 局部变量
def sum2(*arg):
    sum1 = 0
    for i in range(len(arg)):
        sum1 += arg[i]
    return sum1
sum1 = 0
print(sum2(1, 2, 3, 4, 5))
print(sum1)

运行结果如下:
在这里插入图片描述
2. 全局变量:定义在函数体外面的变量为全局变量

  • 全局变量可以在函数体内部被调用。
  • 但是全局变量不能在函数体内直接被赋值
  • 若同时存在全局变量和局部变量,那么函数体会使用局部变量对全局变量进行覆盖。
  • 如果想要在函数体内对全局变量进行赋值,那么需要使用关键字 global (嵌套函数中使用nonlocal ,其用法域global一样)。(尽量在程序中少用global,它会将代码变得混乱,可读性变差;局部变量会使代码更加抽象,封装性更好。)
# 全局变量
sum1 = 10
def fun():
    sum1 = 100
    sum_global = sum1 + 100
    print('同时存在全局变量sum1=10,局部变量sum1=100,则结果为:')
    # sum1 += 1   # 全局变量不能在函数体内修改和赋值
    return sum_global
print(fun())
# 使用global,在函数体内对全局变量赋值
sum1 = 0
def sum2(*arg):
    global sum1
    for i in range(len(arg)):
        sum1 += arg[i]
    return sum1
print(sum1)
print(sum2(1, 3, 5, 7))
print(sum1)
print(sum2(1, 3, 5, 7))

运行结果如下:
在这里插入图片描述

4.1.7 任务实现

任务:方差计算公式的一个推导公式为平方的均值减去均值的平方

1.构建求和函数sum及平方和函数。
2. 构建求均值函数mean,需要调用求和函数的结果。
3. 构建求方差函数var,需调用求平方和函数及求均值函数的结果。
4. 在方差函数中内建求平方和函数及求均值函数,并在求均值函数中在内建一个求和函数。

# -*- coding: utf-8 -*-

def var(*args):  # 构建主体方差函数
    def mean(z):  # 内建求均值函数
        def sum(x):  # 内建求和函数
            sum1 = 0;
            for i in x:
                sum1 += i
            return sum1
        return sum(args) / len(args)    # 平均值 = 和 / 长度 
    
    def sums(y):  # 内建求平方和函数
        sum2 = 0
        for i in y:
            sum2 += i**2
        return sum2
    return sums(args) / len(args) - mean(args)**2  # 方差 = 平方和的均值 - 均值的平方


print(var(1, 2, 3, 4, 5, 6, 7, 8, 9))

4.2 使用匿名函数添加列表元素

4.2.1 lambda、map、fib、filter函数

  1. lambda创建匿名函数(函数没有具体的i名称)

格式:lambda 函数参数:返回值

  1. lambda定义的是单行函数,如果需要复杂的函数,应使用def语句。
  2. lambda语句可以包含多个参数。
  3. lambda语句有且仅有一个返回值。
  4. lambda语句中的表达式不能含有命令,且仅有一条表达式。(避免匿名函数䣌滥用)
# lambda创建匿名函数
example = lambda x: x ** 3
print(example)
print(example(2))

from math import log  # 引用math库中的对数函数
def function_log(base):  # 创建一个范围值为:以base为底的匿名对数函数
    return lambda x: log(x, base)
my_log = function_log(3)  # 调用对数函数,其底数值设置为3
print(my_log(9))  # 使用对数函数,还要设置其真数

运行结果为:
在这里插入图片描述

  1. map函数

格式:map(func,list)
作用:在执行时,序列对象(list)中的每个元素,按照从左到右的顺通过把函数(funx)一次作用在list的每个元素上,得到一个新的llist并返回
注意:map函数不改变原有的list,只是返回一个新的list。
重要应用:从键盘上输入一个数组
num = list(map(int,input(“请输入一组数(以空格隔开):”).split()))

# map函数
def add(x):
    x += 3
    return x
num = list(range(10))
# num = list(map(int,input("请输入一组数(以空格隔开):").split())) # 从键盘上输入一组数
num1 = list(map(add, num))  # 普通的调用函数实现
num2 = list(map(lambda x: x+3, num))  # 速度快,可读性强
print(num)
print(num1)
print(num2)

运行结果为:
在这里插入图片描述

  1. fib函数(递归函数)

斐波那契函数:
当n<=2时:f(n)=1
当 n>2 时: f(n)=f(n-1)+f(n-2)
计算过程如下(n=3):
(1)n=3,fib(3),判断为fib(3-1)+fib(3-2)。
(2)先看fib(3-1),即fib(2),返回结果为2。
(3)再看fib(3-2),即fib(1),返回结果为2。
(4)最后计算第(1)步,结果为fib(n-1)+fib(n-2)=2+2=4,将结果返回。

# fib函数求解斐波那契额数列
def fib(n):
    if n <= 2:
        return 2
    else:
        return fib(n-1) + fib(n-2)
num = eval(input('请输入项数n:'))
print('第{}项为:{}'.format(num, fib(num)))
print('斐波那契数列为:')
for i in range(1,num+1):
    print('{}'.format(fib(i)), end='\t')

运行结果为:
在这里插入图片描述

  1. filter函数(过滤函数)

格式:filter(func,list)
作用:filter函数接收一个函数(func)和一个元素列表(list),这个func函数的作用是对每个元素进行判断

# filter函数
list1 = [1, 4, 67, 9, 12, 17]
list2 = list(filter(lambda x: x % 2 == 1, list1))
print(list1)
print(list2)
s1 = 'i love python and R'
s2 = list(filter(lambda c: c != 'o', s1))
s2 = ''.join(s2)   # 变为字符型
print(s1)
print(s2)

运行结果为:
在这里插入图片描述

4.2.2 任务实现

  1. 先用def关键字定义一个累加函数add。
  2. 创建一个空列表和一组数据[0,9]。
  3. 用循环结构对列表进行数据累加后的元素添加(list.append)。
  4. 使用匿名函数代替累加函数,再进行后续操作。
  5. 使用map函数快速实现上述操作。
# -*- coding: utf-8 -*-
# 正常方式
def add(x):
    x +=3
    return x
new_nums = []
for i in range(10):
    new_nums.append(add(i))
print(new_nums)
# lambda函数方式(匿名函数)
lam = lambda x: x+3
n2 = []
for i in range(10):
    n2.append(lam(i))
print(n2)
# 或者
lam = lambda x: x+3
n1 = []
[n1.append(lam(i)) for i in range(10)]
print(n1)
# map函数
nums = list(range(10))
aa = list(map(lambda x: x+3, nums))  # map(add, nums)
# [aaa**2 for aaa in aa]  # 速度快,可读性强
print(aa)
# 更快
bb = list(map(lambda x: x+3, list(range(10))))
print(bb)

运行结果为:
在这里插入图片描述

4.3 存储并导入函数模块

关于封装:本任务将实现简单的封装方法,将自定义函数封装为函数模块,然后导入模块,在调用里面的函数。

4.3.1 存储并导入整个模块

导入模块的函数,步骤如下:

  1. 首先,需要先创建一个模块。创建一个包含make_steak函数的模块,然后鸿文件中的其他代码删除。将改代码块在所在目录中保存为steak.py。
# 文件名为 steak.py
def make_steak(d, *other):
    print('Make a steak wll done in %d ' % d + 'with the other:')
    for o in other:
        print('-' + o)
  1. 接下来 ,导入整个模块,并且调用里面的make_steak函数两次。
import steak
steak.make_steak(9, 'salad')
steak.make_steak(8, 'red wine', 'salad', 'coffee')

运行结果为:
在这里插入图片描述

4.3.2 导入函数

  1. 导入指定函数。
    在python中,可以导入模块中的指定函数,也可以是多个指定函数。

格式:from 文件名 import 函数名
作用:导入模块中的指定函数。
用法:使用这种方法,调用函数时就不需要加模块的前缀,直接调用它的函数名称即可。
缺点:但如果导入模块的函数较多,则这种方法比较麻烦。

# 导入指定函数
from steak import make_steak
make_steak(9, 'salad')
make_steak(8, 'red wine', 'salad', 'coffee')
  1. 导入所有函数。
    如果模块中的函数较多,并需要导入所有函数,使用星号(*)运算符。

格式:from 文件名 import 星号(*)
作用:将所有函数都导入当前程序中。
用法:采用没有模块前缀的方法可以调用模块中的所有函数
缺点:如果模块中的函数名称和项目程序中的名称相同,就会倒是混乱或者程序出错,所以一般不要采用这种导入方法。

# 导入指定函数
from steak import make_steak
make_steak(9, 'salad')
make_steak(8, 'red wine', 'salad', 'coffee')

4.3.3 指定别名

关于Python的导入方法,最佳的是,只导入所需使用的函数,或者导入整个模块,并用前缀的方式表示。这能让代码更清晰,更容易阅读和理解。

  1. 指定函数别名(from 模块名 import 方法名 as 方法别名 )
    如果导入的函数名称可能与程序中现有的名称冲突,或者名称太长,可用as语句在导入时给函数指定别名
# 指定函数别名
from steak import make_steak as ms
ms(9, 'salad')
ms(8, 'red wine', 'salad', 'coffee')
  1. 指定模块别名(from 模块名 as 模块别名)
    在python中,通过给模块指定别名,能够轻松地调用模块中的函数,并且代码更简单。
# 指定模块别名
import steak as s
s.make_steak(9, 'salad')
s.make_steak(8, 'red wine', 'salad', 'coffee')

4.3.4 任务实现

  1. 将前文任务4.1中的方差函数封装并命名为test5.1.py。
  2. 导入封装好的函数模块。
  3. 导入模块中特定的var.var。
  4. 给函数指定别名fangcha。
  5. 给函数模块指定别名V。
  6. 导入模块中的所有函数。
# -*- coding: utf-8 -*-
# 导入封装好的函数模块
import var
var1 = var.var(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(var1)
# 导入模块中特定的函数var.var
from var import var
var2 = var(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(var2)
# 给var函数指定别名为fangcha
from var import var as fangcha
var3 = fangcha(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(var3)
# 给var函数模块指定别名V
import var as V
var4 = V.var(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(var4)
# 导入模块中的所有函数
from var import *
var5 = var(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(var5)

运行结果如下:
在这里插入图片描述

五、面向对象编程

python不只是解释型语言,也是一门面向对象的编程语言,因此自定义对象是python语言的核心之一。

5.1 认识面向对象编程

5.1.1 类与对象

  • 面向对象编程(Object Oriented Programming,OPP)即面向对象程序设计。
  • 类和对象是OOP中的两个关键内容
  • 在面向对象编程中,以类来构造现实世界中的事物情景,在基于类创建对象来帮助进一步认识、理解、刻画。根据类来创建的对象,每个对象都会自动带有类的属性和特点,还可以按照实际需要赋予每个对象特有的属性,这个过程称为类的实例化
  • 抽象的直接表现形式通常为类。
  • 抽象指对显示世界的事物、行为和特征建模、建立一个相关的数据集用于描绘程序结构,从而实现这个模型。
  • 抽象不仅包括这种模型的数据属性,还定义了这些数据的接口
  • 从面向对象设计(Object Oriented Design,OOD)角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的,可以进行相似编码,或者编入与对象交互的对象中。
  • 从现实角度来看,抽象类与普通类的不同之处在于:抽象类只有抽象方法(没有实现功能),该类不能被实例化,只能被继承。且子类必须实现抽象方法。

5.1.2 体会面向对象实例

  • 面向过程是分析处解决问题所需要的步骤,然后用函数一步一步实现这些步骤,使用的时候一个一个依次调用即可。
  • 面向对象是把构成问题的事物分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

以下“五子棋”为例:

  • 面向过程的设计思路就是首先分析问题的步骤,即开始游戏–>黑子先走–>绘制画面–>判断输赢–>轮到白子–>绘制画面–>判断输赢–>返回步骤2–>输出结果,把每个步骤分别用函数来实现,问题就解决了;
  • 面向对象的设计思路则是从另一种思路来解决问题,它将其分为3个对象:一是黑白双方,双方的行为是一模一样;二是棋盘系统,负责绘制画面;三是规则系统,负责判断注入犯规、输赢等。第一类对象负责接收用户输入信息,并告知第二类对象棋子布局的变化,棋盘对象接收到棋子的输入就要负责在画面上显示处这种变化,同时利用第三类对象来对棋局进行判定。

可以明显看出,面向对象是以功能来划分问题的,而不是循环步骤

5.1.3 了解面向对象的优点

  1. 基于数据抽象的概念可以在保持外部接口不变的情况下对内部进行修改,从而减少甚至避免对外界的干扰。
  2. 通过继承可以大幅减少冗余代码,并可以方便地拓展现有代码,提高编码效率,也降低了出粗概率,降低了软件维护难度。
  3. 结合面向对象分析、面向对象设计,允许将问题中的对象直接映射到程序中,键少了软件开发过程中中间环节的转换过程。

5.2 创建Car类

任务描述:
创建一个Car类,为其赋予车轮数(4)、颜色(red)的属性,并定义函数来输出“汽车有4个车轮, 颜色时红色。”及“车行驶在学习的大道上。” ,在调用类的方法(函数)。

6.2.1 定义和使用类

在面向对象的程序设计中,类是创建对象的基础,描述了所创建对象共有的属性和方法。它同时也有接口和结构,接口可以通过方法与类或对象进行互操作,而结构表现处一个对象中有什么样的属性。这些都为面向对象编程的3个最重要的特性(封装性、继承性、多态性)提供了实现手段。

定义一个类,格式如下:

在python中,首字母大写的名称指的是类(Car)
如果名称是两个单词,两个单词的首字母都要大写,”驼峰式命名“
函数名称一般用小写字母或者下划线符号连接。
类的函数(方法)的参数都有一个self参数,并默认为第1个参数。

class 类名:
	属性列表
	方法列表
class Cat():
    """一次模拟猫咪的简单尝试"""
    name = 'xinxin'
    age = 3
    def sleep(self):
        """模拟猫咪被命令睡觉"""
        print('%d岁的%s正在沙发上睡懒觉。' % (self.age, self.name))
    def eat(self,food):
        """模拟猫咪被命令吃东西"""
        self.food = food
        print('%d岁的%s再吃%s' % (self.age, self.name, self.food))
cat = Cat()
cat.eat('鱼')

运行结果为:
在这里插入图片描述

5.2.2 绑定self

  • python的类的方法和普通的函数有一个很明显的区别,就是类的方法必须有一个额外的参数(self),并且在调用这个方法的时候不必为这个参数赋值。python类方法的这个特别参数指代的是对象本身。
  • self代表当前对象的地址,能避免非限定调用时找不到访问对象或变量。当调用sleep等函数时,会自动把该对象的地址作为第1个参数传入;如果不传入地址,程序将不知道该访问那个对象。
  • 在python中,self不是关键字,可以定义成a、b或者其他名字、但是最好还是安装约定使用self。self总是指调用时的类的实例。
class Cat():
    def sleep(self):
        print(self)
new_cat = Cat()
new_cat.sleep()

运行结果为:
在这里插入图片描述

5.2.3 掌握类的专有方法

无论任何类,都有类的专有方法,它们的特殊性由代码就能看出来,通常是用双下划线“__”开头或者结尾
查看类的属性及方法:

# #查看类的属性及方法
class Example():
    pass
example = Example()
print(dir(example))  # 查看类属性
print(dir(Example))  # 查看方法

运行结果为:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', 
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', 
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

常用的类的专有方法:

类的专有方法功能
__ init __构造函数,在生成对象时调用
__ del __析构函数,解释对象时使用
__ repr __打印,转换
__ setitem __按照索引赋值
__ getitem __按照做因获取值
__ len __获得长度
__ cmp __比较运算
__ call __函数调用
__ add __加运算
__ sub __减运算
__ mul __乘运算
__ div __除运算
__ mod __求余运算
__ pow __乘方

5.2.4 任务实现

任务步骤如下:

  1. 创建Car类,添加车轮数和颜色两个属性。
  2. 定义第1个函数,并增加参数name,输出“name有4个车轮,颜色时红色。”
  3. 定义第2个函数,输出“车行驶在学习的大道上。”
  4. 调用Car类,赋值于新变量。
  5. 对新变量调用自己定义的两个函数。
# -*- coding utf-8 -*-
class Car():
    WheelNum = 4
    color = 'red'
    def CarInfo(self,name):
        self.name = name
        print("{}有{}个车轮,颜色是{}".format(self.name, self.WheelNum, self.color))
    def run(self):
        print("车行驶在学习的大道上!")
        
        
car = Car()  # 调用Car类
car.CarInfo('玛莎拉蒂')
car.run()

运行结果如下:
在这里插入图片描述

5.3 创建Car对象

任务描述
创建Car对象,先用构造器构造初始化类的实例对象,赋予属性newWheelNum和newColor,并定义函数,实现输出“车载跑,目标:夏威夷。”,然后创建具体对象,访问对象的属性和方法(函数),最后用机构的方法删除对象。

5.3.1 创建对象

__ init __是类的一个特殊的方法,每当根据类创建实例时,python都会自动运行它,这就是一个初始化手段,python中的 __ init __方法用于初始化类的实例对象。

c++的构造函数,可创建一个类的实例对象。
而python执行 __ init __ 方法时,实例对象已被构造出来。__ init __方法会在对象构造出来后自动执行,所以可以用于初始化所需要的数据属性。

# 创建对象
class Cat():
    """再次模拟猫咪的简单尝试"""
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def sleep(self):
        """模拟猫咪被命令睡觉"""
        print('{}岁的{}正在沙发上睡觉'.format(self.age, self.name))

    def eat(self, food):
        """模拟猫咪被命令吃东西"""
        self.food = food
        print('{}岁的{}再吃{}'.format(self.age, self.name, self.food))


cat = Cat('xinxin', 4)
cat.sleep()
cat.eat('fish')

运行结果如下:
在这里插入图片描述

5.3.2 删除对象

  1. 创建对象时,默认调用构造方法。同样,删除对象时,也会默认调用析构方法。
  2. __ del __是类的另一个特殊的方法,当使用del语句删除对象是,会调用它本身的析构函数。
  3. 另外,当对象在某某个作用域中调用完毕,跳出其作用域的同时,析构函数也会被调用一次,释放内存空间。
# 删除对象
class Animal():
    # 构造方法
    def __init__(self):
        print('---构造方法被调用---')
    # 析构方法

    def __del__(self):
        print('---析构方法被调用---')


cat = Animal()
print(cat)
del cat
print(cat)

执行cat = Animal()的结果:
在这里插入图片描述
执行 print(cat)的结果:
在这里插入图片描述
执行del cat;print(cat)的结果:
在这里插入图片描述

5.3.3 掌握对象的属性和方法

1. 对象的属性

对象的变量由类的每个实例对象拥有。不同对象调用该变量,其变量值改变后,对象之间互不影响。

  • 如果在类方法中引用某个属性,则该属性必定是类属性。
  • 如果在实例对象方法中引用某个属性(不进行更改),并且存在同名的类属性:若实例对象由该名称的对象属性,则对象属性会屏蔽类属性,即引用的是对象属性;若实例对象没有该名称的对象属性,则引用的是类属性。
  • 如果在实例对象方法中更改某个属性,并且存在同名的类属性,此时,若实例对象由该名称的对象属性,则修改的是对象属性;若实例对象没有改名称的实例属性,则会创建一个通名称的对象属性。
  • 要修改类属性,如果在类外,则可以通过类对象修改;如果在类里面,则只有在类方法中进行修改。

2. 对象的方法
(1). 对象方法的引用

cat1 = Cat('Tom', 3)
sleep = cat1.sleep
sleep()
cat2 = Cat('Jack', 4)
eat = cat2.eat
eat('fish')

运行结果为:

(2). 对象属性的私有化

print(cat1.age)
print(cat2.name)

运行结果为:
在这里插入图片描述
为了防止程序开发人员无意中修改对象的状态,需要对类的数据属性和方法进行私有化。python不支持直接私有方式,为了让方法的数据属性或方法变成私有,只需要在方法的数据属性或方法的名字前面加上双下划线即可。

# 私有化方法
class Cat():
    """再次模拟猫咪的简单尝试"""
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def sleep(self):
        """模拟猫咪被命令睡觉"""
        print('{}岁的{}正在沙发上睡觉'.format(self.__age, self.__name))

    def eat(self, food):
        """模拟猫咪被命令吃东西"""
        self.__food = food
        print('{}岁的{}再吃{}'.format(self.__age, self.__name, self.__food))

    def getAttribute(self):
        return self.__name,self.__age


cat1 = Cat('Tom', 3)
cat2 = Cat('Jack', 4)
# print("Cat1的名字为:", cat1.name)  # 会报错,此时不能从外部访问对象的属性
# print('Cat2的名字为:', cat2.name)
cat1.sleep()  # 只能通过设置好的接口函数来访问对象
cat2.eat('fish')
print(cat1.getAttribute())

注释部分的运行结果为:
在这里插入图片描述
最终运行结果为:
在这里插入图片描述
但是通过双下划线实现的私有化其实是“伪私有化”,实际上还可以从外部访问这些私有数据属性。
特殊的:可以通过: 对象._类名__属性 来访问私有化的属性。

# 特殊的:可以通过: 对象._类名__属性 来访问私有化的属性
print(cat1._Cat__name)
print(cat2._Cat__age)

运行结果为:
在这里插入图片描述

5.3.4任务实现

具体步骤如下:

  1. 先创建Car类。
  2. 将Car类实例化,添加newWheelNum和newColor两个属性。
  3. 定义一个函数,输出"车再跑,目标:夏威夷"。
  4. 定义析构方法,输出”—析构方法被调用—“。
  5. 调用Car类,创建对象实例。
  6. 访问对象属性并调用函数。
  7. 用析构方法删除所创建的实例化对象,并查看独享是否被删除。
# -*- coding: utf-8 -*-
class Car():
    # 构造器方法
    def __init__(self, newWheelNum, newColor):
        self.wheelNum = newWheelNum
        self.color = newColor

    # 功能函数
    def run(self):
        print('车再跑,目标:夏威夷。')

    # 机构函数
    def __del__(self):
        print('---析构函数方法被调用---')


car = Car(4, 'green')
print('车的颜色为:', car.color)
print('车轮子数量为:', car.wheelNum)
car.run()

del car
# print(car)

运行结果为:
在这里插入图片描述

5.4 迭代Car对象

任务描述:
流程控制语句中已经接触过迭代方式,这里说的是面向对象过程中对象的迭代。本任务将对Car类进行迭代,增加品牌(brand)和废气涡轮增压(T)两个属性,并依次输出所有属性。

5.4.1 生成迭代器

迭代是python最强大的功能之一,是访问集合的一种方式。之前接触到的python容器对象都可以用for循环进行遍历。

for element in [1, 2, 3]:  # 列表迭代
    print(element)
for element in (1, 2, 3):  # 元组迭代
    print(element)
for key in {'one': 1, 'two': 2}:  # 字典迭代
    print(key)
for char in '123':
    print(char)
for line in open('myfile.txt'):
    print(line)

运行结果如下:
在这里插入图片描述
迭代器有两个基本的函数,即iter函数和next函数。
加入for语句在容器对象上调用iter函数,则该函数会返回一个定义next函数的迭代对象,它在容器中逐一访问元素。
当next函数找不到后续元素时,会引发一个StopIteration异常,告知for循环终止。

# iter函数与next函数
L = [1, 2, 3]
it = iter(L)
print(it)
print(next(it))
print(next(it))
print(next(it))
print(next(it))

输出结果:
在这里插入图片描述

**迭代器(Iterator)是一个可以记住遍历的位置的对象,**从第1个元素被访问开始,直到所有元素被访问完结束。但是要注意的是,迭代器只能往前,不会后退。

# iter函数应用
class Cat():
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.info = [self.name, self.age]
        self.index = -1

    def getName(self):
        return self.name

    def getAge(self):
        return self.age

    def __iter__(self):
        print('名字 年龄')
        return self

    def next(self):
        if self.index == len(self.info) - 1:
            raise StopIteration
        self.index += 1
        return self.info[self.index]


cat = Cat('coffe', 3)
print(cat.getName())
iterator = iter(cat.next, 1)
for info in iterator:
    print(info)

运行结果为:
在这里插入图片描述

5.4.2 返回迭代器

1. yieled
在python中,使用生成器(Generator)可以很方便地支持迭代器协议。生成器是一个返回迭代器的函数,它可以通过常规的def函数来定义,但是不用return语句返回,而是用yield语句一次返回一个结果。一般的函数生成值后会退出,但是生成器函数在生成值后会自动挂起暂停执行状态并保存状态信息。这写信息在函数恢复时将再度生效,通过在每个结果之间挂起和几句它们的状态自动实现迭代协议。

# 生成器函数--斐波那契额数列
import sys
def fibonacci(n, w=0):
    a, b, counter = 0, 1, 0
    while True:
        if counter > n:
            return
        yield a
        a, b = b, a + b
        print('{},{}'.format(a, b))
        counter += 1
f = fibonacci(10, 0)
while True:
    try:
        print(next(f), end=" ")
    except:
        sys.exit()

执行yield a 的运行结果:
在这里插入图片描述
不执行yield a的运行结果:
在这里插入图片描述
2. 生成器表达式
列表解析的一般形式如下。

expr for iter_var in iterable if cond_expr

迭代iterable里所有内容时,每一次迭代后,
把iterable里面满足cond_expr条件的内容放到iter_var中,
在在表达式expr中应用iter_var的内容,最后用表达式的计算值生成一个列表。

例如,生成一个list来保护50以内的所有奇数。

# 列表解析 []
list = [i for i in range(50) if i % 2]
# 生成器表达式 ()
list1 = (i for i in range(100) if i % 2)
print(list)
print(list1)

运行结果如下:
在这里插入图片描述

5.4.3 任务实现

具体步骤如下:

  1. 在原有Car类上增加品牌(brand)和废弃涡轮增压(T)两个属性。
  2. 创建列表(brand,wheelnum, color, T )并赋值给变量。
  3. 为迭代设置初试变量。
  4. 分别定义返回对应属性值的函数。
  5. 定义迭代函数,输出“品牌 车轮数 颜色 废弃涡轮增压”,返回对象位置。
  6. 定义迭代器的基本方法,用if语句进行判断,返回对应位置的属性。
  7. 调用Car类,创建对象并命名。
  8. 访问对象属性和调用迭代函数,并输出结果。
# -*- coding:utf-8 -*-
class Car():
    def __init__(self, brand, newWheelNum, newColor, T):
        self.brand = brand
        self.wheelNum = newWheelNum
        self.color = newColor
        self.T = T
        self. info = [self.brand, self.wheelNum, self.color, self.T]
        self.index = -1

    def getBrand(self):
        return self.brand

    def getnewWheelNum(self):
        return self.wheelNum

    def getnewColor(self):
        return self.color

    def getT(self):
        return self.T

    def __iter__(self):
        print('品牌 车轮树 颜色 废气涡轮增压')
        return self

    def next(self):
        if self.index == 3:
            raise StopIteration
        self.index += 1
        return self.info[self.index]


car = Car('BMW', 4, 'red', 2.4)
iterator = iter(car.next, 1)
for info in iterator:
    print(info)

运行结果如下:
在这里插入图片描述

5.5 产生land_Rover对象

任务描述
本任务要在创建的Car类上产生子类Land_Rover,而且要使子类Land_Rover
拥有两恶搞弗雷属性(品牌、颜色)和两个自带属性(车轮数、废气涡轮增压),然后输出子类属性。

5.5.1 继承父类属性和方法

  1. 继承
    面向对象编程带来的好处之一时代码的宠用,实现这种重用的方法之一时继承机制。

继承(Inheritance)时两个类或多个类之间的父子关系,子类继承了父类的所有公用数据属性和方法,并且可以通过编写子类的代码扩充子类的供能。继承实现了数据和方法的重用,减少了代码的冗余度。
继承的特点:

  1. 在继承中,积累初试化方法__init__不会被自动调用。如果希望子类调用基类的__init__方法,需要在子类的__init__方法中显示调用它。这与C++和C#区别很大。
  2. 在调用积累的方法时,需要加上基类的类名前缀,且带上self参数变量。注意,在类中调用在该类中定义的方法是不需要self参数的。
  3. python中总是首先查找对应类的方法,如果在子类中没有对英的方法,python才会在继承链的基类中按顺序查找。
    在python继承中,子类不能访问基类的私有成员。
class Cat():
    def __init__(self):
        self.name = '猫'
        self.age = 4
        self.info = [self.name, self.age]
        self.index = -1

    def run(self):
        print(self.name, '--再跑')

    def getName(self):
        return self.name

    def getAge(self):
        return self.age

    def __iter__(self):
        print('名字 年龄')
        return self

    def next(self):
        if self.index == len(self.info) - 1:
            raise StopIteration
        self.index += 1
        return self.info[self.index]


class Bosi(Cat):
    def setName(self, newName):
        self.name = newName

    def eat(self):
        print(self.name, '--在吃')


bs = Bosi()
print('bs的名字为:', bs.name)
print('bs的年龄为:', bs.age)
bs.run()
bs.setName('波斯猫')
bs.eat()
iterator = iter(bs.next, 1)  # 迭代输出父类的属性
for info in iterator:  
    print(info)

运行结果为:
在这里插入图片描述

  1. 多继承
    如果有多个父类,则父类名需要全部写在括号里,这种情况称为多继承。
    格式如下:
class 子类名(父类名1,父类名2,···)
# 多继承
class A(object):
    def __init__(self):
        print("   ->Input A")
        print("   <-Output A")


class B(A):
    def __init__(self):
        print("   -->Input B")
        A.__init__(self)
        print("   <--Output B")


class C(A):
    def __init__(self):
        print("   --->Input C")
        A.__init__(self)
        print("   <---Output C")


class D(B, C):
    def __init__(self):
        print("--->Input D")
        B.__init__(self)
        C.__init__(self)
        print("<---Output D")


d = D()
issubclass(C, B)  # 判断一个类是不是类一个类的子孙类
issubclass(C, A)

输出结果:
在这里插入图片描述

5.5.2 掌握其他方法

面向对象的三大特性是指重载、封装和多态。

  1. 重载
    所谓重载,就是子类中有一个和父类名字相同的方法,子类中的方法会覆盖父类中同名的方法。
# 重载
class Cat:
    def sayHello(self):
        print("喵喵---1")
class Bosi(Cat):
    def sayHello(self):
        print("喵喵---2")
bosi = Bosi()
bosi.sayHello()

运行结果:
在这里插入图片描述

  1. 封装
    封装(Encapsulation)就是将抽象得到的数据和行为(或功能)相结合,形成一个有机(即类)。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节而只是通过外部接口和特定的访问权限来使用类即可。简而言之,就是将内容分装到某个地方,以后再去调用被封装在某处的内容。
  2. 多态
    多态性(Polymorphism)是允许将父对象设置成和一个或多个它的子对象相等的记住,比如Car = Land_Rover。多态性使得能够利用同一类(父类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以及不同的方式执行相同的操作。
    python是动态语言,可以调用石磊方法,不检查类型,只需要方法存在,参数正确就可以调用,这就是与静态语言(例如Java)最大的差别之一,表明了动态(运行时)绑定的存在。

5.5.3 任务实现

  1. 使用class语句创建子类Land_Rover。
  2. 使用构造方法创建对象,设置品牌、颜色两个父类参数和两个自带参数。
  3. 在子类中调用父类构造函数。
  4. 调用子类,创建对象并命名。
  5. 访问对象属性,调用迭代函数,并输出结果。
# -*- coding:utf-8 -*-
class Car():
    def __init__(self, brand, newWheelNum, newColor, T):
        self.brand = brand
        self.wheelNum = newWheelNum
        self.color = newColor
        self.T = T
        self.info = [self.brand, self. wheelNum, self.color, self.T]
        self.index = -1

    def getBrand(self):
        return self.brand

    def getNeWheelNum(self):
        return self.wheelNum

    def getNewColor(self):
        return self.color

    def getT(self):
        return self.T

    def __iter__(self):
        print("品牌 车轮数 颜色 废气涡轮增压")
        return self

    def next(self):
        if self.index == 3:
            raise StopIteration
        self.index += 1
        return self.info[self.index]


class Land_Rover(Car):
    def __init__(self, brand, newColor):
        self.brand = brand
        self.wheelNum = 4
        self.color = newColor
        self.T = 3
        Car.__init__(self, self.brand, self.wheelNum, self.color, self.T)


car = Car('BMW', 4, 'red', 2.4)
iterator = iter(car.next, 1)
for info in iterator:
    print(info)

运行结果如下:

在这里插入图片描述

六、文件基础

本章主要介绍如何处理文件和保存数据,以便让程序使用得更容易,使用户能够读取TXT或CSV格式的文件,以及输出为TXT或CSV格式的文件;介绍如何用Python编程实现对计算机以及文件夹的查询、移动、复制与删除等操作:介绍如何对文件进行压缩与解压等。

6.1 认识文件

文件类型如下:

文件类型扩展名
文档文件.txt .doc .hlp .rtf .html
压缩文件.rar .zip. gz .z
声音文件.mp3
图形文件.bmp .gif . jpg .pic .png .tif
系统文件.int .sys .dll .adt
可执行文件.exe .com
可执行批处理文件.bat

6.2 读取.txt文件中的数据

任务描述
用python读取瓦尔登湖小说(Walden.txt)文件,并将文档保存到本章程序设置的文件夹里,然后用python读取文件Walden.txt中的数据,打印出来。

6.2.1 读取整个文件

1. 打开文件:标识符可指定文件打开模式为读取模式®、写入模式(w)、附加模式(a)或读取和写入文件的模式(r++)。Python默认只读模式打开文件。格式如下:

f = open('e_digits.txt', 'r')

2. 读取文件:使用read函数一次性读取文件的全部内容。

txt = f.read()
print(txt)

3. 关闭文件:调用close函数关闭文件。文件使用完毕后必须关闭,引文文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的。

f.close()

6.2.2 使用with语句读取文件

  1. 使用try···finall···结构:无论是否出错,都能够正常关闭文件。
# 使用try···finall···结构
try:
    f = open('e_digits.txt', 'r')
    print(f.read())
finally:
    if f:
        f.close()
  1. 使用with语句:更加简洁,并且能很好地处理上下文环境产生的异常,会自动调用close函数。
# 使用with语句
with open('e_digits.txt', 'r') as f:
    print(f.read())

6.2.3 设置工作路径

1. 相对文件路径:如果目标文件实在本项目文件的子文件夹那么需要提供相对文件路径让Python到指定位置查找文件,而该文件是相对于当前运行的程序所在的目录而言的,即相对路径。

# 相对文件路径
# 方法一:
with open('text_file\e_digits.txt', 'r') as f:
    print(f.read())
# 方法二:
with open('./text_file/e_digits.txt', 'r') as f:
    print(f.read())

2. 绝对文件路径:如果目标文件不在本项目文件夹下,那么需要提供完整准确的存储位置(即绝对文件路径)给程序,不需要考虑当前运行程序存储在什么位置。
(1).反斜杠(\):在绝对路径前面加了r,这是因为在window系统中,读取文件可以用反斜杠(\),但是在字符串中反斜杠被当作转义字符来使用,文件路径可能会被转义,所以需要在绝对文件路径前添加字符r,显示声明字符串不用转义。

# 反斜杠: \
with open(r'D:\Python\PycharmProjects\7\text_file\e_digits.txt', 'r') as f:
    print(f.read())

(2). 双反斜杠(\):也可以采用双反斜杠(\)的方式表示路径,此时不需要声明字符串。

# 双反斜杠: \\
with open('D:\\Python\\PycharmProjects\\7\\text_file\\e_digits.txt', 'r') as f:
    print(f.read())

(3).正斜杠(/):使用Linux路径表示方式是正斜杠(/),该方法也不需要声明字符串,在Linux及Windows操作系统下均可使用。

# 正斜杠: /
with open('D:/Python/PycharmProjects/7/text_file/e_digits.txt', 'r') as f:
    print(f.read())

6.2.4 创建含有文件数据的列表

  • for循环读取文件:程序运行结果会有很多空白行,空白行出现的原因是文档中每行末尾都有一个看不见的换行符,print函数也给打印出来的数据加上了一个换行符。
# for 循环来---读取
file_name = './text_file/e_point.txt'
with open(file_name, 'r') as f:
    for line_t in f:
        print(line_t)

运行结果如下:
在这里插入图片描述

  • rstrip函数(删除string字符串末尾的指定字符,默认为空格,从而可实现消除换行符)
  • lstrip函数(删除字符前面的指定字符)
  • strip函数(删除字符串首尾两端的指定字符)。
# 消除换行符
file_name = './text_file/e_point.txt'
with open(file_name, 'r') as f:
    for line_t in f:
        print(line_t.rstrip())

运行结果为:
在这里插入图片描述

  • read函数可以读取整个文件的内容,但是读取的内容将存储到一个字符串的变量中。
# read函数读取文件
file_name = './text_file/e_point.txt'
with open(file_name, 'r') as f:
    txts = f.read()
print(type(txts))
print(txts)

运行结果为:
在这里插入图片描述

  • 如果需要将读取的文件存储到一个列表里面,可以使用readliness函数:实现按行读取整个文件内容,然后将读取的内容存储到一个列表里面
# readlines 函数
with open('./text_file/e_point.txt') as f:
    txts = f.readlines()
print(type(txts))
print(txts)
for txt in txts:
    print(txt.strip())

运行结果为:
在这里插入图片描述

  • python还提供了readline函数,此函数可以实现每次读取文件的一行,通常也是将读取到的一行内容存储到一个字符串变量中,返回str类型
  • 因为readline函数实现的是逐行读取,所以读取整个文件时,速度会比readlines函数慢,所以仅当没有足够内存读取整个文件时才会使用readline函数。
# readline函数
with open('./text_file/e_point.txt') as f:
    txt = f.readline()
print(type(txt))
print(txt)

运行结果为:
在这里插入图片描述

6.2.5 任务实现

实现打开并读取整个文件Walden.txt。

with open('Walden.txt') as file_object:
    contects = file_object.readlines()
    print(contects)

运行结果为:
在这里插入图片描述

6.3 保存数据为CSV格式文件

任务描述
为实现数据写入写入文件,先使用Python创建列表数据,创建一个包含从1~100的平方的列表;在将数据保存为CSV格式,并命名。

6.3.1 写入.txt文件

  1. 数据写入文件
    在python的open函数中,标识符可指定文件打开模式。
r读文本文件
rb读二进制文件
w写文本文件
wb写二进制文件
  • 如果要写入的文件不存在,那么open函数将自动创建文件
  • 如果文件已经存在,那么写入模式写入文件时会先清空该文件(注意)
    -在写入文件的过程中,操作系统往往不会立刻把数据写入磁盘,而是放到内存中缓存起来。
  • 只有调用close函数时,操作系统才保证把没有写入的数据全部写入磁盘
# 写入文件
def file_see(file_name):
    with open(file_name) as f:
        txts = f.readlines()  # 将读取到文件内容存入列表中
    for txt in txts:
        print(txt.strip())  # 删除列表中每个元素的指定换行符
file_name = './text_file/words.txt'
print('文件的初始内容为:')
file_see(file_name)
f = open(file_name, 'w')
f.write('Hello, world!')
print('写完文件的内容(但还没有关闭文件):')
file_see(file_name)
f.close()
print('写完文件后的内容(已经完毕文件):')
file_see(file_name)

运行结果如下:
在这里插入图片描述

  • 如果需要将数值型数据写入文本文件, 必须先用str函数将数值型数据转换为字符串格式。
file_name = './text_file/data.txt'
f = open(file_name, 'w')
data = list(range(1, 11))
f.write(str(data))
f.close()
file_see(file_name)

运行结果为:
在这里插入图片描述

  • 写入多行数据的时候,write函数不会自动提娜佳换行符号,此时会出现几行数据挤在一起的情况。
  • 为了将行与行数据进行区分,需要在write语句内添加换行符号(\n)。
# 多行写入
file_name = './text_file/words.txt'
f = open(file_name, 'w')
f.write('Hello, world!')
f.write('I love Python!')
f.close()
print('写入多行数据:')
file_see(file_name)
# 多行写入,每行加\n
f = open(file_name, 'w')
f.write('Hello, world!\n')
f.write('I love Python!')
f.close()
print(r'写入多行语句(每行数据\n):')
file_see(file_name)

运行结果如下:
在这里插入图片描述

  1. 使用with语句写入.txt文件
    忘记调用close函数的后果可能是数据只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险。
# 用with语句写入.txt文件
file_name = './text_file/words.txt'
with open(file_name, 'w') as f:
    f.write('Hello, world!\n')
    f.write('I love Python!\n')
file_see(file_name)

运行结果为:
在这里插入图片描述
要写入特定编码的文本文件,需要给open函数传入encoding函数,将字符串自动转换成指定编码。open函数默认encoding参数为UTF-8。要读取非UTF-8编码的文本文件,例如读取GBK编码的文件,需要给open函数传入encoding参数。

# 写入文件
file_name = './text_file/words.txt'
f = open(file_name, 'w', encoding='gbk')
f.write('Hello,world!')
f.close()
file_see(file_name)

运行结果为:
在这里插入图片描述

  1. 对文件添加内容
    在编写代码时,可能需要给文件添加内容,但不覆盖文件原内容,这时候需要以附加模式(a)打开文件,此时写入的内容会附加到文件末尾,而不会覆盖原内容。
# 添加文件
file_name = './text_file/words.txt'
with open(file_name, 'a') as f:
    f.write("What's your favourite language?\n")
    f.write("My favorite language is Python too.\n")
file_see(file_name)

运行结果为:在这里插入图片描述

6.3.2 读写CSV文件

**逗号分隔值(Comma-Separated Values, CSV)**有时也称为字符分隔值,是一种通用的、相对简单的文件格式,常应用于在程序之间转移表格数据。
csv文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其他字符或字符串,最常见的分隔符是符号或制表符。
在编写程序时,可能需要将数据转移到CSV文件里面,在程序中,用命令import csv 可直接调用csv模块进行CSV文件的读写。

  1. 读取CSV数据
    (1)使用csv.reader函数,接收一个.csv文件,能返回一个生成器,从其中解析出csv的内容。以行为单位,利用csv.reader函数读取存储iris数据集的iris.csv文件的全部内容,并存储为列表。
# 读取iris数据
import csv
file_name = './text_file/iris.csv'
with open(file_name, 'r') as f:
    reader = csv.reader(f)
    iris = [iris_item for iris_item in reader]
print(iris)

运行结果为:

[['', 'Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width', 'Species'], 
['1', '5.1', '3.5', '1.4', '0.2', 'setosa'],
['2', '4.9', '3', '1.4', '0.2', 'setosa'], 
['3', '4.7', '3.2', '1.3', '0.2', 'setosa'],
['4', '4.6', '3.1', '1.5', '0.2', 'setosa'], 
['5', '5', '3.6', '1.4', '0.2', 'setosa'], 
···

(2) 使用csv.DictReader函数,该函数与csv.reader函数类似,接收一个可迭代的对象,能返回一个生成器,但是返回的每一个单元格都放在一个字典的值内,而字典的键则是这个单元格的标题(即列头)。

# csv.DictReader函数读取数据
import csv
file_name = './text_file/iris.csv'
with open(file_name, 'r') as f:
    reader = csv.DictReader(f)
    iris1 = [iris_item for iris_item in reader]
print(iris1)

运行结果为:

[OrderedDict([('', '1'), ('Sepal.Length', '5.1'), ('Sepal.Width', '3.5'), ('Petal.Length', '1.4'), ('Petal.Width', '0.2'), ('Species', 'setosa')]), OrderedDict([('', '2'), ('Sepal.Length', '4.9'), ('Sepal.Width', '3'), ('Petal.Length', '1.4'), ('Petal.Width', '0.2'), ('Species', 'setosa')]), OrderedDict([('', '3'), ('Sepal.Length', '4.7'), ('Sepal.Width', '3.2'), ('Petal.Length', '1.3'), ('Petal.Width', '0.2'), ('Species', 'setosa')]), OrderedDict([('', '4'), ('Sepal.Length', '4.6'), ('Sepal.Width', '3.1'), ('Petal.Length', '1.5'), ('Petal.Width', '0.2'), ('Species', 'setosa')]), 
···

如果用csv.DictReader函数读取CSV文件的某一列,则可以用列的标题(Sepal.Length)查询。

# 读取Name列的内容
file_name = './text_file/iris.csv'
with open(file_name, 'r') as f:
    reader = csv.DictReader(f)
    column = [iris_item['Sepal.Length'] for iris_item in reader]
print(column)

运行结果为:

['5.1', '4.9', '4.7', '4.6', '5', '5.4', '4.6', '5', '4.4', '4.9', '5.4', '4.8', '4.8', '4.3', '5.8', '5.7', '5.4', '5.1', '5.7', '5.1', '5.4', '5.1', '4.6', '5.1', '4.8', '5', '5', '5.2', '5.2', '4.7', '4.8', '5.4', 
···
  1. 写入.CSV文件
  • 对于列表形式的数据:除了csv.write函数外,还需要用到writerow函数将数据将数据逐行写入CSV文件。
# 写入列表数据
import csv
file_name = './text_file/test.csv'
with open(file_name, 'w', newline='') as f:
    with_csv = csv.writer(f)
    with_csv.writerow(iris)
  • 对于字典形式的数据,CSV模块提供了csv.DictWriter函数,除了提供open函数的参数外,还需要输入字典所有键的数据,然后通过writeheader函数在文件内添加标题,标题内容与键一致。最后使用writerows函数将字典内容写入文件。

6.4 认识os模块及shutil模块

任务描述
os模块和shutil模块是常用的文件模块。通过编写Python程序,即将squares.csv文件及程序文件移动到当前工作目录下的test_file文件夹里,并压缩成RAR格式的压缩包。

6.4.1 认识os模块

os模块是pythpn标准库中的一个用于访问操作系统的模块,包含普遍的操作系统功能,如复制、创建、修改、删除文件及文件夹。

  1. 查询操作系统
    os.name函数获取操作系统的名称
    如果是windows系统,则返回nt;
    如果是Linux/UNIX系统,则返回posix。
    os.sep函数查询相应操作系统下文件路径的分隔符
    Windows系统使用的是 \\ ,
    Linux系统中的路径分隔符是 /,
    而苹果Mac OS系统中的是 :。
    os.linesep函数:查询当前系统使用的终止符
    Windows系统使用 \r\n,
    Linux系统使用 \n,
    Mac系统使用 \r。
import os
print('操作系统名称为 ',  os.name)  # 查询操作系统名称
print('文件路径的分隔符为 ', os.sep)  # 查询文件路径的分隔符
print('当前系统使用的行终止符为 ', os.linesep)  # 查询当前系统使用的行终止符
  1. 查询工作路径
    os.getcwd函数:查询python的工作路径。
# 查询工作路径
path = os.getcwd()  # 查询当前公祖婆工作目录
print(path)
  1. 查询指定目录下的文件
    os.;istdir函数:查看指定目录下的所有文件和目录名。
# 查询指定目录下的文件
files = os.listdir('./text_file')
print(files)
  1. 删除文件
    os.remove函数:移除指定文件。
# 删除文件
os.remove('./text_file/test.csv')
print(os.listdir('./text_file'))
  1. 创建与删除目录
    os.mkdir函数:创建目录。
    os.rmdir函数:删除指定路径的文件夹。但是这个文件夹必须是空的,不包含任何文件或子文件夹。
# 创建与删除目录
file_name = './text_file/my_file'
os.mkdir(file_name)  # 创建文件夹
print(os.listdir('./text_file'))
os.rmdir(file_name)  # 删除文件夹
print(os.listdir('./text_file'))

运行结果为:
在这里插入图片描述

  1. 对文件路径的操作
    os模块里面含有os.path相关的函数,提供了相应的对文件路径的操作。
os.path.isdir(name)判断name是不是目录,不是目录就返回False
os.path.isfile(name)判断name这个文件是否存在,不存在就返回False
os.path.exists(name)判断是否存在文件或目录name
os.path.getsize(name)获得文件大小,如果name是目录,则返回OL
os.path.abspath(name)获得绝对路径
os.path.isabs()判断是否为绝对路径
os.path.normpath(path)规范path字符串形式
os.path.split(name)分隔文件名与目录(事实上,如果完全使用目录,它也会将最后一个目录作为文件名而使其分隔开,同时它不会判断文件或目是否存在)
os.path.splitext()分离文件名和扩展名
os.path.join(path,name)连接目录与文件名或目录
os.path.basename(path)返回文件名
os.path.dirname(path)返回文件路径
os.path.split()返回一个路径下的目录名或文件名
os.path.isfile()检验给出的路径是否是一个文件
os.path.isdir()检验给出的路径是否是一个目录
os.path.existe()检验给出的路径是否真的存在
# 对文件路径的操作
import os
system = os.name
if system == 'nt':
    print('当前的操作系统是Windows。')
else:
    print('当前二点操作系统是Linux。')
print('本系统标识路径的分隔符是:' + os.sep)
print('本系统中使用的行终止符为:', [os.linesep])

path = os.getcwd()  # 获得当前目录
print('运行本程序所在目录是:' + path)
print('计算机的Path环境变量如下图所示: \n' + os.getenv('Path'))

os.mkdir('test')  # 创建空文件夹
print('当前文件夹中文件由: \n', os.listdir(path))
if os.path.exists('test'):
    os.rmdir('test')
    print('文件夹删除成功')
else:
    print('文件夹不存哎')
print('删除后的结果为:\n', os.listdir(path))

filepath1 = 'Python7'
if os.path.isfile(filepath1):
    print(filepath1 + '是一个文件。')
else:
    print(filepath1 + '不是一个文件。')

name = 'Ch7.py'
print('本程序的大小为:', os.path.getsize(name))
name = os.path.abspath(name)
print('本程序的绝对路径是' + name)
print('本程序的文件名分别为:', os.path.split(name))

files = os.path.splitext(name)
print('本程序的扩展为:' + files[1])
print('本程序的文件名为:' + os.path.basename(name))
print('本程序的路径为 ' + os.path.dirname(name))

运行结果如下:

当前的操作系统是Windows。
本系统标识路径的分隔符是:\
本系统中使用的行终止符为: ['\r\n']
运行本程序所在目录是:D:\Python\PycharmProjects\7
计算机的Path环境变量如下图所示: 
C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\dotnet\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\studio\tools;C:\studio\platform-tools;C:\Program Files (x86)\Microsoft SQL Server\150\DTS\Binn\;C:\Program Files\MySQL\MySQL Utilities 1.6\;C:\Users\觉主有点迷\AppData\Local\Programs\Python\Python36\Scripts\;C:\Users\觉主有点迷\AppData\Local\Programs\Python\Python36\;C:\Users\觉主有点迷\AppData\Local\Microsoft\WindowsApps;;C:\Program Files (x86)\SSH Communications Security\SSH Secure Shell;D:\Bandizip\

在这里插入图片描述

6.4.2 认识shutil模块

os模块不仅提供了新建文件、删除文件、查看文件属性的操作功能,还提供了对文件路径的操作功能。但是,对于移动、复制、打包、压缩、解压文件及文件夹等操作,os模块没有提供相关的函数,此时需要用到shutil模块。
shutil模块是对os模块中文件操作的补充,是Python自带的关于文件、文件夹、压缩文件的高层次的操作工具、类似于高级API。

  1. 移动文件或文件夹
    shutil.move函数:将指定的文件或文件移动到目标路径下,返回值是移动后的文件绝对路径字符串。
    (1)如果目标路径指向一个文件夹,那么指定文件将移动到目标 路径指向的文件夹中,并且保持原有名字。
    (2)如果目标路径指向的文件夹中已经存在了同名文件,那么该文件将被重写。
    (3)如果目标文件指向一个具体的文件,那么指定的文件在移动后将被重命名。
    (注意)目标路径下的文件夹必须是已经存在的,否则程序会返回错误。
# 移动文件
import shutil
shutil.move('./text_file/e_point.txt', './data')

shutil.move('./text_file/e_point.txt', './data/point.txt')  # 重命名

  1. 复制文件
    shutil.copyfile(src,dst)函数:可以从src文件复制内容(不包含元数据)到dst文件。**dst必须是完整的目标文件名。**返回值是复制后的文件绝对路径字符串。
    (1)如果src和dst是同一文件,就会引发错误shutil.Error。dst文件必须是可写的,否则将会引发IOError。
    (2)如果dst文件已经存在,则它会被替换。
    (3)对于特殊文件,例如字符或块设备文件和管道不能使用此功能,因为copfile会打开读取文件。
    shutil.copy(src,dst)函数可以复制文件src到文件或目录dst。如果dst是目录,则会使用src相同的文件名创建(或覆盖),文件权限也会复制返回值是复制后的文件绝对路径字符串。

shutil.copytree函数用于进行目录的复制。该函数返回结果为复制后目录的路径。“程序”文件夹下的目录将复制到test文件夹内。需要注意的是,test文件夹必须事先不存在。

import shutil
# 复制文件
shutil.copyfile('Ch7.py', 'Ch7.py.copy')
# 跨路径复制文件
shutil.copy('./text_file/data.txt', './data/data.txt')
# 复制text_file文件夹下的目录到data1文件夹内
shutil.copytree('./text_file', './data1')
  1. 永久删除文件和文件夹
    os.unlink函数:会删除指定的文件。
    os.rmdir函数:会删除路径指定的文件夹,但是这个文件夹必须是空的,不能包含任何文件或子文件夹。
    shutil.rmtree函数:可以删除路径指定的文件夹,并且这个文件夹里面的所有文件和子文件夹都会被删除。
    因为涉及对文件与文件夹的永久删除,因此对以上函数的使用必须要非常谨慎。
  2. 压缩与解压文件
base_name压缩包 的文件名,也可以是压缩包的路径,是文件名时,则保存至当前目录,否则保存至指定路径
format压缩包种类,可以是zip、tar、bztar、gztar
root_dir要压缩的文件夹路径(默认当前目录)
owner用户,默认当前用户
group组,默认当前组
logger用于记录日志,通常是logging.Logger对象

6.4.3 任务实现

通过编写Python程序,将squares.csv文件及程序文件移动到当前工作目录下的test_file文件夹里,需要先把两个文件从把不同路径下复制到当前文件目录下的test_file文件夹里,然后直接调用函数将test_file文件夹压缩成RAR格式的压缩包。

import os
import shutil
file_name1 = './text_file/squares.csv'  # csv文件
file_name2 = './test7.4.py'  # 程序文件
out_file = os.getcwd() + '\\test'   # 目标路径:当前工作目录+test文件夹
os.mkdir(out_file)  # 创建文件夹
shutil.copy(file_name1, out_file)  # 复制csv文件
shutil.copy(file_name2, out_file)  # 复制程序文件
shutil.make_archive('test7.4', 'zip', root_dir=out_file)  # 压缩文件
  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值