MENU

Python Learning

March 5, 2020 • 学习笔记阅读设置

0.序言

本来因为没考上 计算机专业 ,所以就想打算做成生活博客的,把以前自己乱折腾的东西就全删了。

不过恰好今年我们通识课也有开设关于 Python 学习的课程,所以还是来写写。

因为是初学者,且非科班专业,如有不正之处还请大佬们包含。

本文较长,建议点击右侧按钮以打开 目录树 ,选择您需要的内容进行浏览!

可配合我在 Github 上开的坑一起食用 ;

1.环境安装与基础知识

这边就直接选择我们学校老师推荐的 Python 3.7.4 + Jupyter Notebook 了, 大佬们给我安利的各类 IDE 这边就不多折腾了,怕在学校里显得我很另类

Python 安装

我们先下载 Python 3.7.4 64位

勾选 Add Python 3.7 to PATH ,并点击 Customize installation

Pic1

无脑点击 Next

Pic2

勾选 Install for all users ,并自定义设置 安装路径

Pic3

顺利完成安装 ;

Pic4

扩展包 安装

打开 命令提示符 ,运用 pip install [包名] 即可完成安装,如安装 IPython包

pip install IPython

Pic5

如提示 需升级 则按说明输入如下代码即可 ;

python -m pip install --upgrade pip

Pic6

我们老师也给了个 批量安装扩展包脚本 ,双击安装即可 ;

Pic7

Jupyter Notebook 工作路径配置与启动

使用了老师给的脚本后,已经顺利完成了 Jupyter Notebook 的安装,然后我们需要修改 默认工作路径

运行命令:

jupyter-notebook --generate-config -y

Pic8

如图所示,我的配置文件在 C:\Users\BleShi\.jupyter\ 路径 ;

此时我们双击打开 jupyter_notebook_config.py 文件 ;

Ctrl + F 搜索代码: #c.NotebookApp.notebook_dir = ''

Pic9

' ' 内,填入你需要设置的默认工作路径,并记得删除前面的 # 号

如我设置后为:

c.NotebookApp.notebook_dir = 'C:/Workspace-jupyter'

Pic10

此时,所有的安装已经完毕了,可以在 命令提示符 内输入 jupyter notebook 以默认浏览器启动 Jupyter Notebook ,使用它的时候请 不要关闭 这个 命令提示符 窗口 ;

Pic11

关键字/保留字

以下内容均为 关键字/保留字他们仍然是区分大小写的

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

变量命名规则

  1. 可以由字母、数字、下画线 _ 组成,但开头不能有数字
  2. 不能是 Python 的 关键字 ,但可以包含关键字,如: not_and 等 ;
  3. 不能包含空格 ;

内置函数

Pic12

作业 1 温度换算

Python 中调试和运行以下程序,并执行,将程序代码上传。

Pic13

我的答案:

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

temp_str = input("请输入带符号的温度值,如'23c','34f'")
if temp_str[-1] in ['F','f']:
    temp_Cels = (eval(temp_str[0:-1]) -32) / 1.8
    print("转换后的温度是 %.2f摄氏度" % temp_Cels)
elif temp_str[-1] in ['C','c']:
    temp_Farhr = 1.8 * eval(temp_str[0:-1]) + 32
    print("转换后的温度是{:.2f}华氏度".format(temp_Farhr))
else:
    print("格式错误")

Pic4

Pic15

请注意所有符号为英语输入状态下输入!

作业 2 金灿灿画图

Python 中调试和运行以下程序,并执行,将程序代码上传。

Pic16

我的答案:

# -*- coding: utf-8 -*-
    
import turtle as t
import time
t.color("red","yellow")
t.speed(10)
t.begin_fill()
for i in range(50):
    t.forward(200)
    t.left(170)
t.end_fill()
time.sleep(1)

Pic17

作业 3 绘制小猪佩奇

Python 中调试和运行以下代码,将结果上传。

小猪佩奇绘制代码示例文件名

我的答案:

Pic18

2.Python 语言基础

唔!终于开始学辣!感觉区分基础概念很困难,但是执行代码倒还挺简单哒!

数据类型 概念

Python 3 中有 6 种标准的数据类型: Number(数字) 、 String(字符串) 、 List(列表) 、 Tuple(元组) 、 Set(集合) 、 Dictionary(字典) ;

Python 3 支持 3 种不同的数值类型: 整形(int) 、 浮点型(float) 、 复数(complex) ;

整数 没有上下限,也不会产生误差 ;

数据有类型是因为它们分配的内存大小不同 ;

数据有类型是因为它们的运算种类不同 ;

变量没有类型是因为 Python 不根据变量分配内存 ;

数据类型 整型 int

int 通常被称为整形或整数,有 之分,但不带小数点 ;

如:

>>> 50
50

>>> 25+25
50

>>> 50-25
25

>>> 50*2
100

>>> 50//2.0
25.0
# 地板除,只取整数部分

>>> 57%7.0
2.0
# 余数运算,直接得到余数

数据类型 浮点型 float

浮点型由整数部分与小数部分组成,也可以用科学计数法表示 ;

如:

>>> 3.3*51
168.29999999999998
# 因整数和浮点数在计算机内部存储的方式不同,整数运算是精确的,但浮点可能会四舍五入误差

>>> 50//2.0
25.0
# 地板除,只取整数部分,此时结果为浮点数

>>> 57%7.0
2.0
# 余数运算,直接得到余数,此时结果为浮点数

数据类型 数据类型转换

可以利用 int 函数 和 float 函数进行转换 ;

>>> int(5.20)
5
# 将括号内的值转换为整数

>>> float(1314)
1314.0
# 将括号内的值转换为浮点数

>>> float(int(520.1314))
520.0
# 也可以嵌套起来食用呐!

变量和关键字 常量

变量指向各种类型值的名字,以后再用到的时候,直接引用名字就可以啦!

我们甚至可以把字符串赋值给变量,具体类型并不是固定哒!

我们利用 = 进行赋值,如:

>>> a=200
>>> print(a)
200
>>> a=a+200
>>> print(a)
400
# 赋值语句是先计算右侧的表达式的
>>> a="www.bleshi.com"
>>> print(a)
www.bleshi.com

变量和关键字 变量名称

变量可以随便命名,只要你喜欢就可以,包括但不局限于你用中文日文 火星文 (这个不行哈哈哈哈,不能乱用符号)等。

如:

>>> 藍小檸為什麼還沒有女朋友 ="我还是好喜欢她"
print(藍小檸為什麼還沒有女朋友)
藍小檸為什麼還沒有女朋友

但你还是需要注意如下规则哦:

  1. 可以由字母、数字、下画线 _ 组成,但开头不能有数字
  2. 不能是 Python 的 关键字 ,但可以包含关键字,如: not_and 等 ;
  3. 不能包含空格 ;

另,请注意 Python变量 是区分大小写的。

语句和表达式 语句

语句是 Python 解释器可以运行的一个代码单元,可以理解为可执行的命令啦。

如:

>>> 藍小檸想找什麼類型的女孩子呢 ="憋说了,换个话题吧"
print(藍小檸為什麼還沒有女朋友)
憋说了,换个话题吧

语句和表达式 表达式

表达式就是值、变量和操作符的组合,一个值也可以看作表达式的哦。

如:

>>> 3*3
9

操作符和操作对象

unm 像 +-*///% 这种都可以算运算符,操作对象就是把运算符连接起来的东西。

具体用专业术语说,有如下 8 种运算符:

  1. 算数运算符 ;
  2. 比较(关系)运算符 ;
  3. 赋值运算符 ;
  4. 逻辑运算符 ;
  5. 位运算符 ;
  6. 成员运算符 ;
  7. 身份运算符 ;
  8. 运算符优先级 ;

算数运算符

 除去数据类型板块内已经介绍过的运算符,这边再介绍下之前没提到的次方运算:

如:

>>> 2**8
256
# 即 2 的 8 次方运算

比较运算符

比较运算符主要用于比较 废话 ,通常是会返回 TrueFalse ,具体如下:

== # 等于,就是用来比较是否相等
!= # 不等于,就是用来比较是否不等
>  # 大于,比较左边是不是大于右边
<  # 小于,比较左边是不是小于右边
>= # 大于等于,比较左边是不是大于等于右边
<= # 小于等于,比较左边是不是小于等于右边

如:

>>> a=1
>>> b=2
>>> a!=b
True 
# 显然 a 不等于 b 啦,所以就返回 True 咯

赋值运算符

我将它朴素的理解为 先运算再赋值,形如 c+=a 等价于 c=c+a

=   # 等于赋值运算符
+=  # 加法赋值运算符
-=  # 减法赋值运算符
*=  # 乘法赋值运算符
/=  # 除法赋值运算符
%=  # 取余赋值运算符
**= # 幂赋值运算符
//= # 取整赋值运算符

运算符优先级

一个表达式内出现多个操作符后,会按照如下的运算优先级依次进行操作:

()                     # 括号
**                     # 指数运算
* / % //               # 乘、除、取余、取整
+ -                    # 加法、减法
<= < = > >=            # 比较运算符
!= ==                  # 等于运算符
+= -= *= /= %= **= //= # 赋值运算符

注释

注释必须以 # 开始,可以单独占据一行,也可以放在句末。

3.列表和元组

数据结构是通过某种方式(如对元素进行编号)组织在一起的数据元素的集合,这些元素可以是数字或字符。在 Python 中,最基本的数据结构是序列 SequencePython 包含 6 种内建序列,即 列表元组字符串Unicode字符串Buffer对象Xrange对象

通用序列操作 索引

序列中每个元素都分配一个数字,代表他在序列中的位置索引,第一个索引是 0 ,第二个索引是 1 ,可以通过编号分别对序列的元素进行访问:

>>> website="www.bleshi.com" # 定义变量 website 为 www.bleshi.com
>>> print(website[0])        # 根据编号取元素
w                            # 输出编号为 0 的元素
>>> print(website[3])        # 根据编号取元素
.

可以配合本图理解食用。

Pic19

我们将上方的内容称之为 正数索引 ,而从右向左的索引可以称之为 负数索引

>>> website="www.bleshi.com" # 定义变量 website 为 www.bleshi.com
>>> print(website[-1])        # 根据编号取元素
m                            # 输出编号为 0 的元素
>>> print(website[-4])        # 根据编号取元素
.

所以我们的图片得到了升级:

Pic20

另,不定义变量直接索引也可以:

>>> print("Happy"[0])
H
>>> print("Happy"[-1])
y

>>> CleverBoy=input()[0] # 操作函数的返回序列
BleShi
>>> print(CleverBoy)
B

因此,索引可以用于 变量引用操作直接操作操作函数的返回序列

通用序列操作 分片

分片通过 : 可以实现一定范围内元素的访问,若边界为 ab ,则得出的结果是 a<=x<b ,可理解为 [a,b)

>>> sequence=[1,2,3,4,5,6,7,8,9,10]
>>> print(sequence[0:4])   # 取索引中的第零到第三位置的元素
[1, 2, 3, 4]
>>> print(sequence[-3:-1]) # 取索引中从右向左的第三位和第二位
[8, 9]
>>> print(sequence[:0])    # 不知道这个是啥意思,反正啥也出不来qwq,盲猜从第零位置到第零位置
[]
>>> print(sequence[-3:])   # 取最后三个元素
[8, 9, 10]
>>> print(sequence[0:])    # 取全部元素
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> print(sequence[:])     # 取全部元素
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> print(sequence[:3])    # 取前三个元素
[1, 2, 3]

如果要取用不连续的元素,我们就要使用到 步长 ,默认 步长 均为 1 ,要用则多加一个 :

>>> sequence=[1,2,3,4,5,6,7,8,9,10]
>>> print(sequence[0:10:2])   # 取所有的奇数
[1, 3, 5, 7, 9]
>>> print(sequence[2:10:3])   # 取3的整数倍
[3, 6, 9]
>>> print(sequence[9:0:-2])   # 步长也可以是负的(有一说一,很高级
[10, 8, 6, 4, 2]

通用序列操作 序列相加

可以用 + 来进行序列的连接操作:

>>> a=[1,2,3]
>>> w=[4,5,6]
>>> print(a+w)
[1, 2, 3, 4, 5, 6]

>>> s="Ble"
>>> l="Shi"
>>> print(s+l)
BleShi

但是只有 类型相同 的序列才能够进行序列连接操作。

通用序列操作 序列乘法

在字符后面用 * 以使其反复出现:

>>> print("iloveu"*5)
iloveuiloveuiloveuiloveuiloveu
>>> print([52013]*14)
[52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013, 52013]

通用序列操作 长度 最小(大)值

可以用 lenmaxmin 函数来实现这些功能。

>>> sequence=[1,100,500,10000]
>>> print(len(sequence)) # 输出长度
4
>>> print(max(sequence)) # 输出最大的数值
10000
>>> print(min(sequence)) # 输出最小的数值
1

列表 元素赋值

可以使用 赋值语句 来改变列表的方式:

>>> a=[1,2,3]
>>> a[1]=10 # 替换第一位的数字,也就是将数字 2 换为 10
>>> print(a)
[1, 10, 3]
>>> a[1]="BleShi" # 替换第一位的数字,也就是将数字 2 换为 10
>>> print(a)
[1, 'BleShi', 3]

列表 增加元素

利用 append 函数在列表末尾添加对象:

>>> maxim=[520]
>>> maxim.append(1314)
>>> print(maxim)
[520, 1314]
>>> maxim.append("Ohhhhh") # 也可以往里面加文字哦
>>> print(maxim)
[520, 1314, 'Ohhhhh']

列表 删除元素

利用 del 函数删除你的对象:

>>> girlfriend=["She","nobody"]
>>> del girlfriend[0] # 你的对象已被删除
>>> print(girlfriend)
['nobody']

列表 分片赋值

利用 list 函数,可以实现老罗的大爆炸功能

>>> boom=list("Smartisan,OS")
>>> print(boom)
['S', 'm', 'a', 'r', 't', 'i', 's', 'a', 'n', ',', 'O', 'S']
>>> boom[10:]=list("YES") # 第 10 位后换位 YES
>>> print(boom)
['S', 'm', 'a', 'r', 't', 'i', 's', 'a', 'n', ',', 'Y', 'E', 'S']

>>> task=list("蓝小柠有女朋友了吗")
>>> task[3:3]=list("在2020年")
>>> print(task)
['蓝', '小', '柠', '在', '2', '0', '2', '0', '年', '有', '女', '朋', '友', '了', '吗']

列表 嵌套列表

欢迎使用 mix 函数开始套娃:

>>> a=["BleShi"]
>>> b=[".com"]
>>> mix=[a,b]
>>> print(mix[0],mix[1])
['BleShi'] ['.com']

列表 列表方法

利用 count 函数,可以实现对象中有多少个个数的计算:

>>> ohhhhhh=("23333")
>>> print("在ohhhhhh中一共出现了",ohhhhhh.count("3"),"个3")
在ohhhhhh中一共出现了 4 个3

利用 extend 函数,可以在原序列后增加内容:

>>> a=["Ble","Shi"]
>>> b=["ohhhhh","23333"]
>>> a.extend(b)
>>> print(a)
['Ble', 'Shi', 'ohhhhh', '23333']

请注意 extend 函数有别于两个列表相加,它会使得原序列发生改变哦!

利用 pop 函数,可以移除某元素:

>>> a=[1,2,3,4,5,6,7,8,9,0]
>>> a.pop() # 不传参则删末位
0
>>> print(a)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a.pop(2) # 传参2,则删第二位
3
>>> print(a)
[1, 2, 4, 5, 6, 7, 8, 9]

这里学习到的 pop 函数是除了 none 以外又能够修改列表又能够返回元素值的:

利用 insert 函数,可以插入某元素:

>>> num=[1,2,3,4,5]
>>> num.insert(2,"a") # 数字 2 后插入 a
>>> print(num)
[1, 2, 'a', 3, 4, 5]

元组

( ) 来创建 元组 ,用 , 分割

>>> (1,2,3)
(1, 2, 3)
>>> ("BleShi",".com")
('BleShi', '.com')
>>> (1,) # 记得要加逗号哦
(1,)

元组 tuple函数

利用 tuple 函数以一个序列作为参数,并转换为元组:

>>> tuple("hello")
('h', 'e', 'l', 'l', 'o')
>>> tuple(["Ble","Shi"])
('Ble', 'Shi')
>>> tuple(("Ble","Shi")) # 如是元组,则原样返回
('Ble', 'Shi')

元组 访问元组

访问元组的方式与访问列表一样:

>>> a=(1,2,3,4,5,6)
>>> print(a[1])
2
>>> print(a[0:3])
(1, 2, 3)

元组 连接元组

元组可以被连接,但不可以被修改:

>>> a=(1,2,3)
>>> b=(6,7,8,9)
>>> print(a+b)
(1, 2, 3, 6, 7, 8, 9)

元组 删除元组

不能删除元素,但可以整个元组删除。

>>> a=(1,2,3)
>>> del a

元组 元组索引、截取

和列表的方式一样:

>>> a=[1,2,3,4]
>>> print(a[2])
3
>>> print(a[-3])
2

据说,不可变的 tuple 会使得代码更安全,可以按照实际情况来选用。(我啥都写不来,你还和我说安全呜呜呜

4.程序设计的结构

开始写程序辣,冲鸭!

条件和条件语句 布尔值(逻辑值)

布尔值 只有两个值:True和False,分别表示真和假。

以下值被视为假,也就是 0

False、None、0、""、()、[]、{} 

其他的所有都视为真,也就是 1 ,包括各类数字、字母等。

>>> print(True==1)
True
>>> print(True-1)
0
>>> print(True+False+5)
6
>>> print(bool(5)) # 给定参数转换为布尔类型,无则返回 False
True

条件和条件语句 if 与 else

直接用 if 就可以了,但请注意代码的缩进:

num1=int(input("请输入一个整数:"))
num2=int(input("请再输入一个整数: "))
max=num1
if max<num2:
    max=num2
print("这两个整数最大的是:",max)
请输入一个整数:100
请再输入一个整数: 150
这两个整数最大的是: 150

直接用 eles 也可,但请注意代码的缩进:

year=int(input("请输入一个公元年份:"))
if(year % 4==0 and  year%100!=0) or (year%400==0):
    print("公元",year,"年是闰年")
else:
    print("公元",year,"年是平年")

请输入一个公元年份:2020
公元 2020 年是闰年

条件和条件语句 elif 多分支选择

使用 if...elif...else 的结构来实现:

score=int(input("请输入学生成绩:"))
grades=("优秀","良好","中","合格","不合格")
if score>=90:
    grade=grades[0]
elif score>=80:
    grade=grades[1]
elif score>=70:
    grade=grades[2]
elif score>=60:
    grade=grades[3]
else:
    grade=grades[4]
print("该生成绩为:",grade)

请输入学生成绩:75
该生成绩为: 中

条件和条件语句 选择结构嵌套

# 本程序用于求一元二次方程的根
import math
a=float(input("请输入一元二次方程的二次系数:"))
b=float(input("请输入方程的一次系数:"))
c=float(input("请输入方程的常数项:"))
if a==0:
    print("方程二次系数不能为0!")
else:
    delta=b*b-4*a*c
    x=-b/(2*a)
    if delta==0:
        print("方程有唯一解,即X=",x)
    elif delta>0:
        x1=x-math.sqrt(delta)/(2*a)
        x2=x-math.sqrt(delta)/(2*a)
        print("方程有个两个实根,分别是X1=",x1,",X2=",x2)
    else:
        x1=(-b+complex(0,1)*math.sqrt((-1)*delta))/(2*a)
        x2=(-b-complex(0,1)*math.sqrt((-1)*delta))/(2*a)
        print("方程有个两个虚根,分别是X1=",x1,",X2=",x2)

请输入一元二次方程的二次系数:2
请输入方程的一次系数:4
请输入方程的常数项:24
方程有个两个虚根,分别是X1= (-1+3.3166247903554j) ,X2= (-1-3.3166247903554j)

循环结构 while

利用 while 以实现循环:

sum=0
n=0
while n<=100:
    sum=sum+n
    n+=1
print("1+2+3+...+100=",sum)

1+2+3+...+100= 5050

它也可以同 else 一起使用:

count=int(input("请输入一个整数:"))
while count<10:
    print(count,"比10小")
    count+=1
else:
    print(count,"不比10小")

请输入一个整数:4
4 比10小
5 比10小
6 比10小
7 比10小
8 比10小
9 比10小
10 不比10小

循环结构 for

for 语句是循环结构中应用比较广泛的循环控制语句,特别适合循环次数确定的情况,可配合 range 一起食用:

格式为:for 目标变量 in 序列对象,range([start,]end[,step]):

for i in range(5):
    print(i)
0
1
2
3
4

for i in range(2,5):
    print(i)
2
3
4

for i in range(2,20,3): # 步长为 3
    print(i)

用for循环计算1+2+3+...+100的值:

sum=0
for i in range(101):
    sum=sum+i
print("1+2+3+...+100=",sum)

1+2+3+...+100= 5050

再举个栗子:

words=["蓝小柠 ","是个 ","可爱的 ","小盆友"]
for word in words:
    print(word,end="")

蓝小柠 是个 可爱的 小盆友

循环结构 跳出循环 break语句

利用 break 语句用在循环体内,迫使所在循环立即终止,马上跳出循环体,继续执行循环体后面的语句:

# 求两个整数的最大公约数
# 基本方法是先求两者较小的那个,然后循环变量从较小的变量向1倒退,当循环变量同时被两者整数时,最大公约数就找到了,立即退出循环。
m=int(input("请输入正整数:"))
n=int(input("请再输入一个正整数:"))
min=m
if m>n:
    min=n
for i in range(min,1,-1):
    if m%i==0 and n%i==0:
        print(m,"和",n,"的最大公约数是:",i)
        break

请输入正整数:105
请再输入一个正整数:70
105 和 70 的最大公约数是: 35

注意:break只能用于while和for语句构成的循环体中;在循环嵌套的情况下,break只能终止并跳出最近的一层循环体。

循环结构 continue语句

当在循环结构中遇到 continue 语句时,程序将跳过 continue 语句后面尚未执行的语句,重新开始下一轮循环,也就是说只结束本次循环的执行,并不终止整个循环的执行:

# 求1到100之间全部奇数之和。
x=y=0
while True:
    x+=1
    if not(x%2==0):
        continue
    elif x>100:
        break
    else:
        y+=x
print("y=",y)

y= 2550

循环结构 pass语句

pass 语句可以用来占个坑,但是啥用没有:

>>> for i in range(10):
        pass

列表推导 序列解包

序列解包是一种很好玩的 赋值 方法,例如:

>>> x,y,z=1,2,3
>>> print(x,y,z)
1 2 3

也可以用来交换变量的值:

>>> x,y,z=1,2,3
>>> x,y=y,x
>>> print(x,y,z)
2 1 3

可以使用*运算符收集多余的值,如:

>>> a,b,*rest=[1,2,3,4]
>>> print(a,",",b,",",rest)
1 , 2 , [3, 4]

>>> a,*middle,c=[1,2,3,4,5,6]
>>> print(a,",",middle,",",c)
1 , [2, 3, 4, 5] , 6

列表推导 增强赋值

将自身的赋值语句的运算符 移动到左侧 ,如:

>>> x=5
>>> x+=1 # 等价于 x=x+1
>>> print(x)
6

>>> x=5
>>> x*=4
>>> print(x)
20

>>> BleShi="蓝小柠"
>>> BleShi*=6
>>> print(BleShi)
蓝小柠蓝小柠蓝小柠蓝小柠蓝小柠蓝小柠

列表推导 简单推导

比如需要生成一个平方数列表:

square=[]
for i in range(10):
    square.append(i*i)
print(square)

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

但使用 列表推导 ,我们就可以这么写:

print([x*x for x in range(10)])

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

如只想显示那些能被3整除的平方值:

square=[] # 传统写法
for i in range(10):
    if i%3==0: # 注意:i能被3整除和i的平方能被3整除等价。  
        square.append(i*i)   
print(square)

[0, 9, 36, 81]

print([x*x for x in range(10) if x%3==0]) # 列表推导
    
[0, 9, 36, 81]

5.函数和面向对象

Pic21

面对对象编程,冲鸭!

函数的概念 函数的定义

计算机程序设计语言中的函数是一种具有独立性的子程序和可复用的代码块,这种结构是为了重复利用代码而设计的。

函数的定义使用 def 语句,后面跟上函数名,括号,括号里面是参数,注意最后还有冒号。

def fibs(num): # 将斐波那契数列写成如下的函数
    result=[0,1]
    for i in range(num-2):
        result.append(result[-2]+result[-1])
    return result

print(fibs(10)) # 直接这样输出结果就可
print(fibs(30))

fibs 函数的定义中,注意 result 表示斐波那契数列, return 语句用于指明函数的返回值,函数执行到 return 语句就结束了。

函数的参数 列表作为参数

函数作用域有限制,内部修改参数的值,外部变量的值不发生变化。

def change_para(name):
    name="小柠"
    print("函数内变量的值是:",name) # 会输出 函数内变量的值是:小柠
    return 
name="蓝小柠"
change_para(name)
print("函数外部变量的值是:",name) # 会输出 函数内变量的值是:蓝小柠

但以上限制域只对于 数值逻辑值字符串 这种不可变类型有效,对于可变的类型就不行惹

def change_para(names):
    names.append("袁绍")
    print("函数内列表的值:",names)
    return 
names=["曹操","孙权","刘备"]
change_para(names)
print("函数外列表的值:",names)

函数内列表的值: ['曹操', '孙权', '刘备', '袁绍']
函数外列表的值: ['曹操', '孙权', '刘备', '袁绍']

我们发现遇到了 列表 的时候,因都是对于同一个列表进行操作,所以发生冲突,我们可以用创造副本的方式来解决:

def change_para(names):
    names.append("袁绍")
    print("函数内列表的值:",names)
    return 
names=["曹操","孙权","刘备"]
change_para(names[:])            # 注意:这里用切片产生了列表的副本。
print("函数外列表的值:",names)

函数内列表的值: ['曹操', '孙权', '刘备', '袁绍']
函数外列表的值: ['曹操', '孙权', '刘备']

这样就可以惹,这里使用的创造副本用的是 浅复制 ,遇到嵌套的列表要使用 深复制

函数的参数 位置参数和关键字参数

我们自定义的函数也可以拥有多个参数:

def show_provinceinfo(provincename,population,area):
    print(provincename,"的人口是",population,"万,面积是",area,"万平方公里。")
    return
show_provinceinfo(area=48.6,population=8341,provincename="四川省") # 指定了参数的名字给他们赋值,避免顺序问题

四川省 的人口是 8341 万,面积是 48.6 万平方公里。

函数的参数 收集参数

如有多个同样类型的数据,我们可以用 * 的方式来实现元组解包:

def print_district(city,*district):
    print(city,"包括以下地区:",*district)   # 元组解包
print_district("上海市","青浦区","松江区","闵行区","浦东新区")
上海市 包括以下地区: 青浦 松江 闵行 浦东新区

* 的收集参数最好在最后的位置,否则必须用名称指定后面的参数,不然就会引起混淆。

我们还可以用两个*收集关键字参数,也就是字典,例如:

def print_params(**params):
    print(params)
print_params(x=1,y=2,z=3)

{'x': 1, 'y': 2, 'z': 3}

变量的作用域

局部变量和全局变量名字相同,但是他们互不干扰:

def foo():
    x=2333
    print("局部变量x的值:",x)
x=5887415157
foo()
print("全局变量x的值:",x)

局部变量x的值: 2333
全局变量x的值: 5887415157

如在函数内需要修改全局变量的值,则先用 global 关键字声明:

def foo():
    global x
    x+=50
    print("函数内x的值:",x)
x=100
foo()
print("函数外x的值:",x)

函数内x的值: 150
函数外x的值: 150

函数内需要使用全局变量,则可以使用 globals() 函数来访问:

def foo():
    x=50
    x+=globals()["x"]
    print("全局变量x和局部变量x的值:",x)
x=100
foo()

作用域与函数的递归

求1到100的和,就是100加上1到99的和;求1到99的和,就是99加上1到98的和;1到98的和,就是98加上1到97的和......这样一直下去,最后就到了1到2的和:

def resur_sum(num):
    if num==1:
        return 1
    else:
        return num+resur_sum(num-1) # 我调用我自己
print("1到100的和是:",resur_sum(100))

1到100的和是: 5050

不能无穷递归哦!

一切都是对象 数据是对象

可以用点 . 运算符访问属性和方法,例如:

a=4+3j              # 创建一个复数对象
print(a.real)       #显示这个复数的实部(对象的属性)
b=[1,2,3,4]         #创建一个列表对象
b.append(5)         #使用对象的方法添加元素
print(b)

一切都是对象 对象存储位置与类型

id()函数可以查看变量的位置,大致相当于内存地址编码:

x=5
print(id(x))
x=10
print(id(x))
for x in range(10):
    print(id(x))

一切都是对象 引用计数与垃圾回收

给一个对象分配一个名称,或者将其放到容器中(列表、元组或字典等),都会增加对象的引用计数:

a=37       #创建一个值为37的对象
b=a        #增加对象37的引用计数
c=[]
c.append(b)   #增加对象37的引用计数

引用计数就无法归零,对象不用以后也无法销毁,这就造成了内存浪费,或者叫做内存泄漏,内存中始终存在一段无用的代码。

一切都是对象 引用与复制

程序中,进行 a=b 这样的赋值时,就会创建一个对b的新引用。对于数值和字符串这样的不可变对象,增加的引用只是多了个名字。但对于 列表字典 这样的可变对象就不一样了:

a=[1,2,3,4]
b=a
print(b is a)
b[2]=100 # 同时修改了 a 和 b
print(b)
print(a)

True
[1, 2, 100, 4]
[1, 2, 100, 4]

所以,要创建对象的副本,而不是增加新的引用。

浅复制 的方法:

a=[1,2,[3,4]]
b=list(a)         # 创建a的浅复制
print("a和b是一个对象吗:",b is a)
b.append(100)     #浅复制的对象添加元素
print("浅复制的对象现在是:",b)
print("原来的对象现在是:",a)
b[2][0]=-100      #修改一个元素 
print("浅复制的对象现在是:",b)
print("原来的对象现在是:",a)

注意这里 ab 是独立的两个对象,但是他们的元素是共享的,对可变元素来说,修改之后将影响另外一个对象。

所以我们又有了 深复制 ,需要使用到库中的 copy 模块中的 copy.deepcopy() 函数进行:

import copy
a=[1,2,[3,4]]
b=copy.deepcopy(a)
b[2][0]=100
print(a,b)

类与对象 创建类

利用 class 类名(father-class): 的方式,最后定义类的内部实现:

class Cat:
    def describe(self):
        print("这是一只猫!")
cat=Cat()
cat.describe()           # 用对象名.成员的方法使用类的方法,不需要输入self参数。

Last Modified: October 19, 2023