2022年 11月 9日

Python程序设计

一.Python语言概述

1.面向对象的解释型程序设计语言

2.自由软件

3.可以移植到多平台

4.设计哲学是“优雅”、“明确”、“简单

1.1编程方式

1.1.1交互式

在python自带的idle中进行编程,每次只执行一段代码

1.1.2.文件式

在idle中新建一个py文件在文件中编写代码,保存执行之后,再run module

 

 

1.2标识符和变量

标识符是指用来标识某个实体的一个符号,在不同的应用环境下有不同的含义。

标识符由字母、下划线和数字组成,且不能以数字开头。不能属于关键字,且标识符区分大小写。

1.2.1python的关键字

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

1.2.2常量和变量

常量就是不能改变的量

比如3.1415926就是一个常量

变量就是值可以改变的量,变量名则是程序为了方便的引用内存中的值而为它取的名称。

Python变量名是大小写敏感的

注意:不要使用python的内置函数作为变量名,否则该内置函数将无法使用,如果想要恢复,使用del函数

Python变量有一个非常重要的性质:变量是将名字和对象进行关联

赋值操作并不会实际复制值,它只是为数据对象取个相关的名字。

id()是Python的内置函数,可以显示对象的地址

小整数Python将数值放在数组中,提高效率,大整数或其它类型是重新分配内存空间

1.3输入函数和输出函数

1.3.1输入函数input()

input函数在python中是一个内建函数,可以实现从标准输入(键盘)中读入一个字符串。

若要输入其它数据类型的数据

like
a=int(input())

要输入多个值,在同一行实现

a,b=input().split()

在输入时给与提示

n=int(input("请输入一个整型值N:"))

1.3.2输出函数print

语法 print(要输出的值)默认换行

若有多个值中间用逗号隔开

for i in range(5)
    print(i)
//结果换行输出

如果不想换行

for i in range(5)
    print(i.end='')

例子1 计算三角形面积

import math
a=int(input())
b=int(input())
c=int(input())
s=(a+b+c)/2
area=math.sqrt(s*(s-a)*(s-b)*(s-c))
print("三角形的边长:",a,b,c,end=' ')
print("三角形的面积:",area)

例子2 绘画五角星

import turtle
turtle.forward(200)
turtle.right(144)
turtle.forward(200)
turtle.right(144)
turtle.forward(200)
turtle.right(144)
turtle.forward(200)
turtle.right(144)
turtle.forward(200)
turtle.done()

二.用Python语言编写程序

2.1 数字类型

整数(int)取值范围一般无限制

进制 前导符 示例 十进制
二进制 0b或0B 0b10 2
八进制 0o或0O 0o10 8
十六进制 0x或0X 0x10 16

浮点数(float)

取值范围和精度都有限制

表示方式

1.23*10^9 1.23e9

浮点数运算存在的问题

浮点数运算存在不确定尾数,有误差

采用round函数消除尾数

复数(complex)

由实部和虚部组成,虚部用j表示

例如

2+3j

表示方法

算术运算符

运算符 说明 示例 运算结果
+ 加法 5+10 15
减法 100-5 95
* 乘法 8*9 72
/ 浮点数除法 100/5 20.0
// 整数除法 100//5 20
% 模(求余) 9%4 1
** 2**3 8

整数除法向左取整(即向数轴左边取整)

数学库(math)

函数或常数 功能
e 自然常数
pi 圆周率
log(x,[base]) 返回以base为底的对数,缺省为e
pow(x,y) 返回x的y次方
sqrt(x) 返回x的平方根
fabs(x) 返回x的绝对值
round(x[,n]) 返回浮点数x的四舍五入值,n代表舍入到小数点后的位置
divmod(x,y) 返回x和y的商和余数

2.2 字符串

字符串是以引号括起来的任意文本,是一个有序序列

单引号双引号表示单行文本,三引号表示多行文本

转义字符

转义字符 说明
\n 回车符,将光标移到下一行开头。
\r 回车符,将光标移到本行开头。
\t 水平制表符,也即Tab键,一般相当于四个空格
\b 退格(Backspace),将光标位置移到前一列。
\ 反斜线
单引号
双引号
\ *在字符串行尾,即一行未完,转到下一行继续写

字符串运算符

运算符 功能 示例
+ 连接字符串 ‘hello’+‘world’ ‘helloworld’
* 复制字符串 ‘ab’*3 ‘ababab’

字符串切片

字符串是一个有序序列,可以是正向递增也可以是反向递减:

0 1 2 3 4 5 6 7
a b c d e f g h
-8 -7 -6 -5 -4 -3 -2 -1

索引:在[]中给出序号

切片:在[]中给出序号范围

布尔值

布尔值:True、False

逻辑运算和关系运算的结果是布尔值

关系运算符

运算符 表达式 含义 实例 结果
== x==y x等于y ‘ABCD’==’ABCDEF’ False
!= x!=y x不等于y ‘ABCD’!=’abcd’ True
> x>y x大于y ‘ABC’>”ABD” False
>= x>=y x大于等于y 123>=23 True
< x<y x小于y ‘ABC'<‘DEF’ True
<= x<=y x小于等于y ‘123’<=’23’ True

注意:字符串和数字不能进行比较

关系运算符实例

1<3>5
等价于
1<3 and 3<5 

逻辑运算符

and运算

逻辑量1 逻辑量2 结果
False False False
False True False
True False False
True0 True True

只要逻辑量中有一个是False,则结果也为False

or运算符

逻辑量1 逻辑量2 结果
False False False
False True True
True False True
True0 True True

not运算

逻辑量 结果
False True
True False

示例

 

优先级和结和性实例

2.3内置转换函数

函数名 含义
bool() 根据传入的参数的逻辑值创建一个新的布尔值
int() 根据传入的参数创建一个新的整数
float() 根据传入的参数创建一个新的浮点数
complex() 根据传入的参数创建一个新的复数
str() 创建一个字符串
ord() 返回Unicode字符对应的整数
chr() 返回帧数所对应的Unicode字符
bin() 将整数转换成2进制字符串
oct() 将整数转换成8进制字符串
hex() 将整数转换成16进制字符串
list() 根据传入的参数创建一个新的列表

类型转换函数实例

基本格式:int(x[,base=10])

ord函数和chr函数

 

bin函数,oct函数,hex函数

2.4语句

2.4.1赋值语句

基本形式是“变量=值”的形式

例:基本赋值语句

2.4.2 if语句

分支语句:if语句

if 逻辑表达式:
    语句块1
else:
    语句块2

例:判断奇偶数

x=int(input())
if x%2==0:
    print("偶数")
else:
    print("奇数")

为鼓励居民节约用水,自来水公司采取按用水阶梯式计价的办法,居民应交水费y(元)与月用水量x(吨)相关:

当x不超过15吨时,y=4x/3;超过后,y=2.5x-17.5,小数部分保留2位。请编写程序实现水费的计算。

x=float(input())
if x<=15:
    y=4*x/3
else:
    y=2.5*x-17.5
print("{:.2f}".format(y))

2.4.3 for语句

循环语句:for语句

for variable in 列表:
​
    语句块     

例:遍历列表

for i in [1,2,3,4]:
    print(i,end=" ")
for i in [1,2,3,4]:
    print(i)
    i=i+2
    print("i+2之后的值")
    print(i)

结果展示

range函数

range(start,stop,step).

start:计数从start开始。默认是从0开始

例如 range(5)等价于range(0,5)

stop:计数到stop结束,但不包括stop。

例如:list(range(0,5))是[0,1,2,3,4]没有5

step:步长,默认为1.

例如:range(0,5)等价于range(0,5,1)

例:

输入n(n>=10),求1+2+3+…+n之和

n=int(input())
s=sum(list(range(n+1)))
print(s)

例:输入n(n>=5)求n!

n=int(input())
factor=list(range(1,n+1))
f=1
for i in factor:
    f=f*i
print(f)

2.4.4 列表推导式

列表是Python最常用数据类型之一:

由零个或多个元素组成,元素之间用逗号分开,整个列表被方括号所包裹

元素类型可以相同也可以不同

通过序号可以引用列表中的元素

支持加法、乘法、比较、索引、切片操作等等

列表推导式(又称列表解析式)提供一种简明扼要的方法创建列表

它可以将循环和条件判断结合,从而避免语法冗长的代码,同时提高程序性能

基本格式:

[expression for item iterable]

 

带条件的列表解析

 

列表推导式应用

求1+1/2+…+1/20之和

a=sum([1/i for i in range(1,21)])
print(a)

求1-1/2+1/3-1/4+…之前n项和(n>=10)

n=int(input())
a=sum([1/i if i%2==1 else -1/i for i in range(1,n+1)])
print(a)

求6+66+666+…+66666….6666

n=int(input())
print(sum([int('6'*i) for i in range(1,n+1)]))

2.5 格式化输出

例 华氏-摄氏温度转换表

输入2个正整数lower和upper(lower<upper<100),输出一张取值范围为[lower,upper]、且每次增加2华氏度的华氏-摄氏温度转换表,结果小数部分保留一位。温度转换的计算公式:C=5*(F-32)/9 其中:C表示摄氏温度,F表示华氏温度

lower,upper =input().split()
lower,upper=int(lower),int(upper)
for i in range(lower,upper+1,2):
    print(i,"{:.1f}".format(5*(i-32)/9))

format()函数

基本格式:str.format()

0和1表示format函数中的第一和第二个参数

.2f表示小数部分保留两位,四舍五入

课后题:求交错序列的前N项和

输入正整数N,输出序列和,结果保留三位小数

1-2/3+3/5-4/7+5/9-6/11+…+前N项

解法一

n=int(input())
result=0
for i in range(1,n+1):
    if i%2==1:
        result=result+i/(2*i-1)
    else:
        
        result=result-i/(2*i-1)
print("{:.3f}".format(result))

解法二

n=int(input())
alist=[i/(2*i-1) if i%2==1 else -i/(2*i-1) for i in range(1,n+1)]
result=sum(alist)
print("{:.3f}".format(result))

三.使用字符串、列表、元组

3.1序列的访问及运算符

3.1.1序列类型容器

 

示例:

 

3.1.2取单个元素

注意:字符串根据下标值不能随便修改

 

3.1.3 字符串和列表切片

示例:取出身份证号中的出生日期

sfh =input()
sr=sfh[6:14]
print(sr)

示例:取出某一季度的月份

month=[‘一’,‘二’,”三”,”四”,”五”,”六”,”七”,”八”,”九”,”十”,”十一”,”十二”]

示例:取出温度的数值

示例:取后面的字符

3.1.4序列的函数

len()函数:表示有多少个个数

min取最小值 max取最大值

 

3.2使用字符串

3.2.1 字符串再认识

当字符串中包含单引号时,可将外部的单引号换成双引号。需要使用双引号就在外面使用三引号或者使用单引号,用三引号表示多行元素 r表示保留之前的形式

 

 

3.2.2字符串函数

点函数

lower():将字符串中的大写字母全部变为小写

find():找到子字符所在的位置

count():统计某一字符的次数

strip():将两边的空格去掉

rstrip():将右边的空格去掉

lstrip():将左边的空格去掉

replace():替换一串字符串为其它内容

 

3.2.3字符串和数字之间的转换

 

3.3.1基本的列表操作

列表中的元素可以是不同的类型

列表是序列类型,之前的所有序列操作对于列表来说都是成立的。

list()函数可以将字符串转换成列表

列表的元素也可以是列表,就称这样的表为广义表

如果将两个列表赋值,改变其中的一个元素,另一个列表中元素也会改变

列表变量赋值之后指向的是同一个地址

 

列表只是管理者并不是拥有者

如果想另外设置一个不同地址的列表,就需要将列表做切片,比如a1=a2[:]

切片的列表内容个数也可以不相同

del 可以删除列表的某一个元素 del 元素变量

 

 

3.3.2 列表的函数

列表.append()往一个列表增加一个元素

列表.extend([7,8,9])列表拼接列表

列表.insert(“位置”,“元素”)

列表.remove(元素) 只删除第一个元素

列表.pop() 最后一个元素

列表.pop(位置) 删除第几个位置的元素

列表.reverse() 颠倒列表中元素的顺序

列表.index(“元素”) 查找某个元素所在的位置

3.3.3 列表和字符串之间的操作

split()函数 :以空格作为分隔,当然也可以自带参数

join将列表连接成字符串

 

3.4 元组的使用

元组和列表几乎没有区别,唯一的区别是元组是由小括号组成,元组是一种不可修改的数据,无法进行元素的赋值,一般的内置函数列表与元组相同唯一不同的是,不能使用能改变元素的函数。

为什么要使用元组,是想让给出的数据不能够被改变

使用tuple函数,用逗号隔开的都是元组

 

3.5 Python随机模块(随机函数库)

将列表从小到大排序 :sort函数

将列表顺序打乱 导入random库

random.shuffle 将列表顺序打乱

random.choice 随机选择一个元素

随机数是平均分布

random.seed(x) 根据x的值返回确定的数

 

四.条件循环和其它语句

4.1 条件语句

x=int(input())
if x>0:
    print("POS")
else:
    print("NEG")

嵌套的if语句

x,y=map(int,input().split())#嵌套的if语句
if x>y:
    if x>0:
        print(x)
    else:
        print(-x)
else:
    print(y)

if表示数学的分段函数

x=int(input())
y=0
if x>0:
    y=1
else :
    if x==0:
        y=0
    else:
        y=2*x+100
print(y)
x=int(input())
y=0
if x>0:
    y=1
elif x==0:
    y=0
else:
    y=2*x+100
print(y)

4.2 while 循环

s=0
cnt=0
while True:
    x=int(input())
    if x!=-1:
        s+=x
        cnt+=1
    else:
        print("结束")
        break
if cnt>0:
    print(s/cnt)
else:
    print(0)

4.3 for循环

for

else

表示如果for正常执行结束,会再执行else否则就不执行else

示例:判断素数

x=int(input())
isprime=True
for k in range(2,x):
    if x%k==0:
        isprime=False
        print("is not prime")
        break
else:
    print("is prime")

求两个数之间的素数的和和素数的个数

m,n=map(int,input().split())
s=0
cnt=0
for x in range(m,n+1):
    for k in range(2,x):
        if x % k ==0:
            break
    else:
        cnt+=1
        s+=x
print(cnt,s)

4.4 range函数

产生的是列表数列

有两个参数的话表示的是从哪里开始到哪里结束

range的第三个参数表示的是步长

第三个参数要是负数,则可以从大到小排列

4.5异常

4.5.1 异常处理

异常保护机制

语法

try:

执行某语句

except:

发生错误时执行此语句

 

else执行是try中没有异常就执行else

finally是无论是否有异常都会执行

示例

x=int(input())
t=[1,2,3,4,5]
try:
    print(t[x])
    print("hello")
except:
    print("x is not a valid index")
else:
    print("nothing")
finally:
    print("anyway")

输入2时结果

输入5时

 

x=int(input())
y=int(input())
try:
    result=x/y
except ZeroDivisionError:
    print("division by zero!")
else:
    print("result is",result)
finally:
    print("executing finally clause")

 

python常见的标准异常

AssertionError 断言语句(assert)失败 AttributeError 尝试访问未知的对象属性 EOFError 用户输入文件末尾标志EOF(Ctrl+d) FloatingPointError 浮点计算错误 GeneratorExit generator.close()方法被调用的时候 ImportError 导入模块失败的时候 IndexError 索引超出序列的范围 KeyError 字典中查找一个不存在的关键字 KeyboardInterrupt 用户输入中断键(Ctrl+c) MemoryError 内存溢出(可通过删除对象释放内存) NameError 尝试访问一个不存在的变量 NotImplementedError 尚未实现的方法 OSError 操作系统产生的异常(例如打开一个不存在的文件) OverflowError 数值运算超出最大限制 ReferenceError 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 RuntimeError 一般的运行时错误 StopIteration 迭代器没有更多的值 SyntaxError Python的语法错误 IndentationError 缩进错误 TabError Tab和空格混合使用 SystemError Python编译器系统错误 SystemExit Python编译器进程被关闭 TypeError 不同类型间的无效操作 UnboundLocalError 访问一个未初始化的本地变量(NameError的子类) UnicodeError Unicode相关的错误(ValueError的子类) UnicodeEncodeError Unicode编码时的错误(UnicodeError的子类) UnicodeDecodeError Unicode解码时的错误(UnicodeError的子类) UnicodeTranslateError Unicode转换时的错误(UnicodeError的子类) ValueError 传入无效的参数 ZeroDivisionError 除数为零

五.集合与字典

5.1集合

特点:元素无序(是指无法指定元素在集合中的位置)、无重复元素

集合的自变量表示是大括号

往集合里加数 用add函数

可以将一个列表通过set函数转换成集合

空的{}表示的是字典

而要表示空集合要用set()

 

A集合小于B集合,表示A集合是B集合的真子集

A集合小于等于B集合,表示A集合是B的子集

A|B:取并集

A&B :A与B取交集

A^B:对称差运算

A-B: 差值运算

 

 

 

5.2字典

{‘key’:value}键值对

想要添加元素,直接赋值

5.2.1删除条目

用del语句,删除指定键的字典条目。

del score[‘张三’]

注:如果指定键不存在,则会抛出KeyError异常

min,max分别获得最大最小的key

d.get()也可以获取某一具体的值

 

 

示例:统计输入的数字的个数

d={}
while True:
    x=int(input())
    if x!=-1:
        d[x]=d.get(x,0)+1#如果存在就+1
        # if x in d:
        #     d[x]+=1
        # else:
        #     d[x]=1
    else:
        break
print(d)

5.3集合与字典的应用

示例 :处理学生成绩

输入:(以END结束)

学生的学号,姓名

学生的学号,课程,成绩

输出:

表头 学号 姓名 课程1 课程2… 平均分

内容 <学号><姓名>< 成绩1><成绩2><平均分>

数据结构

字典 stuid,键是学号,值是姓名

score,键是课程,值是成绩

stuscore,键是学号,值是字典score

集合course,课程

 

stuid={}
stuscore={}
score={}
course=set()
while True:
    line=input()
    if line=='END':
        break
    else:
        s=line.split(',')
        if len(s)==2:
            stuid[s[0]]=s[1]
        elif len(s)==3:
            score=stuscore.get(s[0],{})
            score[s[1]]=int(s[2])
            stuscore[s[0]]=score
            course.add(s[1])
​
courename=list(course)
print('学号'+','+'姓名',end='')
for name in courename:
    print(','+name,end='')
print(','+'平均分',end='')
print()
for id in stuid.keys():
    print(id+','+stuid[id],end='')
    score=stuscore[id]
    sum=0
    cnt=0
    for name in courename:
        print(',',end='')
        if name in score:
            print(score[name],end="")
            sum+=int(score[name])
            cnt+=1
    print(","+str(int(sum/cnt)))

验证

 

六.函数

6.1函数定义与调用过程

函数是重用的程序段。它们允许你给一段语句命名一个名字,这是函数定义。

你可以在你的程序的任何地方使用这个名称运行这个语句块,这是函数调用

内置函数不用定义,直接调用。

len(“hello”)

5

自定义函数语法格式:

def 函数名(参数表):

函数体

如要定义函数: y=x^2+1

def f(x):

value=x**2+1

return value

n=int(input())

y=f(n)

print(y)

求斐波那契数列的前n项

def fibs(n):
    result=[1,1]
    for i in range(n-2):
        result.append(result[-2]+result[-1])
    return result
print(fibs(5))

 

注意:函数要先定义再使用

匿名函数–lambda表达式

函数定义的另一种方法是用lambda表达式,它定义了一个匿名函数。lambda的一般形式是关键字lambda后面跟一个或多个参数,紧跟一个冒号,后面是一个表达式。作为表达式,lambda返回一个值。lambda用来编写简单的函数,而def用来处理更强大任务的函数。

g=lambda x,y,z:x+y+z

#把lambda定义的匿名函数赋给函数g

print(g(1,4,5))

练习:定义函数y=sin(x)+1

import math
def f(x):
    y=math.sin(x)+1
    return y
y=f(3.5)
print(y)

6.2函数参数

函数定义时的参数称为形参,这些参数就像变量一样

参数在函数定义的圆括号内指定,用逗号分割。

当我们调用函数的时候,函数中的参数值称为实参

函数形参取得的值是你调用函数时提供的实参。

6.2.1位置参数(按照先后顺序赋值)

Python处理参数的方式要比其他语言更加灵活。其中,最熟悉的参数类型是位置参数,传入参数的值是按照顺序依次赋值给形参,

from math import sqrt
def dis(x1,y1,x2,y2):#求平面上两点距离
    print("x1={},y1={},x2={},y2={}".format(x1,y1,x2,y2))
    return sqrt((x1-x2)**2+(y1-y2)**2)
print(dis(1,3,4,5))

6.2.2关键字参数

为了避免位置参数严格的位置要求,调用参数时可以指定对应形式参数的名字,这是关键字参数,它甚至可以采用与函数定义时不同的顺序。

from math import sqrt
def dis(x1,y1,x2,y2):#求平面上两点距离
    print("x1={},y1={},x2={},y2={}".format(x1,y1,x2,y2))
    return sqrt((x1-x2)**2+(y1-y2)**2)
print(dis(x1=1,y2=3,y1=4,x2=5))

6.2.3 位置参数和关键字参数混合

如果同时出现两种参数形式,首先应该写的是位置参数,然后是关键字参数。

from math import sqrt
def dis(x1,y1,x2,y2):#求平面上两点距离
    print("x1={},y1={},x2={},y2={}".format(x1,y1,x2,y2))
    return sqrt((x1-x2)**2+(y1-y2)**2)
print(dis(1,3,y2=5,x2=4))

6.2.4 默认值参数

当调用方没有提供对应形式参数的值时,你可以指定默认形式参数值。如果你提供实参,在调用时会代替默认值

from math import sqrt
def dis(x1,y1,x2,y2=5):#求平面上两点距离
    print("x1={},y1={},x2={},y2={}".format(x1,y1,x2,y2))
    return sqrt((x1-x2)**2+(y1-y2)**2)
print(dis(1,3,4))

默认参数值在函数对象被创建时计算

def init(arg,result=[]):
    result.append(arg)
    print(result)
init('a')
init('b')
init(1,[1])

 

6.2.5数量可变参数

当函数参数数目不确定时,星号将一组可变数量的位置参数集合成参数值的元组

def countnum(a,*b):#计算参数个数
    print(b)
    print(len(b)+1)
countnum(3,7,9)
countnum(5,8,1,6,89)

 

收集参数到字典中–**

def countnum(a,**d):#计算参数个数
    print(d)
    print(len(d)+1)
countnum(3,x1=9,x2=1,x3=6,x4=89)

 

print函数的完整表示

print(*obkect,sep=" ",end="\n",file=sys.stdout)
object:输出参数,可变数量
缺省值参数
sep="":输出分割符
end="\n":输出函数结束换行
file=sys.stdout:输出到屏幕缺省

实参拆包

 

*或**都是加在形参的前面,表示不定长参数,分别用来接收不带变量名的多余参数和带有变量名的多余参数,分别将它们以元组和字典的形式接收进函数

当在实参的前面加上星号,就意味着拆包。*表示将序列拆成一个个单独的实参。

可变对象和不可变对象当参数

可变对象和不可变对象当参数,效果可能是不同的

当实参是不可变对象时,形参值改变不会影响实参!

当实参时可变对象时,形参值改变可能会影响实参!

例子1

def change(a,b):
    a=3
    b=b+a
x,y=7,9
change(x,y)
print(x,y)

 

def change1(a):
    a[0]=3
    a[1]=11+a[0]
l=[7,9]
change1(l)
print(l)

 

6.3函数返回值

函数用return语句返回值。

return后面的表达式的值就成为这次函数调用的返回值。

如函数没有用return语句返回,这时函数返回的值为None;如果return后面没有表达式,调用的返回值也为None。

None是Python中一个特殊的值,虽然它不表示任何数据,但仍然具有重要的作用。

示例:求整数M和N区间内素数的个数并对它们求和(2<=M<N)

def isprime(i):
    for k in range(2,i):
        if i%k==0:
            return False
    return True
m,n=input().split()
m,n=int(m),int(n)
p=[i for i in range(m,n+1) if isprime(i)]
print(len(p),sum(p))

 

返回值是函数

def test(par):
    return par
def test1():
    return 1000
def test2(par):
    return 2000
def f(x):
    return {
        'a':test,
        'b':test1,
    }.get(x,test2)
print(f('a')(100))
print(f(4)(100))

 

集合add函数返回值是None

按列表原来的次序输出非重复元素

l=[2,3,5,8,3,6,8,6,5]
seen=set() #集合存放已在列表中的元素
l1=[i for i in l if i not in seen and not seen.add(i)]
print(l1)

 

如果将程序换位

l=[2,3,5,8,3,6,8,6,5]
seen=set() #集合存放已在列表中的元素
l1=[i for i in l if not seen.add(i) and i not in seen]
print(l1)
​

l1=[i for i in l if not seen.add(i) and i not in seen]中先执行 add 将没有的函数添加到集合中并且 为True 但是 此时后面的判断条件就为False了

6.4命名空间和作用域

1.变量可被访问范围称为变量的作用域,也称为变量命名空间或变量名字空间。Python程序用命名空间区分不同空间的相同名字。

2.Python解释器启动时建立一个全局命名空间,全局变量就放在这个空间,还建立内置命名空间(built-in namespace).记录所有标准常量名、标准函数名等。在全局命名空间中定义的变量是全局变量。

3.每一个函数定义自己的命名空间,函数内部定义的变量是局部变量。如果在一个函数中定义一个变量x,在另外一个函数中也定义x变量,因为是在不同的命名空间,所以两者指代的是不同的变量。可以通过多种方式获取其他命名空间的变量。

6.4.1全局命名空间

 

 

6.4.2局部变量与全局变量

Python语言规定赋值即定义。“var=1”赋值语句定义了变量“var”并赋值为1

全局变量:定义在函数外,作用域是整个程序。

局部变量:定义在函数内,作用域是函数内部。形参也是局部变量

6.4.3局部变量和全局变量同名

def scope():
    var1=1
    print("函数内部打印结果")
    print(var1,var2)
var1=10
var2=20
scope()
print("函数外部打印结果")
print(var1,var2)

 

6.4.4global关键字

如希望在函数中使用全局变量,而不是创建局部变量,需要用global关键字声明

def scope():
    global var1
    var1=1
    print("函数内部打印结果")
    print(var1,var2)
var1=10
var2=20
scope()
print("函数外部打印结果")
print(var1,var2)

 

练习

x=100
def f():
    y=x #x未定义出错
    x=0
    print(x,y)
f()

纠正

x=100
def f():
    x=0
    y = x
    print(x,y)
f()

6.5递归

函数调用自身的编程技巧称为递归

递归做为一种算法在程序设计中广泛应用。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,大大减少了程序的代码量。

递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要终止条件和递归条件。当终止条件不满足时,递归前进;当终止条件满足时,递归返回。编写递归函数时,必须告诉它何时停止递归,从而避免形成无限循环。

斐波那契数列递归定义

斐波那契数列是一个经常使用递归方式定义的序列

fib(0)=1 n=0 (1)

fib(1)=1 n=1 (2)

fib(n)=fib(n-1)+fib(n-2) n>=2 (3)

公式(1)和公式(2)是递归终止条件,公式(3)是递归式

斐波那契数列递归程序

def fib(n):#假定n是正整数,返回第n+1个斐波那契数
    if n==0 or n==1:
        return 1
    else:
        return fib(n-1)+fib(n-2)
print(fib(4))

改进斐波那契数列递归程序

pre={0:1,1:1}
def fib(n):
    if n in pre:#可以用in检查字典中是否有n这个关键字
        return pre[n]
    else:
        newvalue=fib(n-1)+fib(n-2)
        pre[n]=newvalue#增加字典的条目
        return newvalue
print(fib(100))

 

求嵌套列表中数字元素和(返回多个值)

def flatten(items):
    lst=[]
    for x in items:
        if isinstance(x,(list,tuple)) and not isinstance(x,str):
            for element in flatten(x):
                lst.append(element)
        else:
            if type(x)!=str:
                lst.append(x)
    return lst
items=[11,2,[3,7],(68,-1),"123",9]
l=[i for i in flatten(items)]
print(l)
print(sum(l))

 

6.6内置函数

6.6.1 sorted函数

sorted函数对字符串,列表,元组,字典对象进行排序操作。

sort是应用在list上的方法,sorted可以对更多的数据类型进行操作。

即便都是对列表操作,list的sort方法返回的是对已经存在的列表进行操作,而内建函数sorted返回的是一个新的list,而不是在原来的基础上进行的操作。

sorted函数语法

stored(iterable[,key[,reverse]])

iterable –序列,如字符串,列表,元组等。

key -函数,缺省为空

reverse –排序规则

reverse = True 降序,reverse = False 升序(默认)

示例:

students=[('张三',89,15),("李四",80,16),("王五",85,17)]#第二个分量是成绩,第三个分量是年龄
print("按年龄从小到大排序")
print(sorted(students,key=lambda s:s[2])) #按年龄从小到大排序
print("按成绩从大到小排序")
print(sorted(students,key=lambda s:s[1],reverse=True))#按成绩从大到小降序

6.6.2 map函数

map会根据提供的函数对指定序列做映射。

map函数语法:map(function,iterable,…)

第一个参数function是对参数序列中的每一个元素调用function函数,iterable是序列

返回值的新列表或迭代器,每个元素是调用

function函数的返回值

示例:

print(list(map(lambda x:x**2,[1,2,3,4,5])))#使用lambda匿名函数
​
print(list(map(lambda x,y:x+y,[1,3,5,7,9],[2,4,6,8,10])))#提供了两个列表,对相同位置的列表数据进行相加

 

6.6.3 zip函数

zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表或迭代器。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同。

zip语法:zip([iterable,…])

参数说明:iterable,… –两个或多个序列

返回值:返回元组列表

a=[1,2,3]
b=[4,5,6]
c=[4,5,6,7,8]
​
print(list(zip(a,b)))
​
print(list(zip(a,c)))#元素个数与最短的列表一致

 

示例:字典键值互换

d={'blue':500,'red':100,'while':300}#值不相同
d1=dict(zip(d.values(),d.keys()))
print(d1)

 

6.6.4 eval和exec函数

Python是一种动态语言,它包含很多含义。Python变量类型,操作的合法性检查都在动态运行中检查;运算的代码需要到运行时才能动态确定;程序结构也可以动态变化,容许动态加载新模块等。这两个函数就体现了这个特点。

eval是计算表达式,返回表达式的值。

exec可运行Python的程序,返回程序运行结果。

x,y=3,7
print(eval('x+3*y-4'))
exec('print("hello world")')

 

6.6.5 all和any函数

all()和any()函数将可迭代的对象作为参数。

all函数参数都是True时,才返回True,否则返回False

any函数参数只要有一个为True,就返回True,参数全部时False,返回iFalse

n=47
print(all([1 if n%k!=0 else 0 for k in range(2,n)]))
​
m=15
print(all([1 if n%k!=0 else 0 for k in range(2,n)]))
​
print(any([[],False,0]))#空列表和0都表示False

 

6.7 程序结构

书的内容按照这样的层次组织:单词、句子、段落以及章。

代码也有类似的自底向上的组织层次:数据类型类似于单词,语句类似于句子,函数类似于段落,模块类似于章。

一个Python程序可以在不同的文件中,这些文件是一个个模块。用import语句引入

import 模块名

模块名是另外一个Python文件的文件名,不包含扩展名,模块是可以运行的程序,

“import 模块名”就是执行文件名为模块名的程序

6.7.1 引入模块中函数的另一种方法

from 模块名 import *

这种方法引入模块中的所有函数,调用的时候不需要再加模块名

from 模块名 import 函数名

这种方法引入模块中的单个函数,调用的时候也不需要再加模块名

6.7.2 创建模块(两文件同一目录)

下面是triangle模块(文件名为triangle.py)

import math
def area(a,b,c):
    s=(a+b+c)/2
    return (math.sqrt(s*(s-a)*(s-b)*(s-c)))

主程序是另一个文件(area.py)

import triangle
a=12
b=34
c=26
print(triangle.area(a,b,c))

 

6.7.3 模块名字空间

1.“主程序”指启动一个程序的代码。包含“主程序”的模块,它的模块空间就是全局名字空间

2.模块空间中有:

模块名,它是模块的文件名,但包含“主程序”的模块名,是“ __ main__”

全局变量

函数名

3.dir(模块名 ):显示模块内容

6.7.4 包

我们已使用过单行代码、多行函数、独立程序以及同一目录下的多个模块。为了使Python应用更具可扩展性,你可以把多个模块文件组织成目录,称之为包。包是一个目录,其中包含一组模块文件和一个init.py文件。如果模块存在于包中,使用“import 包名.模块名”形式导入包中模块,用以下形式调用模块,用以下形式调用函数:“包名.模块名.函数”

6.7.5 sys模块

上面的area.py和triangle.py两个文件在同一目录下,通过Python运行主程序area.py,会引用triangle模块,执行函数area。

模块的查找路径:sys.path

如不在同一目录,可用sys模块加入搜索路径后调用

sys模块中的常用量

sys.argv 从程序外部向程序传递参数
sys.path 模块搜索路径的字符串列表
sys.stdin 标准输入
sys.stdout 标准输出
sys.stderr 标准错误输出
sys.getdefaultencoding() 获取系统当前编码

6.8习题选讲

输入整数n(3<=n<=7),编写程序输出1,2,…,你、

整数的全排列,按字典序输出。

输入样例:

输入 3

输出:123 132 213 231 312 321

def perm(word): #满足输入要求的n个整数组成的字符串,如“123”
    result=[]
    if len(word)==1: #递归结束
        result.append(word)
        return result
    else: #递归过程
        for i in range(len(word)):
            newword=word[:i]+word[i+1:] #生成去掉一个后的字符串
            newresult=perm(newword) #递归调用
            for s in newresult:
                result.append(word[i]+s)
    return result
​
n=int(input())
s="".join([str(i) for i in range(1,n+1)])
for s1 in perm(s):
    print(s1,end=" ")

一元多项式相加

用字典表示多项式,键表示指数,值表示系数

a={12:9,8:15,2:3}
b={19:26,8:-1,6:-13,2:-3,0:82}
def polyadd(a,b):
    newpoly={}
    deg=set(a)|set(b)
    for d in deg:
        coe=a.get(d,0)+b.get(d,0)
        if coe!=0:
            newpoly[d]=coe
    return newpoly
lst=list(polyadd(a,b).items())
print(sorted(lst,key=lambda x:x[0],reverse=True))

七.文件

7.1 文件读写操作

计算机文件,是存储在某种长期存储设备上的一段数据流。所谓“长期存储设备”一般指磁盘、光盘、U盘等。其特点是所存信息可以长期、多次使用,不会因为断电而消失。

计算机文件可分为二种:二进制文件和文本文件

图形文件及文字处理程序等计算机程序都属于二进制文件。这些文件含有特殊的格式以及计算机代码。

文本文件则是可以用文字处理程序阅读的简单文本文件

7.1.1 文件读写操作

7.1.1.1文件读写步骤

1.打开文件

2.处理数据

3.关闭文件

7.1.1.2显示文件内容

textFile=open("7-1.txt","rt",encoding='utf-8') #以文本方式打开
t=textFile.readline()
print(t)
textFile.close()
binFile=open("7-1.txt","rb")# 以二进制方式打开
b=binFile.readline()
print(b)
binFile.close()

 

open函数

fileobj=open(filename,mode)

fileobj是open()返回的文件对象

filename是文件的文件名

mode是指明文件类型和操作的字符串

mode的第一个字母表明对其的操作。mode的第二个字母是文件类型:t(可省略)代表文本类型文件;b代表二进制类型文件。

7.1.1.3文件打开模式

文件打卡模式 含义
“r” 只读模式(默认)
“w” 覆盖写模式(不存在则新创建;存在则重写新内容)
“a” 追加模式(不存在则新创建;存在则只追加内容)
“x” 创建写模式(不存在则新创建;存在则出错)
“+” 与r/w/a/x一起使用,增加读写功能
“t” 文本类型
“b” 二进制类型

7.1.1.4 文件读写函数

名称 含义
open() 打开文件
read(size) 从文件读取长度为size的字符串,如果未给定或为负则读取所有内容
readline() 读取整行,返回字符串
readlines() 读写所有行并返回列表
write(s) 把字符串s的内容写入文件
writelines(s) 向文件写入一个元素为字符串的列表,如果需要换行则要自己加入每行的换行符。
seek(off,whence=0) 设置文件当前位置
tell() 返回文件读写的当前位置
close() 关闭文件。关闭后文件不能再进行读写操作。

7.1.1.5文件复制

source=open("cj.txt","r")
back=open("cjback.txt","w")
s=source.read()
back.write(s)
source.close()
back.close()

7.1.2 多行文件读写

用readlines()读写多行文件

f=open("score.txt","r")
for line in f.readlines():
    print(line) #处理行
f.close()

可用嵌套列表存放多行内容

示例:

学号  姓名 专业 笔试 平时 实验
20101  张三 计算机    65 85 76
20102  李四 金融 86 95 85
20103  王五 经济 86 95 65
20104  丁六 化学 62 75 92

总评=笔试 * 50%+平时 * 25%+ 实验 * 25%

f=open("score.txt","r",encoding="utf-8")
# s=f.readlines()
# print(s)
head=f.readline()
newhead=head[:6]+head[6:17]+head[17:-1]+"   总评成绩"
print(newhead)
for line in f.readlines():
    l=line.split()
    s=round(int(l[3])*0.5+int(l[4])*0.25+int(l[5])*0.25,2)
    l[4]="  "+l[4]
    l[5]="   "+l[5]+"    "
    print(" ".join(l)+str(s))
f.close()

 

7.1.3 输入输出重定向

sys.stdin 标准输入

sys.stdout 标准输出

sys.stderr 标准错误输出

import sys
#c从文件读入变为从键盘输入,改变输入源
s=sys.stdin.readlines()
print(s)

 

import sys
s=sys.stdin.read();strs=s[:s.finf('#')]
for k in set([i for i in strs if i.isalnum()==False and i!="_"]):
    strs=strs.replace(k," ")
strs=strs.rstrip(" ").lower().split()
counts=dict()
for i in strs:
    k=i[:15]
    if k not in counts:
        counts[k]=1
    else:
        counts[k]+=1
ans=sorted(counts.items(),key=lambda x:(-x[1],x[0]))
print(len(counts))
for i in range(0,int(0.1*len(counts))):
    print(str(ans[i][1])+":"+ans[i][0])

7.2 用Pandas模块读写常见格式文件

Python的模块函数分三个层次:

一.内置函数

不用import语句引入,它里面的函数可直接调用。

二.标准模块函数

用import语句引入后再调用,但不必安装。如math库

三.第三方模块函数

需要安装,再用import语句引入模块后才能调用里面的函数,如Pandas模块

7.2.1第三方库安装

PyPI · The Python Package Index

 

pip命令安装

pip install pandas #安装pandas模块

7.2.2 Pandas模块

Pandas是Python的一个数据分析包

Pandas最初被作为金融数据分析工具而开发出来,Pandas为时间序列分析提供了很好的支持。Pandas是基于Numpy的一种工具。

Pandas纳入了大量函数和一些标准的数据模型,提供了高效操作大型数据集所需的工具,提供了大量能使我们快速便捷地处理数据的函数和方法,让Python成为强大而高效的数据分析环境。

7.2.3 Plotly 模块

Plotly是一个基于JavaScript的动态绘图模块。Plotly的绘图效果与我们在网页上看到的动态交互式绘图结果是一样的,其默认的绘图结果是一个HTML网页文件,通过浏览器就可以查看。

Plotly有着强大又丰富的绘图库,支持各种类型的绘图方案。

Plotly是基于JavaScript的绘图库,所以其绘图结果可以与web应用无缝集成。

Plotly最初是一款商业化的绘图软件,由plotly.js开源之后,我们可以使用本地的离线模式进行绘图,不依赖于官方的服务器,使得绘图速度更快,而效果与在线绘图一样。

离线模式: from plotly。offline import plot

7.2.4 DataFrame 数据类型

DataFrame是Pandas库的一种数据类型。DataFrame是一个行和列都具有标签的表格,它与Excel电子表格并无不同。DataFrame使用非常方便,当你处理二维表格数据时,都应该使用它们。DataFrame可由元组、列表、字典或另一个DataFrame构造出来。

7.2.5 由列表产生DataFrame变量data

准备:安装pandas模块和plotly模块

7.2.5.1在PyCharm中安装模块

1.打开file中的Settings

 

2.配置库查询网址

点击加号

 

3.点击 Manage Repositories

 

4.配置网址

Simple Index

PyPI · The Python Package Index

5.搜索模块,点击安装

 

from plotly.offline import plot
from plotly import figure_factory as FF
import pandas as pd
data=pd.DataFrame([["201101","张三","计算机类",65,85,76],["201102","金融类","李四",75,80,76],["201103","化学类","王五",85,82,74],
 ["201104","医学类","丁柳",95,85,100],["201105","经济学类","徐兵",65,75,72]],columns=("学号","姓名","专业","笔试","平时","实验"))
table =FF.create_table(data) #用plotly产生输出表格
plot(table,show_link=False)

 

7.2.6 用DataFrame计算总评分

from plotly.offline import plot
from plotly import figure_factory as FF
import pandas as pd
data=pd.DataFrame([["201101","张三","计算机类",65,85,76],["201102","金融类","李四",75,80,76],["201103","化学类","王五",85,82,74],
 ["201104","医学类","丁柳",95,85,100],["201105","经济学类","徐兵",65,75,72]],columns=("学号","姓名","专业","笔试","平时","实验"))
​
#data变量中增加一列
data["总评成绩"]=data["笔试"]*0.5+data["平时"]*0.25+data["实验"]*0.25
table =FF.create_table(data) #用plotly产生输出表格
plot(table,show_link=False)

 

7.2.7 用pandas读写各种类型文件

read_csv to_csv 读写csv文件
read_excel to_excel 读写excel文件
read_json to_json 读写json文件

7.2.8 读取CSV文件

from plotly.offline import plot
from plotly import figure_factory as FF
import pandas as pd
​
data=pd.read_csv("score.csv",encoding="GBK")
table=FF.create_table(data) #产生表格
plot(table,show_link=False)

“GB2312”、”GBK”和“CP936”都是用两个字节表示中文的编码。

“GB2312”是国标码,“GBK”是“GB2312”的扩展,“CP936”是在“GB2312”基础上开发的汉字编码

7.2.9 写网页文件

产生网页文件“score.html”

from plotly.offline import plot
from plotly import figure_factory as FF
import pandas as pd
​
data=pd.read_csv("score.csv",encoding="GBK")
table=FF.create_table(data)
plot(table,filename='score.html',show_link=False)

7.2.10 读写Excel文件

首先安装xlrd模块

读score.xlsx文件

写入score.xlsx文件

如果安装第三方模块不成功

使用

pip install 包名 -i Simple Index –trusted-host pypi.douban.com

import pandas as pd
data =pd.read_excel("score.xlsx")
data["总评"]=data["笔试"]*0.5+data["平时"]*0.25+data["实验"]*0.25
data.to_excel("scoregp.xlsx",index=0)

7.2.11 JSON文件读写

JSON文件主要有两种结构:

“键/值”对的集合:不同的语言中,它被理解为对象,记录,结构,字典,哈希表,有键列表,或者关联数组。Python中对应字典类型。

值的有序列表:在大部分语言中,它被理解为数组。Python中对应列表类型。

to_json和read_json

读取Excel文件”score.xlsx”,用to_json函数产生JSON文件data.json,最后用read_json读JSON文件“data.json”

 

7.3数据可视化-plotly模块(4.0)

7.3.1 直线图

from plotly.offline import plot
import plotly.express as px
import pandas as pd
dataset=pd.DataFrame({"x":[1,2],"y":[5,6]})
figure=px.line(dataset,x="x",y="y")
plot(figure)

 

7.3.2 折线图

from plotly.offline import plot
import plotly.express as px
import pandas as pd
​
data=pd.read_csv("score.csv",encoding="GBK")
data["总评成绩"]=data["笔试"]*0.5+data["平时"]*0.25+data["实验"]*0.25
figure=px.line(data,x="姓名",y="总评成绩")
plot(figure)

 

7.3.3 同时绘制笔试和总评分的折线图

from plotly.offline import plot
import  plotly.graph_objs as go
​
import pandas as pd
data=pd.read_csv("score.csv",encoding="GBK")
data["总评成绩"]=data["笔试"]*0.5+data["平时"]*0.25+data["实验"]*0.25
xdata=data["姓名"].tolist() #取姓名这一列,变列表
ydata1=data["总评成绩"].tolist() #取总评成绩这一列,变列表
ydata2=data["笔试"].tolist() #取笔试成绩这一列,变列表
trace0=go.Scatter(x=xdata,y=ydata1,name="总评成绩")#总评折线
trace1=go.Scatter(x=xdata,y=ydata2,name="笔试成绩")#笔试折线
mylayout=go.Layout(title="总评成绩和笔试成绩相关图")#图的标题
fig=go.Figure(data=[trace0,trace1],layout=mylayout)
plot(fig)

 

7.3.4 绘制成绩柱状图

from plotly.offline import plot
import plotly.graph_objs as go
​
import pandas as pd
data=pd.read_csv("score.csv",encoding="GBK")
xdata=data["姓名"].tolist()#取姓名这一列,变列表
ydata1=(data["平时"]*0.25).tolist()#取平时成绩这一列,变列表
ydata2=(data["笔试"]*0.5).tolist()
ydata3=(data["实验"]*0.25).tolist()
​
trace0=go.Bar(x=xdata,y=ydata1,name="平时成绩")
trace1=go.Bar(x=xdata,y=ydata2,name="笔试成绩")
trace2=go.Bar(x=xdata,y=ydata3,name="实验成绩")
layout=go.Layout(title="层叠柱状图表示成绩",barmode='stack')
​
fig=go.Figure(data=[trace0,trace1,trace2],layout=layout)
plot(fig)
​

 

7.3.5 Benford定律验证

import pandas as pd
from plotly.offline import plot
import plotly.express as px
digit_counts={d:0 for d in "123456789"} #用字典解析产生字典
population_file=open("population.txt","r")
population_file.readline()#读标题行
total=0
for line in population_file.readlines():
    line=line.strip().split()
    if line and line[2][0].isdigit():
        first_digit=line[2][0]
        digit_counts[first_digit]+=1
        total+=1
percents=sorted([(int(digit),count*100/total)
                 for digit,count in digit_counts.items()])
dataset=pd.DataFrame(percents,columns=("mark","per"))
fig=px.bar(dataset,x="mark",y="per")
plot(fig)
​

数据:

rank,national,pop,percent
1 中国 1,405,372,834 18.82%
2 印度 1,304,200,000 17.86%
3 美国 322,760,000 4.42%
4 印尼 257,740,000 3.53%
5 巴西 205,290,000 2.81%

 

7.3.6 人均GDP和人均寿命关系

import pandas as pd
from plotly.offline import  plot
import plotly.express as px
dataset=pd.read_excel("人均GDP和人均寿命1900.xlsx")
figure=px.scatter(dataset,x="income",y="life-exp",
                  animation_frame="year",animation_group="country",
                  size="income",color="continent",
                  hover_name="country",log_x=True,size_max=45,
                  range_x=[500,200000],range_y=[25,90],
                  labels=dict(income="人均收入(PPP购买力标准)",lifeExp="人均寿命"))
plot(figure)

八.类和对象

8.1 类和对象的概念

8.1.1 什么是面向对象程序设计?

示例

class Students: #定义Students类
    uname="厦门大学"
    def __init__(self,ino,iname):
        self.no=ino
        self.name=iname
    def getInfo(self):
        print("学校:",Students.uname,',学号:',self.no,',姓名:',self.name)
s1=Students('1160520200008',"zhy") #创建一个Students对象s1
s1.getInfo()
s="厦门大学" #创建一个字符串对象s,等价于s=str("厦门大学")
s.index("大学")

变量都可以称为对象

 

面向对象程序设计(Object Oriented Programming,OOP):

使用对象进行程序设计,实现代码复用和设计复用,使得软件开发更高效方便。

类是一种对象的模板和数据类型,它定义了对象的属性(数据),并提供用于初始化对象的初始化程序和操作这些属性的方法。

对象是类的一个实例,使用构造方法来创建一个对象,使用圆点运算符(.)通过引用方法和变量来访问对象的成员。

术语对象(object)和实例(instance)经常是可以互换的。

Python完全采用了面向对象程序设计的思想,是真正面向对象的高级编程语言,完全支持面向对象的基本功能,如封装、继承、多态以及对基类方法的覆盖或重写。

Python中对象的概念很广泛,python中的一切内容都可以称为对象,除了数值、字符串、列表、元组、字典、集合、range对象等等,函数也是对象,类也是对象。

 

 

类:str 对象:s1,s2

面向对象三个特性:封装、继承、多态

8.2 类和对象的创建

8.2.1 类的定义

Python使用class关键字来定义类,class关键字之后是一个空格,然后是类的名字,再然后是一个冒号,最后换行并定义类的内部实现。Python定义类方法:

class Classname:
​
    initializer #初始化
​
    methods #定义方法
class Student: #Student类:包含成员变量和成员方法
    def __init__(self,mname,mnumber): #构造方法,用于创建对象
        self.name=mname #定义成员变量
        self.number =mnumber
        self.Course_Grade={}
        self.GPA=0
    def getInfo(self):
        print(self.name,self.number)
​
s1=Student("wang","3170004545")
s1.getInfo()
s2=Student("zhang","235646546")
s2.getInfo()

 

8.2.2 创建对象

定义了类之后,可以用来实例化对象,并通过“对象名.成员名”的方式来访问其中的数据成员或成员方法。

s1=Student("ji","10001")
s1.getInfo()
s1.name

在Python中,可以使用内置方法isinstance()来测试一个对象是否为某个类的实例。

print(isinstance(s1,Student))
print(isinstance(s1,str))

 

8.2.3 访问对象

对象成员是指它的数据(属性)和方法,数据也称为实例变量,每个对象(实例)的数据中都有一个特定值,方法也被称为实例方法,因为方法被一个对象(实例)调用来完成对象上的动作。

可以使用圆点运算符(.)访问对象的数据成员或方法成员,它也被称为对象成员访问运算符,使用”对象名。成员名”形式

访问数据

s1=Student("Wang","26565646")
s1.name
​
"wang"

调用方法

s2=Student("Zhang","122021212")
s2.getInfo()
​
Zhang 122021212

8.2.4 关于类和对象的变量(数据、属性)

类中的每个变量都必须有初始值,哪怕这个值是0或空字符串

例子:

s3=Student("Li","31263135")
s3.setGpa(3.5)
print("我的名字是"+s3.name,",学号为"+s3.number+",平均绩点为",s3.GPA)

 

8.2.5变量值的修改

可以各种不同的方式修改变量的值:直接通过对象进行修改:通过方法进行设置。

直接通过对象进行修改:

s4=Student("lei","45456456")
s4.GPA=3.8
print("我的名字是"+s4.name,",学号为"+s4.number+",平均绩点为",s4.GPA)

 

s5=Student("Sun","1521523135")
s5.setGpa(3.6)
print("我的名字是"+s5.name,",学号为"+s5.number+",平均绩点为",s5.GPA)

 

示例:

class Student: #Student类:包含成员变量和成员方法
    def __init__(self,mname,mnumber):
        self.name=mname #定义成员变量
        self.number =mnumber
        self.Course_Grade={}
        self.GPA=0
    def getInfo(self):
        print(self.name,self.number)
    def setGpa(self,GPA):
        self.GPA=GPA
        
s4=Student("lei","45456456")
s4.GPA=3.8  #直接通过对象进行修改
print("我的名字是"+s4.name,",学号为"+s4.number+",平均绩点为",s4.GPA)
​
s5=Student("Sun","1521523135")
s5.setGpa(3.6) #通过方法进行设置
print("我的名字是"+s5.name,",学号为"+s5.number+",平均绩点为",s5.GPA)

 

8.3 使用对象编写程序

输出gpa最高的学生信息

数据:

zhao    12  160 608
li  13  165 610
xu  14  160 600
gao 15  158 585
zhu 16  155 480
lv  17  170 605
class StudentGPA:
    def __init__(self,name,num,credits,qpoints): #构造方法,用于创建对象
        self.name=name #姓名
        self.num=num  #学号
        self.credits=float(credits) #总学分数
        self.qpoints=float(qpoints) #总绩点数
    def getName(self): #获取姓名和学号的方法
        return self.name,self.num
    def getCredits(self): #获取总学分的方法
        return self.credits
    def getQPonits(self): #获取总绩点的方法
        return self.qpoints
    def gpa(self):
        return self.qpoints/self.credits
#定义makeStudent方法,用于创建对象
def makeStudent(infoStr):
    name,num,credits,qpoints=infoStr.split("\t")
    return StudentGPA(name,num,credits,qpoints)
# 程序从这里开始运行,输入要读入数据的文本文件名,以读方式打开
filename=input("Enter name the grade file:")
infile=open(filename,"r",encoding="utf-8")
#从文件中读入一行,创建第一个学生对象
best=makeStudent(infile.readline())
for line in infile.readlines():
    if line.split()!=[]:
        s=makeStudent(line)
        if s.gpa() > best.gpa():
            best=s
infile.close()
#计算GPA最高,best对象存放GPA最高的学生
#打印成绩最好学生的信息
print("成绩最好的学生:",best.getName())
print("学分:",best.getQPonits())
print("GPA",best.gpa())

 

8.4 封装

封装:

将数据和对数据的操作组合起来构成类,类是一个不可分割的独立单位

类中既要提供与外部联系的接口,同时又要尽可能隐藏类的实现细节。

Python类中成员分为变量(数据、属性)和方法(函数)

Python类中成员:

变量(数据)

类变量

实例变量

Python类中成员

方法(函数)

公有方法

私有方法:方法名以下两个下划线“_”前缀

类方法:@classmethod

静态方法:@staticmethod

8.4.1 类变量与实例变量

类变量是类中所有方法之外定义的

实例变量一般是指在构造方法 __ init __ ()定义的,定义和使用时以self作为前缀

特性:在主程序中(或类的外部),实例变量属于实例(对象),只能通过对象名访问:而变量属于类,可以通过类名或对象名都可以访问。

class Car:
    price=100000  #定义类变量
    def __init__(self,c): #定义实例变量
        self.color=c
car1=Car("Red") #创建对象
car2=Car("Blue")
print(car1.color,Car.price) #查看实例变量和类变量的值
Car.price=110000 #修改类变量
Car.name="QQ" #动态增加类变量
car1.color="Yellow" #修改实例变量
print(car2.color,Car.price,Car.name)
print(car1.color,car1.price,Car.name)

 

8.4.2 实例方法、类方法

实例方法:在类的方法中第一个参数如果为self,这种方法称为实例方法。实例方法对类的某个给定的实例进行操作,可以通过self显示地访问该实例。

类方法:Python允许声明属于类本身的方法,即类方法。类方法不对特定实例进行操作,在类方法中不能访问对象的实例变量。类方法通过装饰器@classmethod来定义,第一个形式参数必须为类对象本身,通常为cls。

8.4.3 私有成员与共有成员

Python类的成员没有访问权限限制,这与其它面向对象程序设计语言不同。

在Python中通常有一些约定,以下划线开头的方法名和变量名有特殊的含义,尤其是在类的定义中。

在Python中,以下划线开头的方法名和变量名有特殊的定义,尤其是在类的定义中。

_xxx:受保护成员,不能用’from module import *’导入:

__ xxx __:系统定义的特殊成员:

__ xxx: 私有成员,只有类内自己能访问,不能使用对象直接访问到这个成员。

实例:

class Car1:
    price = 300000    #定义类变量
    def __init__(self,name):    #构造方法
        self.__name=name      #定义实例变量
        self.__color=""     #存储汽车颜色
    def setColor(self,color): #设置汽车的颜色
        self.__color=color
    def getName(self):  #打印汽车的名字和颜色
        print(self.__name,self.__color)
car1=Car1("奥迪")  #创建car1对象
car1.setColor("黑色") #car1的汽车颜色
car1.getName()  #打印car1的名字和颜色
print(car1.price) #打印汽车的价格

 

8.5 继承和多态

8.5.1 继承

继承:从一个通用类(父类),扩展更多特定的类(子类)

例:下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此我们也可以在前面创建的Car类的基础上创建新类ECar,这样我们就只需为电动汽车特有的属性和方法编写代码。

下面来创建一个简单的ECar类,它具备Car类的所有功能:

实例:

class Car:    #父类
    price = 300000    #定义类变量
    def __init__(self,name):
        self.name=name      #定义实例变量
        self.color=""     #存储汽车颜色
    def setColor(self,color): #设置汽车的颜色
        self.color=color
class ECar(Car):   #子类ECar继承父类Car
    def __init__(self,name):
        super().__init__(name) # 初始化父类的属性
        self.battery_size=300
    def getEcar(self):
        print("我是电动汽车"+self.name+",电瓶容量为"+str(self.battery_size)+"公里")
my_tesla=ECar("特斯拉")
my_tesla.getEcar()

 

8.5.2多态

多态:子类的对象可以传递给需要父类类型的参数。一个方法可以被沿着继承链的几个类,运行时由Python决定调用哪个方法,这个也成为动态绑定。

例子:

 

动态绑定 ‘+’运算符重载

九.Web应用程序开发和网络爬虫

9.1 Web应用程序开发概述

Web应用程序是一种可以通过浏览器访问的应用程序,程序的最大好处是用户很容易访问应用程序,终端只需要有浏览器即可,不需要再安装其他软件。

这种程序开发也成为App开发

Web应用程序现在主要采用浏览器/服务器架构(Browser/Server,简称B/S),它能够很好地应用在广域网上,成为越来越多企业的选择。

9.1.1 Web应用程序的运行过程

1.运行用Python编写的服务程序

2.用户在浏览器输入URL访问某个资源

3.Flask接受用户请求分析URL

4.为这个URL找到对应的处理函数

5.执行函数并生成响应,返回给浏览器

6.浏览器接受并解析响应,经信息显示在页面中国

 

9.1.2 URL统一资源定位符

URL就是统一资源定位符(Uniform Resourse Locator),它的一般格式如下:

protocol://hostname[:port]/path/:parameters#fragment

URL的格式由三个部分组成:

(1)protocol: 第一部分就是协议,例如百度使用的就是https协议;

(2)hostname:[:port]: 第二部分就是主机名(端口号为可选参数),Flask默认的端口号为5000,百度的主机名就是:www.baidu.com

(3)path:第三部分就是主机资源的具体地址,如目录和文件名等。

9.1.3 超级文本标记语言(HTML)

超级文本标记语言(HTML)是为网页创建而设计的一种标记语言。网页的本质就是超级文本标记语言,通过结合使用其他的技术,可以创造出功能强大的网页。

一个HTML文件对应一个网页,以.html或html为扩展名。可以使用任何能够生成TXT类型的文本编辑器来产生超文本标记文件,。然后修改文件扩展名即可。

实例:返回网页的服务器程序

from flask import Flask
app=Flask(__name__)
@app.route("/")
def hello():
    return ''' <!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="Content-Type" content="text/html" />
    <title>div标签</title>
  </head>
  <body>
    <h2>热门课程排行榜</h2>
    <ol>
        <li>Python程序设计</li>
        <li>零基础学习html</li>
        <li>JavaScript全攻略</li>
    </ol>
    <h2>最新课程排行</h2>
    <ol>
        <li>版本管理工具介绍</li>
        <li>Canvas 绘图详解</li>
        <li>Pandas数据分析</li>
    </ol>
  </body>
</html>'''
if __name__ =="__main__":
    app.run()

 

9.1.4 HTML常用标签

标签 属性 用途
HTML 整个HTML文档
HEAD 文件头
TITLE 文档标题
BODY background,bgcolor 文档主体内容
H1,H2,H3 标题
I,EM 斜体强调样式
P,SPAN,DIV 段落,块元素,行内元素
BR 换行
A href 超链接
IMG src,width,height 图片
TABLE 表格
TR 表格中的一行
TH,TD 表头/单元格
OL,UL 有序/无序列表
LI 列表
DL 描述列表
INPUT name 用户输入域
SELECT name 下拉菜单
B,STRONG 加粗强调样式
PRE 格式化

9.1.5 层叠样式表(css)

CSS为HTML标记语言提供了一种样式描述,定义了其中元素的显示方式。CSS提供了丰富的文档样式外观

CLASS属性允许向一组在CLASS属性上具有相同值的元素应用声明。使用CLASS属性来分类元素,在样式表中创建规则来引用CLASS属性的值,然后浏览器自动将这些属性应用到该组元素。CLASS选择器以标志符“.”开头,用于指示后面是哪种类型的选择器。

ID属性操作类似于CLASS属性,但有一点重要的不同之处:ID属性的值在整篇文档中必须是唯一的。这使得ID属性可用于设置单个元素的样式规则。包含ID属性的选择器称为ID选择器。ID选择器的标识符是符号“#”。

示例

from flask import Flask
app=Flask(__name__)
@app.route("/")
def hello():
    return ''' <!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="Content-Type" content="text/html" />
   <title>类和 ID 选择器的区别</title>
<style type="text/css">
.stress{font-weight:bold;}
.bigsize{font-size:25px;}
#stressid{font-weight:bold;}
#bigsizeid{font-size:25px;}
</style></head>
<body>
 <h1>勇气</h1>
<p>三年级时,我还是一个<span id="stressid">胆小如鼠</span> 
的小女孩, <br/> 
 上课从来不敢回答老师提出的问题,生怕回答错了老师 <br/> 
 会批评我。就一直没有这个<span class="stress">勇气</span>来回 <br/> 答老师提出的问题。
学校举办的活动我也没勇气参加。</p> <br/> 
 <p>到了<span class="stress bigsize">三年级</span>下学期时,<br/> 我们班上了一节公
开课,老师提出了一个很简单的问题,班里很多 <br/> 
 同学都举手了,甚至成绩比我差很多的,也举手了, <br/> 
 还说着:"我来,我来。"我环顾了四周,就我没有举手。</p> 
</body></html> '''
if __name__ =="__main__":
    app.run()

 

9.1.6 常用选择器例子

选择器 例子 解释
.class .stress 选择class=stress的所有节点
#id #stressid 选择id=stressid的所有节点
* * 选择所有节点
element span 选择所有span节点
element element div p 选择div节点内部的所有p节点
element,element div,p 选择所有div节点和所有p节点
element>element div>p 选择父节点为div节点的所有p节点

9.1.7 HTML DOM树

 

9.2 Web应用框架Flask和文件模块

Flask是一个使用Python编写的轻量级Web应用框架。其WSGI工具箱采用Werkzeug,模块引擎则使用Jinja2.Flask使用BSD授权。

Flask也成为“microframework”,因为它使用简单的核心,用扩展增加其他功能。Flask是第三方模块,需要先安装才能使用。

9.2.1 URL分析和对应的处理函数

1.运行Python服务程序

2.用户在浏览器输入URL访问某个资源

3.Flask接受用户请求分析URL

4.为这个URL找到对应的处理函数

5.执行函数并生成响应,返回给浏览器

6.浏览器接受并解析响应,将信息显示在页面中

9.2.2 多个URL对应同一个函数

多个URL可对应统一函数,这样在浏览器中输入不同的URL返回结果是一样的

在浏览器输入:http://127.0.0.1:5000或http://127.0.0.1:5000/hello,结果一样

from flask import Flask #导入flask模块
app=Flask(__name__) #创建flask对象app
@app.route("/") #装饰器,定义目录"/"的操作
@app.route("/hello")
def hello():    #定义函数,遇到网址目录为"/"或"/hello"执行
    return "Hello World!这是一个Web应用程序" #返回字符串
if __name__ == "__main__":
    app.run()   #运行程序

 

9.2.3 HTTP协议常用请求

GET:从服务器程序获取信息

POST:通常用作向服务器程序发送数据,一般用表单实现,POST请求可能会导致新的资源的建立和/或已有资源的修改

9.2.4 浏览器和服务器程序交互

浏览器和服务器程序交互可以通过get和post方法实现。

在装饰器上可以加上http方法,常用的是get和post方法,缺省的是get方法

@app.route(“/”)就等同于@app.route(“/”,methods=[“get”])

如需要用两个方法,可写成:@app.route(“/”,methods=[“get”,”post”]) get和post是站在浏览器角度看的

9.2.5 url_for 函数

url_for()函数获取静态文件的URL

url_for(‘static’,filename=’css/bootstrap.css’)

表示文件的URL是:

/static/css/bootstrap.css

9.3 习题选讲

9.3.1 Dash简介

Dash构建在Flask、Plotly和React之上,非常适合在纯Python中,使用高度自定义的用户界面,构建数据可视化App。它特别适合使用Python进行数据分析的人。

Dash应用程序在Web浏览器中呈现,可以将应用程序部署到服务器,然后通过URL进行共享。由于Dash应用程序是在Web浏览器中进行查看,因此Dash本质上是跨平台的。

pip install dash

pip install dash-html-components

pip install dash-core-components

pip install dash-table

Dash用户手册:Dash Documentation & User Guide | Plotly

典型Dash App:Dash Enterprise

9.3.2 Dash应用程序结构

Dash应用程序由两部分组成。第一部分是应用程序的“布局”,描述了应用程序的外观。第二部分描述应用程序的交互性。

Dash为一组丰富的基于Web的交互式组件提供了Python接口,不必编写JavaScript程序。

Dash提供了一个简单的回调函数,用于将自定义数据分析代码绑定到Dash用户界面,实现高级交互。

9.3.3 布局–layout

布局由一个组件树组成,如html.Div和dcc.Graph

dash_html_components库为每一个HTML标签都提供一个组件。

children属性是特殊的。按照惯例,它始终都是第一个属性,这意味着你可以省略它

dash_core_components描述了更高级别的组件。这些组件时交互式的,并通过JavaScript、HTML和CSS等生成

import dash_core_components as dcc

dcc.Graph参数是用plotly产生的图表

9.3.4 Dash HTML Compoents例子

import dash_html_components as html
html.Div(
    [
        html.Div('Example Div',style={'color':'blue','fontSize':14}),
        html.P('Example P',className='my-class',id='my-p-element')
    ],style={'marginBottom':50,'marginTop':25}
)

9.3.5 人均收入和人均寿命关系图

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.express as px
dataset=pd.read_excel("gapminder.xlsx")
fig=px.scatter(dataset,x="income",y="life_exp",animation_frame="year",
               animation_group="country",size="income",color="continent",
               hover_name="country",log_x=True,size_max=45,
               range_x=[500,200000],range_y=[25,90],
               labels=dict(income="人均收入(PPP购买力标准)",life_exp="人均寿命"))
app=dash.Dash(__name__) #创建Web应用程序,即App
app.layout=html.Div([
    html.H1(children='人均收入和人均寿命关系图',style={'textAlign':'center'}),
    html.Div([dcc.Graph(figure=fig)])
])
app.run_server()

 

9.3.6 Dash 样式

Dash标准样式: https://codepen.io/chriddyp/pen/bWLwgP

网格布局:网格是一个12列的流体网格,最大宽度为960px,随着浏览器/设备的缩小而缩小。最大宽度可以用一行CSS更改,所有列都将相应地调整大小。

9.3.6.1 页面区域布局 — Div标签

两列的Web程序

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.express as px
dataset=pd.read_excel("gapminder.xlsx")
​
fig = px.scatter(dataset, x="income", y="life_exp", 
                 animation_frame="year",
                 animation_group="country",size="income",
                 color="continent",
                 hover_name="country",log_x=True, 
                 size_max=45,
                 range_x=[500,200000], range_y=[25,90],
                labels=dict(income="人均收入(PPP购买力标准)",life_exp="人均寿命"))
app = dash.Dash(__name__)
​
app.layout = html.Div([  
    html.H1( #第一行
        children='人均收入和人均寿命关系图',
        style={'textAlign': 'center','color': "#111111" }  #黑色
    ),
    html.Div([ #第二行
    #Column 1
        html.Div([html.Br([]), html.Br([]),  #空行
                 html.H6('使用的第三方模块:'),
                 html.P('Pandas--数据分析'),
                 html.P('Dash--Web应用程序框架')],
                className = "two columns"),
    #Column 2
       html.Div([dcc.Graph(figure=fig)], className = "ten columns"),
    ],className = "row ")])
​
app.run_server()

 

9.3.7 Flask和Dash集成

import flask
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.express as px
dataset=pd.read_excel("gapminder.xlsx")
fig=px.scatter(dataset,x="income",y="life_exp",animation_frame="year",
               animation_group="country",size="income",color="continent",
               hover_name="country",log_x=True,size_max=45,
               range_x=[500,200000],range_y=[25,90],
               labels=dict(income="人均收入(PPP购买力标准)",life_exp="人均寿命"))
server=flask.Flask(__name__)
@server.route("/")
def index():
    return 'Hello Flask'
app=dash.Dash(__name__,server=server,routes_pathname_prefix='/dash/')
​
​
# app=dash.Dash(__name__) #创建Web应用程序,即App
app.layout=html.Div([
    html.H1(#第一行
        children='人均收入和人均寿命关系图',
        style={'textAlign':'center','color':"#111111"}),
    html.Div([
        html.Div([html.Br([]),html.Br([]),#空行
                  html.H6("使用第三方模块:"),
                  html.P('Pandas--数据分析'),
                  html.P('Dash--Web应用程序框架')
                  ],className="two columns"),
        #Column2
        html.Div([dcc.Graph(figure=fig)],className="ten columns"),
    ],className="row")])
if __name__ == '__main__':
    server.run()

 

9.3 云端部署Web应用程序

免费部署python类网站

Host, run, and code Python in the cloud: PythonAnywhere (www.pythonanywhere.com)

9.3.1 步骤

1.点击Web模块,点击Add a new web app

 

2.点击next

 

3.选择Flask模块,以及对应版本,就会创建一个网址

 

4.点击Reload,部署,点击Configuration for的网址

 

5.成功

 

6.选择File模块,选择mysite/,点击flask.app.py

 

7.save保存,并修改为web形式

 

8.重启,进入该网站

 

9.3.2 模块安装

user dash

user dash-html-compoents

user dash-core-compoents