Python 笔记(配套 b 站视频使用--精简版)
Python 特性:
解释性
Python 默认不支持中文
python3 可以解释中文
先用 Python3 版本进行开发
再用 Python 、 执行
交互式(验证和学习小型或局部代码)
python(3)
>>> **365
…
exit() or crtl + D
ipython3 (支持自动补全,自动缩进,支持 bash shell 终端命令等)
集成开发环境(IDE) integrated Development Environment
PyCharm
安装
1)下载 PyCharm
2) tar -zxvf
3) sudo mv /opt/
4) cd /opt/
5) ./
在欢迎界面点击下边的 Configure–>选择“Create Desktop Entry”–>勾选“Create the entry for all
users”–>OK,
之后可以在所有程序里找到 pycharm 图标,右键–>添加到收藏夹
卸载
1)sudo rm -r /opt/
2) sudo rm -r ~/. (隐藏文件)
3)cat /usr/share/applications/
4) rm -r /usr/share/applications/
恢复初始化设置
rm -r .
单行注释
1) # 注释命令 (# 空格 内容)
2) 代码 空2格 #注释文字
多行注释
“”“
”“”
算数运算符
+ — * / //(取整) %(取余) **(平方)
计算三大件: CPU 内存 硬盘
程序要执行,首先需要加载到内存
程序就是用来处理数据的
变量就是用来储存数据的
格式化输出%
%s : string
%d : int
%f : float
%% : percent
print(“格式化字符串”%(变量1,变量2))
标识符和关键字
标识符: 字母 下划线 数字 (不能以数字开头,不能与关键字重名,区分大小写)
import 可以导入一个“工具包”
import keyword
print()
驼峰命名法
1)firstName
2)FirstName
判断语句(分支语句)
if :
空四格(tab)
在 python 开发中,不能混用 Tab and space!!!
“if 语句以及缩进部分的代码看成一个完整的代码块”
ctrl+/ 加入单行注释
逻辑运算符 and or not
if
elif
else
if 嵌套(逐级缩进)
增加和减少缩进 tab shift+tab
随机数:
import random
随机整数 (a,b) a-b 之间的整数
循环(while break continue)
程序三大流程(顺序流程,分支流程(判断语句),循环流程(while))
列表 [] (有序的)
关键字
元祖便利 ()
字典的遍历 {} for in 遍历字典 (无序的)
card_list = [
{},
{}
]
for card_info in card_list:
print(card_info)
字符串:
“我的外号”
‘我的外号是”大西瓜”’
str1=”hello python”
for char in str1:
print(char)
len(str1)
()
()
字符串操作(\t \r \n)
space_str = “ ”
字符串切片(适用于字符串 列表 元祖)
numstr[2:2:2] 开始,截止, 步长
numstr[-1] [-1::-1] or[::-1]逆序输出
公共方法
内置函数 len(item) del(item) max(item) min(item) cmp(item1, item2)
切片 [0,1,2,3,4,5][1:3]
+ 拼接 × 重复 in 3 in [] not in 4 not in []
for
else (没有通过 break 退出循环,循环结束后,会执行代码) (得到一个提示)
变量 流程控制 函数 模块
框架搭建(文件准备 主运行循环)
字符串判断
pass
无限循环
TODO 注释
可变类型
不可变类型,内存中的数据不允许被修改:
数字类型 int, bool, float, complex, long()
字符串 str
元组 tuple
可变类型,内存中的数据可以被修改:
列表 list
字典 dic
可变类型的数据变化,是通过方法来实现的
如果给一个可变类型的变量,赋值了一个新的数据,引用会修改
变量不再对之前的数据引用
变量改为对新赋值的数据引用
字典的 key 只能使用不可变类型的数据
局部变量的生命周期
所谓 生命周期 就是变量从 被创建 到 被系统回收 的过程
局部变量 在 函数执行时 才会被创建
函数执行结束后 局部变量 被系统回收
局部变量在生命周期 内,可以用来存储 函数内部临时使用到的数据
全局变量:
注意:函数执行时,需要处理变量时 会:
1. 首先 查找 函数内部 是否存在 指定名称 的局部变量,如果有,直接使用
2. 如果没有,查找 函数外部 是否存在 指定名称 的全局变量,如果有,直接使用
3. 如果还没有,程序报错!
全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使
用这个变量:
在函数内部,可以 通过全局变量的引用
获取对应的数据
但是,不允许直接修改全局变量的引用
—— 使用赋值语句修改全局变量的值
2) 在函数内部修改全局变量的值
如果在函数中需要修改全局变量,
需要使用 global 进行声明
global num
num = 100
4) 全局变量命名的建议
为了避免局部变量和全局变量出现
混淆,在定义全局变量时,有些公司会
有一些开发要求,例如:
全局变量名前应该增加 g_ 或者 gl_ 的前缀
定义函数时,是否接收参数,或者是否返回结果,是根据 实际的功能需求 来决定的!
1. 如果函数 内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部
2. 如果希望一个函数 执行完成后,向外界汇报执行结果,就可以增加函数的返回值
技巧
在 Python 中,可以 将一个元组 使用 赋值语句 同时赋值给 多个变量
注意:变量的数量需要和元组中的元素数量保持一致
解法 2 —— 不使用临时变量
# 解法 2 - 不使用临时变量
a = a + b
b = a - b
a = a - b
解法 3 —— Python 专有,利用元组
a, b = b, a a, b = (b, a)
(在函数内部,针对参数使用赋值语句,不会改变到外部的实际变量)
问题 1:在函数内部,针对参数使用 赋值语句,会不会影响调用函数时传递的 实参变量?
—— 不会!
无论传递的参数是 可变 还是 不可变
只要 针对参数 使用 赋值语句,会在 函数内部 修改 局部变量的引用,不会影响到 外部
变量的引用
问题 2:如果传递的参数是 可变类型,在函数内部,使用 方法 修改了数据的内容,同样会
影响到外部的数据
在 python 中,列表变量调用 += 本质上是在执行列表变量的 extend 方法,不会修改变量的
引用。 (列表 []+[] 合并选项)
缺省参数
定义函数时,可以给 某个参数 指定一个默认值,具有默认值的参数就叫做 缺省参数
调用函数时,如果没有传入 缺省参数 的值,则在函数内部使用定义函数时指定的 参数
默认值
函数的缺省参数,将常见的值设置为参数的缺省值,从而 简化函数的调用
例如:对列表排序的方法(reverse = FALSE/TRUE)
def print_info(name, gender=True) 缺省表达式
缺省参数的注意事项
1) 缺省参数的定义位置
必须保证 带有默认值的缺省参数 在参数列表末尾
2) 调用带有多个缺省参数的函数
在 调用函数时,如果有 多个缺省参数,需要指定参数名,这样解释器才能够知道参数
的对应关系!
多值参数(知道)
定义支持多值参数的函数
有时可能需要 一个函数 能够处理的参数 个数 是不确定的,这个时候,就可以使用 多值
参数
python 中有 两种 多值参数:
参数名前增加 一个 * 可以接收 元组
参数名前增加 两个 * 可以接收 字典
一般在给多值参数命名时,习惯使用以下两个名字
*args —— 存放 元组 参数,前面有一个 *
**kwargs —— 存放 字典 参数,前面有两个 *
args 是 arguments 的缩写,有变量的含义
kw 是 keyword 的缩写,kwargs 可以记忆 键值对参数
提示:多值参数 的应用会经常出现在网络上一些大牛开发的框架中,知道多值参数,有利
于我们能够读懂大牛的代码
num = 0
# 遍历 args 元组顺序求和
for n in args:
num += n
元组和字典的拆包(知道)
在调用带有多值参数的函数时,如果希望:
将一个 元组变量,直接传递给 args
将一个 字典变量,直接传递给 kwargs
就可以使用 拆包,简化参数的传递,拆包 的方式是:
在 元组变量前,增加 一个 *
在 字典变量前,增加 两个 *
gl_nums = (1, 2, 3)
gl_xiaoming = {"name": "小明", "age": 18}
demo(*gl_nums, **gl_xiaoming) 简化元祖和字典的传递
递归函数的特点
特点:
一个函数 内部 调用自己
函数内部可以调用其他函数,当然在函数内部也可以调用自己
代码特点
1. 函数内部的 代码 是相同的,只是针对 参数 不同,处理的结果不同
2. 当 参数满足一个条件 时,函数不再执行
这个非常重要,通常被称为递归的出口,否则 会出现死循环!
面向对象 (OOP) 基本概念
1) 面相过程 —— 怎么做?
1. 把完成某一个需求的 所有步骤 从头到尾 逐步实现
2. 根据开发需求,将某些 功能独立 的代码 封装 成一个又一个 函数
3. 最后完成的代码,就是顺序地调用 不同的函数
特点
1. 注重 步骤与过程,不注重职责分工
2. 如果需求复杂,代码会变得很复杂
3. 开发复杂项目,没有固定的套路,开发难度很大!
2) 面向对象 —— 谁来做?
相比较函数,面向对象 是 更大 的 封装,根据 职责 在 一个对象中 封装 多个方
法
1. 在完成某一个需求前,首先确定 职责 —— 要做的事情(方法)
2. 根据 职责 确定不同的 对象,在 对象 内部封装不同的 方法(多个)
3. 最后完成的代码,就是顺序地让 不同的对象 调用 不同的方法
特点
1. 注重 对象和职责,不同的对象承担不同的职责
2. 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
3. 需要在面向过程基础上,再学习一些面向对象的语法
类
类 是对一群具有 相同 特征 或者 行为 的事物的一个统称,是抽象的,不能直接使用
特征 被称为 属性
行为 被称为 方法
类 就相当于制造飞机时的图纸,是一个 模板,是 负责创建对象的
对象
对象 是 由类创建出来的一个具体存在,可以直接使用
由 哪一个类 创建出来的 对象,就拥有在 哪一个类 中定义的:
属性
方法
对象 就相当于用 图纸 制造 的飞机
在程序开发中,应该 先有类,再有对象
类和对象的关系
类是模板,对象 是根据 类 这个模板创建出来的,应该 先有类,再有对象
类 只有一个,而 对象 可以有很多个
不同的对象 之间 属性 可能会各不相同
类 中定义了什么 属性和方法,对象 中就有什么属性和方法,不可能多,也不可能少
在程序开发中,要设计一个类,通常需要满足一下三个要素:
1. 类名 这类事物的名字,满足大驼峰命名法
2. 属性 这类事物具有什么样的特征
3. 方法 这类事物具有什么样的行为
类的命名方法:大驼峰命名法
CapWords
1. 每一个单词的首字母大写
2. 单词与单词之间没有下划线
类名的确定
名词提炼法 分析 整个业务流程,出现的 名词,通常就是找到的类
属性和方法的确定
对 对象的特征描述,通常可以定义成 属性
对象具有的行为(动词),通常可以定义成 方法
提示:需求中没有涉及的属性或者方法在设计类时,不需要考虑
面向对象基础语法
目标
dir 内置函数
定义简单的类(只包含方法)
方法中的 self 参数
初始化方法
内置方法和属性
在 Python 中 对象几乎是无所不在的,我们之前学习的 变量、数据、函数 都是对象
在 Python 中可以使用以下两个方法验证:
1. 在 标识符 / 数据 后输入一个 .,然后按下 TAB 键,iPython 会提示该对象能够调用的 方
法列表
2. 使用内置函数 dir 传入 标识符 / 数据,可以查看对象内的 所有属性及方
提示 利用好 dir() 函数,在学习时很多内容就不需要死记硬背了
面向对象 是 更大 的 封装,在 一个类中 封装 多个方法,这样 通过这个类创建出来的对
象,就可以直接调用这些方法了!
在 Python 中要定义一个只包含方法的类,语法格式如下:
class 类名:
def 方法1(self, 参数列表):
pass
def 方法2(self, 参数列表):
pass
方法 的定义格式和之前学习过的函数 几乎一样
区别在于第一个参数必须是 self,大家暂时先记住,稍后介绍 self
self 参数
案例改造 —— 给对象增加属性
在 Python 中,要 给对象设置属性,非常的容易,但是不推荐使用
因为:对象属性的封装应该封装在类的内部
只需要在 类的外部的代码 中直接通过 . 设置一个属性即可
注意:这种方式虽然简单,但是不推荐使用!
使用 self 在方法内部输出每一只猫的名字
由 哪一个对象 调用的方法,方法内的 self 就是 哪一个对象的引用
在类封装的方法内部,self 就表示 当前调用方法的对象自己
调用方法时,程序员不需要传递 self 参数
在方法内部
可以通过 self. 访问对象的属性
也可以通过 self. 调用其他的对象方法
在 类的外部,通过 变量名. 访问对象的 属性和方法
在 类封装的方法中,通过 self. 访问对象的 属性和方法
提示
在日常开发中,不推荐在 类的外部 给对象增加属性
如果在运行时,没有找到属性,程序会报错
对象应该包含有哪些属性,应该 封装在类的内部
初始化方法
当使用 类名() 创建对象时,会 自动 执行以下操作:
1. 为对象在内存中 分配空间 —— 创建对象
2. 为对象的属性 设置初始值 —— 初始化方法 (init)
这个 初始化方法 就是 __init__ 方法,__init__ 是对象的内置方法
__init__ 方法是 专门 用来定义一个类 具有哪些属性的方法!
在初始化方法内部定义属性
在 __init__ 方法内部使用 self.属性名 = 属性的初始值 就可以 定义属性
定义属性之后,再使用 Cat 类创建的对象,都会拥有该属性
改造初始化方法 —— 初始化的同时设置初始值
在开发中,如果希望在 创建对象的同时,就设置对象的属性,可以对 __init__ 方法进行
改造
1. 把希望设置的属性值,定义成 __init__ 方法的参数
2. 在方法内部使用 self.属性 = 形参 接收外部传递的参数
3. 在创建对象时,使用 类名(属性1, 属性2...) 调用
内置方法和属性
| 序号 | 方法名 | 类型 | 作用 |
| :---: | :---: | :---: | --- |
| 01 | __del__ | 方法 | 对象被从内存中销毁前,会被 自动 调用 |
| 02 | __str__ | 方法 | 返回对象的描述信息,print 函数输出使用 |
__del__ 方法(知道)
在 Python 中
当使用 类名() 创建对象时,为对象 分配完空间后,自动 调用 __init__ 方法
当一个 对象被从内存中销毁 前,会 自动 调用 __del__ 方法
应用场景
__init__ 改造初始化方法,可以让创建对象更加灵活
__del__ 如果希望在对象被销毁前,再做一些事情,可以考虑一下 __del__方法
生命周期
一个对象从调用 类名() 创建,生命周期开始
一个对象的 __del__ 方法一旦被调用,生命周期结束
在对象的生命周期内,可以访问对象属性,或者让对象调用方法
__str__ 方法
在 Python 中,使用 print 输出 对象变量,默认情况下,会输出这个变量 引用的对象 是
由哪一个类创建的对象,以及 在内存中的地址(十六进制表示)
如果在开发中,希望使用 print 输出 对象变量 时,能够打印 自定义的内容,就可以利用
__str__ 这个内置方法了
注意:__str__ 方法必须返回一个字符串
目标
封装
小明爱跑步
存放家具
封装
1. 封装 是面向对象编程的一大特点
2. 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中
3. 外界 使用 类 创建 对象,然后 让对象调用方法
4. 对象方法的细节 都被 封装 在 类的内部
self. 属性 = 形参
提示:在 对象的方法内部,是可以 直接访问对象的属性 的!
提示
1. 在 对象的方法内部,是可以 直接访问对象的属性 的
2. 同一个类 创建的 多个对象 之间,属性 互不干扰!
思考:应该先开发哪一个类?
答案 —— 家具类
1. 家具简单
2. 房子要使用到家具,被使用的类,通常应该先开发
小结
主程序只负责创建 房子 对象和 家具 对象
让 房子 对象调用 add_item 方法 将家具添加到房子中
面积计算、剩余面积、家具列表 等处理都被 封装 到 房子类的内部
目标
士兵突击案例
身份运算符
封装
1. 封装 是面向对象编程的一大特点
2. 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中
3. 外界 使用 类 创建 对象,然后 让对象调用方法
4. 对象方法的细节 都被 封装 在 类的内部
一个对象的 属性 可以是 另外一个类创建的对象
假设:每一个新兵 都 没有枪
定义没有初始值的属性
在定义属性时,如果 不知道设置什么初始值,可以设置为 None
None 关键字 表示 什么都没有
表示一个 空对象,没有方法和属性,是一个特殊的常量
可以将 None 赋值给任何一个变量
fire 方法需求
1> 判断是否有枪,没有枪没法冲锋
2> 喊一声口号
3> 装填子弹
4> 射击
小结
1. 创建了一个 士兵类,使用到 __init__ 内置方法
2. 在定义属性时,如果 不知道设置什么初始值,可以设置为 None
3. 在 封装的 方法内部,还可以让 自己的 使用其他类创建的对象属性 调用已经 封装好的
方法
is 与 == 区别:
is 用于判断 两个变量 引用对象是否为同一个 (id 信息)
== 用于判断 引用变量的值 是否相等
私有属性和私有方法
在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外
部被访问到
私有属性 就是 对象 不希望公开的 属性
私有方法 就是 对象 不希望公开的 方法
定义方式
在 定义属性或方法时,在 属性名或者方法名前 增加 两个下划线,定义的就是 私有属性
或方法
私有属性,外部不能直接访问 在对象的方法内部,是可以访问对象的私有方法
私有方法,外部不能直接调用
伪私有属性和私有方法(科普)
提示:在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法
Python 中,并没有 真正意义 的 私有
在给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到
处理方式:在 名称 前面加上 _类名 => _类名__名称
# 私有属性,外部不能直接访问到
print(xiaofang._Women__age)
# 私有方法,外部不能直接调用
xiaofang._Women__secret()
继承
目标
单继承
多继承
面向对象三大特性
1. 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
2. 继承 实现代码的重用,相同的代码不需要重复的编写
3. 多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
目标
单继承
多继承
面向对象三大特性
1. 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
2. 继承 实现代码的重用,相同的代码不需要重复的编写
3. 多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
1) 继承的语法
class 类名(父类名):
pass
子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发
子类 中应该根据 职责,封装 子类特有的 属性和方法
2) 专业术语
Dog 类是 Animal 类的子类,Animal 类是 Dog 类的父类,Dog 类从 Animal 类继承
Dog 类是 Animal 类的派生类,Animal 类是 Dog 类的基类,Dog 类从 Animal 类派生
3) 继承的传递性
C 类从 B 类继承,B 类又从 A 类继承
那么 C 类就具有 B 类和 A 类的所有属性和方法
子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法
方法的重写
子类 拥有 父类 的所有 方法 和 属性
子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发
应用场景
当 父类 的方法实现不能满足子类需求时,可以对方法进行 重写 (override)
重写 父类方法有两种情况:
1. 覆盖 父类的方法
2. 对父类方法进行 扩展
1) 覆盖父类的方法
如果在开发中,父类的方法实现 和 子类的方法实现,完全不同
就可以使用 覆盖 的方式,在子类中 重新编写 父类的方法实现
具体的实现方式,就相当于在 子类中 定义了一个 和父类同名的方法并且实现
重写之后,在运行时,只会调用 子类中重写的方法,而不再会调用 父类封装的方法
2) 对父类方法进行 扩展
如果在开发中,子类的方法实现 中 包含 父类的方法实现
父类原本封装的方法实现 是 子类方法的一部分
就可以使用 扩展 的方式
在子类中 重写 父类的方法
在需要的位置使用 super().父类方法 来调用父类方法的执行
代码其他的位置针对子类的需求,编写 子类特有的代码实现
关于 super
在 Python 中 super 是一个 特殊的类
super() 就是使用 super 类创建出来的对象
最常 使用的场景就是在 重写父类方法时,调用 在父类中封装的方法实现
调用父类方法的另外一种方式(知道)
在 Python 时,如果需要调用父类的方法,还可以使用以下方式:
父类名.方法(self)
这种方式,目前在 Python 还支持这种方式
这种方法 不推荐使用,因为一旦 父类发生变化,方法调用位置的 类名 同样需要修改
提示
在开发时,父类名 和 super() 两种方式不要混用
如果使用 当前子类名 调用方法,会形成递归调用,出现死循环
父类的 私有属性 和 私有方法
1. 子类对象 不能 在自己的方法内部,直接 访问 父类的
私有属性 或 私有方法
2. 子类对象 可以通过 父类 的 公有方法 间接 访问到 私
有属性 或 私有方法
私有属性、方法 是对象的隐私,不对外公开,外界 以及
子类 都不能直接访问
私有属性、方法 通常用于做一些内部的事情
B 的对象不能直接访问 __num2 属性
B 的对象不能在 demo 方法内访问 __num2 属性
B 的对象可以在 demo 方法内,调用父类的 test 方法
父类的 test 方法内部,能够访问 __num2 属性和 __test 方法
多继承
概念
子类 可以拥有 多个父类,并且具有 所有父类 的 属性 和 方法
例如:孩子 会继承自己 父亲 和 母亲 的 特性
语法
class 子类名(父类名1, 父类名2...)
pass
问题的提出?
如果 不同的父类 中存在 同名的方法,子类对象 在调用方法时,会调用 哪一个父类中的
方法呢?
提示:开发时,应该尽量避免这种容易产生混淆的情况! —— 如果 父类之间 存
在 同名的属性或者方法,应该 尽量避免 使用多继承
Python 中的 MRO —— 方法搜索顺序(知道)
Python 中针对 类 提供了一个 内置属性 __mro__ 可以查看 方法 搜索顺序
MRO 是 method resolution order,主要用于 在多继承时判断 方法、属性 的调用 路径
print(C.__mro__)
在搜索方法时,是按照 __mro__ 的输出结果 从左至右 的顺序查找的
如果在当前类中 找到方法,就直接执行,不再搜索
如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
如果找到最后一个类,还没有找到方法,程序报错
新式类与旧式(经典)类
object 是 Python 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使
用 dir 函数查看.
经典类:不以 object 为基类的类,不推荐使用
新式类:以 object 为基类的类,推荐使用
在 Python 中定义类时,如果没有指定父类,会 默认使用 object 作为该类的 基类 —
— Python 中定义的类都是 新式类
在 Python 中定义类时,如果没有指定父类,则不会以 object 作为 基类
目标
多态
面向对象三大特性
1. 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中
定义类的准则
2. 继承 实现代码的重用,相同的代码不需要重复的编写
设计类的技巧
子类针对自己特有的需求,编写特定的代码
3. 多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果
多态 可以 增加代码的灵活度
以 继承 和 重写父类方法 为前提
是调用方法的技巧,不会影响到类的内部设计
类属性和类方法
目标
类的结构
类属性和实例属性
类方法和静态方法
类的结构
术语 —— 实例
1. 使用面相对象开发,第 1 步 是设计 类
2. 使用 类名 () 创建对象,创建对象 的动作有两步:
1) 在内存中为对象 分配空间
2) 调用初始化方法 __init__ 为 对象初始化
3. 对象创建后,内存 中就有了一个对象的 实实在在 的存在 —— 实例
因此,通常也会把:
1. 创建出来的 对象 叫做 类 的 实例
2. 创建对象的 动作 叫做 实例化
3. 对象的属性 叫做 实例属性
4. 对象调用的方法 叫做 实例方法
在程序执行时:
1. 对象各自拥有自己的 实例属性
2. 调用对象方法,可以通过 self.
访问自己的属性
调用自己的方法
结论
每一个对象 都有自己 独立的内存空间,保存各自不同的属性
多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法内
部
类是一个特殊的对象
Python 中 一切皆对象:
class AAA: 定义的类属于 类对象
obj1 = AAA() 属于 实例对象
在程序运行时,类 同样 会被加载到内存
在 Python 中,类 是一个特殊的对象 —— 类对象
在程序运行时,类对象 在内存中 只有一份,使用 一个类 可以创建出 很多个对象实例
除了封装 实例 的 属性 和 方法外,类对象 还可以拥有自己的 属性 和 方法
1. 类属性
2. 类方法
通过 类名. 的方式可以 访问类的属性 或者 调用类的方法
类属性和实例属性
概念和使用
类属性 就是给 类对象 中定义的 属性
通常用来记录 与这个类相关 的特征
类属性 不会用于记录 具体对象的特征
示例需求
定义一个 工具类
每件工具都有自己的 name
需求 —— 知道使用这个类,创建了多少个工具对象
使用赋值语句,定义类属性,记录创建工具对象的总数
属性的获取机制(科普)
在 Python 中 属性的获取 存在一个 向上查找机制
因此,要访问类属性有两种方式:
1. 类名.类属性
2. 对象.类属性 (不推荐)
注意
如果使用 对象.类属性 = 值 赋值语句,只会 给对象添加一个属性,而不会影响到 类属
性的值
类方法和静态方法
类方法
类属性 就是针对 类对象 定义的属性
使用 赋值语句 在 class 关键字下方可以定义 类属性
类属性 用于记录 与这个类相关 的特征
类方法 就是针对 类对象 定义的方法
在 类方法 内部可以直接访问 类属性 或者调用其他的 类方法
@classmethod
def 类方法名(cls):
pass
类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法
类方法的 第一个参数 应该是 cls
由 哪一个类 调用的方法,方法内的 cls 就是 哪一个类的引用
这个参数和 实例方法 的第一个参数是 self 类似
提示 使用其他名称也可以,不过习惯使用 cls
1. 通过 类名. 调用 类方法,调用方法时,不需要传递 cls 参数
2. 在方法内部
可以通过 cls. 访问类的属性
也可以通过 cls. 调用其他的类方法
在类方法内部,可以直接使用 cls 访问 类属性 或者 调用类方法
静态方法
在开发时,如果需要在 类 中封装一个方法,这个方法:
既 不需要 访问 实例属性 或者调用 实例方法
也 不需要 访问 类属性 或者调用 类方法
这个时候,可以把这个方法封装成一个 静态方法
@staticmethod
def 静态方法名():
pass
静态方法 需要用 修饰器 @staticmethod 来标识,告诉解释器这是一个静态方法
通过 类名. 调用 静态方法
方法综合案例
需求
1. 设计一个 Game 类
2. 属性:
定义一个 类属性 top_score 记录游戏的 历史最高分
定义一个 实例属性 player_name 记录 当前游戏的玩家姓名
3. 方法:
静态方法 show_help 显示游戏帮助信息
类方法 show_top_score 显示历史最高分
实例方法 start_game 开始当前玩家的游戏
4. 主程序步骤
1) 查看帮助信息
2) 查看历史最高分
3) 创建游戏对象,开始游戏
案例小结
1. 实例方法 —— 方法内部需要访问 实例属性
实例方法 内部可以使用 类名. 访问类属性
2. 类方法 —— 方法内部 只 需要访问 类属性
3. 静态方法 —— 方法内部,不需要访问 实例属性 和 类属性
提问
如果方法内部 即需要访问 实例属性,又需要访问 类属性,应该定义成什么方法?
答案
应该定义 实例方法
因为,类只有一个,在 实例方法 内部可以使用 类名. 访问类属性
单例
目标
单例设计模式
__new__ 方法
Python 中的单例
01. 单例设计模式
设计模式
设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对
某一特定问题 的成熟的解决方案
使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
单例设计模式
目的 —— 让 类 创建的对象,在系统中 只有 唯一的一个实例
每一次执行 类名() 返回的对象,内存地址是相同的
02. __new__ 方法
使用 类名 () 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间
__new__ 是一个 由 object 基类提供的 内置的静态方法,主要作用有两个:
1) 在内存中为对象 分配空间
2) 返回 对象的引用
Python 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给 __init__ 方法
重写 __new__ 方法 的代码非常固定!
重写 __new__ 方法 一定要 return super().__new__(cls)
否则 Python 的解释器 得不到 分配了空间的 对象引用,就不会调用对象的初始化方法
注意:__new__ 是一个静态方法,在调用时需要 主动传递 cls 参数
03. Python 中的单例
单例 —— 让 类 创建的对象,在系统中 只有 唯一的一个实例
1. 定义一个 类属性,初始值是 None,用于记录 单例对象的引用
2. 重写 __new__ 方法
3. 如果 类属性 is None,调用父类方法分配空间,并在类属性中记录结果
4. 返回 类属性 中记录的 对象引用
只执行一次初始化工作
在每次使用 类名() 创建对象时,Python 的解释器都会自动调用两个方法:
__new__ 分配空间
__init__ 对象初始化
在上一小节对 __new__ 方法改造之后,每次都会得到 第一次被创建对象的引用
但是:初始化方法还会被再次调用
需求
让 初始化动作 只被 执行一次
解决办法
1. 定义一个类属性 init_flag 标记是否 执行过初始化动作,初始值为 False
2. 在 __init__ 方法中,判断 init_flag,如果为 False 就执行初始化动作
3. 然后将 init_flag 设置为 True
4. 这样,再次 自动 调用 __init__ 方法时,初始化动作就不会被再次执行 了
异常
目标
异常的概念
捕获异常
异常的传递
抛出异常
01. 异常的概念
程序在运行时,如果 Python 解释器 遇到 到一个错误,会停止程序的执行,并且提示一
些错误信息,这就是 异常
程序停止执行并且提示错误信息 这个动作,我们通常称之为:抛出 (raise) 异常
程序开发时,很难将 所有的特殊情况 都处理的面面俱到,通过 异常捕获 可以针对突发事件
做集中的处理,从而保证程序的 稳定性和健壮性
02. 捕获异常
简单的捕获异常语法
在程序开发中,如果 对某些代码的执行不能确定是否正确,可以增加 try(尝试) 来 捕获
异常
捕获异常最简单的语法格式:
try: 尝试执行的代码
except: 出现错误的处理
try 尝试,下方编写要尝试代码,不确定是否能够正常执行的代码
except 如果不是,下方编写尝试失败的代码
错误类型捕获
在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不
同的响应,这个时候,就需要捕获错误类型了
语法如下:
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except (错误类型2, 错误类型3):
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s" % result)
当 Python 解释器 抛出异常 时,最后一行错误信息的第一个单词,就是错误类型
捕获未知错误
在开发时,要预判到所有可能出现的错误,还是有一定难度的
如果希望程序 无论出现任何错误,都不会因为 Python 解释器 抛出异常而被终止,可以
再增加一个 except
except Exception as result:
print("未知错误 %s" % result)
异常捕获完整语法
在实际开发中,为了能够处理复杂的异常情况,完整的异常语法如下:
提示:
有关完整语法的应用场景,在后续学习中,结合实际的案例会更好理解
现在先对这个语法结构有个印象即可
else 只有在没有异常时才会执行的代码
finally 无论是否有异常,都会执行的代码
03. 异常的传递
异常的传递 —— 当 函数 / 方法 执行 出现异常,会 将异常传递 给 函数 / 方法 的 调
用一方
如果 传递到主程序,仍然 没有异常处理,程序才会被终止
提示
在开发中,可以在主函数中增加 异常捕获
而在主函数中调用的其他函数,只要出现异常,都会传递到主函数的 异常捕获 中
这样就不需要在代码中,增加大量的 异常捕获,能够保证代码的整洁
04. 抛出 raise 异常
应用场景
在开发中,除了 代码执行出错 Python 解释器会 抛出 异常之外
还可以根据 应用程序 特有的业务需求 主动抛出异常
示例
提示用户 输入密码,如果 长度少于 8,抛出 异常
注意
当前函数 只负责 提示用户输入密码,如果 密码长度不正确,需要其他的函数进行额外
处理
因此可以 抛出异常,由其他需要处理的函数 捕获异常
抛出异常
Python 中提供了一个 Exception 异常类
在开发时,如果满足 特定业务需求时,希望 抛出异常,可以:
1. 创建 一个 Exception 的 对象
2. 使用 raise 关键字 抛出 异常对象
模块和包
目标
模块
包
发布模块
01. 模块
模块的概念
模块是 Python 程序架构的一个核心概念
每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块
模块名 同样也是一个 标识符,需要符合标识符的命名规则
在模块中定义的 全局变量 、函数、类 都是提供给外界直接使用的 工具
模块 就好比是 工具包,要想使用这个工具包中的工具,就需要先 导入 这个模块
模块的两种导入方式
1)import 导入
import 模块名1, 模块名2
提示:在导入模块时,每个导入应该独占一行
import 模块名1
import 模块名2
导入之后
通过 模块名. 使用 模块提供的工具 —— 全局变量、函数、类
使用 as 指定模块的别名
如果模块的名字太长,可以使用 as 指定模块的名称,以方便在代码中的使用
import 模块名1 as 模块别名
注意:模块别名 应该符合 大驼峰命名法
2)from...import 导入
如果希望 从某一个模块 中,导入 部分 工具,就可以使用 from ... import 的方式
import 模块名 是 一次性 把模块中 所有工具全部导入,并且通过 模块名 / 别名. 访问
# 从 模块 导入 某一个工具
from 模块名1 import 工具名
导入之后
不需要 通过 模块名.
可以直接使用 模块提供的工具 —— 全局变量、函数、类
注意
如果 两个模块,存在 同名的函数,那么 后导入模块的函数,会 覆盖掉先导入的
函数
开发时 import 代码应该统一写在 代码的顶部,更容易及时发现冲突
一旦发现冲突,可以使用 as 关键字 给其中一个工具起一个别名
from...import *(知道)
# 从 模块 导入 所有工具
from 模块名1 import *
这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查
模块的搜索顺序 [扩展]
Python 的解释器在 导入模块 时,会:
1. 搜索 当前目录 指定模块名的文件,如果有就直接导入
2. 如果没有,再搜索 系统目录
在开发时,给文件起名,不要和 系统的模块文件 重名
Python 中每一个模块都有一个内置属性 __file__ 可以 查看模块 的 完整路径
注意:如果当前目录下,存在一个 的文件,程序就无法正常执行了!
这个时候,Python 的解释器会 加载当前目录 下的 而不会加载 系统的 random
模块
原则 —— 每一个文件都应该是可以被导入的
一个 独立的 Python 文件 就是一个 模块
在导入文件时,文件中 所有没有任何缩进的代码 都会被执行一遍!
实际开发场景
在实际开发中,每一个模块都是独立开发的,大多都有专人负责
开发人员 通常会在 模块下方 增加一些测试代码
仅在模块内使用,而被导入到其他文件中不需要执行
__name__ 属性
__name__ 属性可以做到,测试模块的代码 只在测试情况下被运行,而在 被导
入时不会被执行!
__name__ 是 Python 的一个内置属性,记录着一个 字符串
如果 是被其他文件导入的,__name__ 就是 模块名
如果 是当前执行的程序 __name__ 是 __main__
# 根据 __name__ 判断是否执行下方代码
if __name__ == "__main__":
main()
02. 包(Package)
概念
包 是一个 包含多个模块 的 特殊目录
目录下有一个 特殊的文件
包名的 命名方式 和变量名一致,小写字母 + _
好处
使用 import 包名 可以一次性导入 包 中 所有的模块
03. 发布模块(知道)(构建-安装-卸载)
如果希望自己开发的模块,分享 给其他人,可以按照以下步骤操作
制作发布压缩包步骤
1) 创建
的文件
2) 构建模块
$ python3 build
3) 生成发布压缩包
$ python3 sdist
注意:要制作哪个版本的模块,就使用哪个版本的解释器执行!
文件
目标
文件的概念
文件的基本操作
文件 / 文件夹的常用操作
文本文件的编码方式
01. 文件的概念
文件的概念和作用
计算机的 文件,就是存储在某种 长期储存设备 上的一段 数据
长期存储设备包括:硬盘、U 盘、移动硬盘、光盘...
文件的作用
将数据长期保存下来,在需要的时候使用
文件的存储方式
在计算机中,文件是以 二进制 的方式保存在磁盘上的
文本文件和二进制文件
文本文件
可以使用 文本编辑软件 查看
本质上还是二进制文件
例如:python 的源程序
二进制文件
保存的内容 不是给人直接阅读的,而是 提供给其他软件使用的
例如:图片文件、音频文件、视频文件等等
二进制文件不能使用 文本编辑软件 查看
02. 文件的基本操作
操作文件的套路
在 计算机 中要操作文件的套路非常固定,一共包含三个步骤:
1. 打开文件
2. 读、写文件
读 将文件内容读入内存
写 将内存内容写入文件
3. 关闭文件
open 函数负责打开文件,并且返回文件对象
read/write/close 三个方法都需要通过 文件对象 来调用
read 方法 —— 读取文件
open 函数的第一个参数是要打开的文件名(文件名区分大小写)
如果文件 存在,返回 文件操作对象
如果文件 不存在,会 抛出异常
read 方法可以一次性 读入 并 返回 文件的 所有内容
close 方法负责 关闭文件
如果 忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问
注意:read 方法执行后,会把 文件指针 移动到 文件的末尾
文件指针(知道)
文件指针 标记 从哪个位置开始读取数据
第一次打开 文件时,通常 文件指针会指向文件的开始位置
当执行了 read 方法后,文件指针 会移动到 读取内容的末尾
默认情况下会移动到 文件末尾
频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读、只写的方式
来操作文件
按行读取文件内容
read 方法默认会把文件的 所有内容 一次性读取到内存
如果文件太大,对内存的占用会非常严重
readline 方法
readline 方法可以一次读取一行内容
方法执行后,会把 文件指针 移动到下一行,准备再次读取
文件读写案例 —— 复制文件
目标
用代码的方式,来实现文件复制过程
小文件复制
打开一个已有文件,读取完整内容,并写入到另外一个文件
大文件复制
打开一个已有文件,逐行读取内容,并顺序写入到另外一个文件
03. 文件 / 目录的常用管理操作
在 终端 / 文件浏览器、 中可以执行常规的 文件 / 目录 管理操作,例如:
创建、重命名、删除、改变路径、查看目录内容、……
在 Python 中,如果希望通过程序实现上述功能,需要导入 os 模块
UTF-8 编码格式
计算机中使用 1~6 个字节 来表示一个 UTF-8 字符,涵盖了 地球上几乎所有地区的文字
大多数汉字会使用 3 个字节 表示
UTF-8 是 UNICODE 编码的一种编码格式
在 Python 文件的 第一行 增加以下代码,解释器会以 utf-8 编码来处理 python 文件
# *-* coding:utf8 *-*
这方式是官方推荐使用的!
也可以使用
# coding=utf8
eval 函数
eval() 函数十分强大 —— 将字符串 当成 有效的表达式 来求值 并 返回计算结果
python3 -m 判断 pygame 成功安装否?
目标
1. 项目准备
2. 使用 pygame 创建图形窗口
3. 理解 图像 并实现图像绘制
4. 理解 游戏循环 和 游戏时钟
5. 理解 精灵 和 精灵组
项目准备
1. 新建 飞机大战 项目
2. 新建一个 hm_01_pygame 入门.py
3. 导入 游戏素材图片
游戏的第一印象
把一些 静止的图像 绘制到 游戏窗口 中
根据 用户的交互 或其他情况,移动 这些图像,产生动画效果
根据 图像之间 是否发生重叠,判断 敌机是否被摧毁 等其他情况
精灵
在游戏开发中,通常把 显示图像的对象 叫做精灵 Sprite
精灵 需要 有 两个重要的属性
image 要显示的图像
rect 图像要显示在屏幕的位置
默认的 update() 方法什么事情也没做
子类可以重写此方法,在每次刷新屏幕时,更新精灵位置
注意: 并没有提供 image 和 rect 两个属性
需要程序员从 派生子类
并在 子类 的 初始化方法 中,设置 image 和 rect 属性
精灵组
一个 精灵组 可以包含多个 精灵 对象
调用 精灵组 对象的 update() 方法
可以 自动 调用 组内每一个精灵 的 update() 方法
调用 精灵组 对象的 draw(屏幕对象) 方法
可以将 组内每一个精灵 的 image 绘制在 rect 位置
派生精灵子类
1. 新建 文件
2. 定义 GameSprite 继承自
如果一个类的 父类 不是 object
在重写 初始化方法 时,一定要 先 super() 一下父类的 __init__ 方法
保证父类中实现的 __init__ 代码能够被正常执行
常量的定义
定义 常量 和 定义 变量 的语法完全一样,都是使用 赋值语句
常量 的 命名 应该 所有字母都使用大写,单词与单词之间使用下划线连接
1) 导入模块
在导入模块时,建议 按照以下顺序导入
1. 官方标准模块导入
2. 第三方模块导入
3. 应用程序模块导入
pygame 的 定时器 使用套路非常固定:
1. 定义 定时器常量 —— eventid
2. 在 初始化方法 中,调用 set_timer 方法 设置定时器事件
3. 在 游戏循环 中,监听定时器事件
vi 笔记
vi 文件 + 行号 (默认行首,+ 行尾)
$ vi 文件名 +行数
提示:如果只带上 + 而不指定行号,会直接定位到文件末尾
末行模式命令
命令 英文 功能
w write 保存
q quit
退出,如果没有保存,不允许
退出
q! quit 强行退出,不保存退出
命令 英文 功能
wq write & quit 保存并退出
x 保存并退出
命令线路图
1. 重复次数
在命令模式下,先输入一个数字,再跟上一个命令,可以让该命令 重复执行指定次数
2. 移动和选择(多练)
vi 之所以快,关键在于 能够快速定位到要编辑的代码行
移动命令 能够 和 编辑操作 命令 组合使用
3. 编辑操作
删除、复制、粘贴、替换、缩排
4. 撤销和重复
5. 查找替换
6. 编辑
1) 上、下、左、右
命令 功能 手指
h 向左 食指
j 向下 食指
k 向上 中指
l 向右 无名指
2) 行内移动
命令 英文 功能
w word 向后移动一个单词
b back 向前移动一个单词
0 行首
命令 英文 功能
^
行首,第一个不是空白字符的
位置
$ 行尾
3) 行数移动
命令 英文 功能
gg go 文件顶部
G go 文件末尾
数字
gg
go
移动到 数字 对应
行数
数字
G
go
移动到 数字 对应
行数
: 数字
移动到 数字 对应
行数
4) 屏幕移动
命令 英文 功能
Ctrl + b back
向上翻
页
Ctrl + f forward
向下翻
页
H Head
屏幕顶
部
M Middle
屏幕中
间
L Low
屏幕底
部
1) 段落移动
vi 中使用 空行 来区分段落
在程序开发时,通常 一段功能相关的代码会写在一起 —— 之间没有空行
命令 功能
{ 上一段
} 下一段
2) 括号切换
在程序世界中,()、[]、{} 使用频率很高,而且 都是成对出现的
命令 功能
%
括号匹配及切
换
3) 标记
命令 英文 功能
mx mark
添加标记 x,x 是 a~z 或者 A~Z 之间的任意
一个字母
'x 直接定位到标记 x 所在位置
选中文本(可视模式)
学习 复制 命令前,应该先学会 怎么样选中 要复制的代码
在 vi 中要选择文本,需要先使用 Visual 命令切换到 可视模式
vi 中提供了 三种 可视模式,可以方便程序员选择 选中文本的方式
按 ESC 可以放弃选中,返回到 命令模式
命令 模式 功能
v 可视模式
从光标位置开始按照正常模式选择
文本
V
可视行模
式
选中光标经过的完整行
Ctrl + v
可视块模
式
垂直方向选中文本
撤销和恢复撤销
在学习编辑命令之前,先要知道怎样撤销之前一次 错误的 编辑动作!
命令 英文 功能
u undo 撤销上次命令
CTRL + r redo
恢复撤销的命
令
删除文本
命令 英文 功能
x cut
删除光标所在字符,或者选中文
字
d (移动命
令)
delete 删除移动命令对应的内容
dd delete
删除光标所在行,可以 ndd 复制
多行
D delete 删除至行尾
* dw # 从光标位置删除到单词末尾
* d0 # 从光标位置删除到一行的起始位置
* d} # 从光标位置删除到段落结尾
* ndd # 从光标位置向下连续删除 n 行
* d 代码行 G # 从光标所在行 删除到 指定代码行 之间的所有代码
* d'a # 从光标所在行 删除到 标记 a 之间的所有代码
复制、粘贴
vi 中提供有一个 被复制文本的缓冲区
复制 命令会将选中的文字保存在缓冲区
删除 命令删除的文字会被保存在缓冲区
在需要的位置,使用 粘贴 命令可以将缓冲区的文字插入到光标所在位置
命令 英文 功能
y (移动命
令)
copy 复制
yy copy
复制一行,可以 nyy 复制
多行
p paste 粘贴
提示
命令 d、x 类似于图形界面的 剪切操作 —— CTRL + X
命令 y 类似于图形界面的 复制操作 —— CTRL + C
命令 p 类似于图形界面的 粘贴操作 —— CTRL + V
vi 中的 文本缓冲区同样只有一个,如果后续做过 复制、剪切 操作,之前缓冲区中的内
容会被替换
注意
vi 中的 文本缓冲区 和系统的 剪贴板 不是同一个
所以在其他软件中使用 CTRL + C 复制的内容,不能在 vi 中通过 P 命令粘贴
可以在 编辑模式 下使用 鼠标右键粘贴
替换
命令 英文 功能 工作模式
r replace 替换当前字符 命令模式
R replace
替换当前行光标后的
字符
替换模式
缩排和重复执行
命令 功能
>>
向右增加缩
进
<<
向左减少缩
进
命令 功能
.
重复上次命
令
查找
常规查找
命令 功能
/str
查找
str
查找到指定内容之后,使用 Next 查找下一个出现的位置:
n: 查找下一个
N: 查找上一个
如果不想看到高亮显示,可以随便查找一个文件中不存在的内容即可
单词快速匹配
命令 功能
*
向后查找当前光标所在
单词
#
向前查找当前光标所在
单词
在开发中,通过单词快速匹配,可以快速看到这个单词在其他什么位置使用过
查找并替换
在 vi 中查找和替换命令需要在 末行模式 下执行
记忆命令格式:
:%s///g
1) 全局替换
一次性替换文件中的 所有出现的旧文本
命令格式如下:
:%s/旧文本/新文本/g
2) 可视区域替换
先选中 要替换文字的 范围
命令格式如下:
:s/旧文本/新文本/g
3) 确认替换
如果把末尾的 g 改成 gc 在替换的时候,会有提示!推荐使用!
:%s/旧文本/新文本/gc
1. y - yes 替换
2. n - no 不替换
3. a - all 替换所有
4. q - quit 退出替换
5. l - last 最后一个,并把光标移动到行首
6. ^E 向下滚屏
7. ^Y 向上滚屏
插入命令
在 vi 中除了常用的 i 进入 编辑模式 外,还提供了以下命令同样可以进入编辑模式:
命令 英文 功能 常用
i insert
在当前字符前插入文
本
常用
I insert 在行首插入文本 较常用
a append
在当前字符后添加文
本
A append 在行末添加文本 较常用
o
在当前行后面插入一
空行
常用
O
在当前行前面插入一
空行
常用
05. 分屏命令
属于 vi 的高级命令 —— 可以 同时编辑和查看多个文件
末行命令扩展
末行命令 主要是针对文件进行操作的:保存、退出、保存 & 退出、搜索 & 替换、另存、
新建、浏览文件
命令 英文 功能
:e . edit
会打开内置的文件浏览器,浏览要当前目录下
的文件
:n 文件
名
new 新建文件
:w 文件
名
write
另存为,但是仍然编辑当前文件,并不会切换
文件
提示:切换文件之前,必须保证当前这个文件已经被保存!
已经学习过的 末行命令:
命令 英文 功能
:w write 保存
:q quit
退出,如果没有保存,不允许
退出
:q! quit 强行退出,不保存退出
:wq write & quit 保存并退出
:x 保存并退出
:%s///gc 确认搜索并替换
分屏命令
使用 分屏命令,可以 同时编辑和查看多个文件
命令 英文 功能
:sp [文件名] split
横向增加分
屏
:vsp [文件
名]
vertical split
纵向增加分
屏
1) 切换分屏窗口
分屏窗口都是基于 CTRL + W 这个快捷键的,w 对应的英文单词是 window
命令 英文 功能
w window 切换到下一个窗口
r reverse 互换窗口
c close
关闭当前窗口,但是不能关闭最后一个窗
口
q quit
退出当前窗口,如果是最后一个窗口,则
关闭 vi
o other 关闭其他窗口
2) 调整窗口大小
分屏窗口都是基于 CTRL + W 这个快捷键的,w 对应的英文单词是 window
命令 英文 功能
+
增加窗口高
度
-
减少窗口高
度
>
增加窗口宽
度
<
减少窗口宽
度
=
等分窗口大
小
调整窗口宽高的命令可以和数字连用,例如:5 CTRL + W + 连续 5 次增加高度