侧边栏壁纸
博主头像
无知无畏 博主等级

行动起来,活在当下

  • 累计撰写 13 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Python学习笔记

快乐玩耍
2024-11-03 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

Python学习打卡日记,日期加上学习的主题命名好了~

已经学习完成,接下来只需要将内容整理成方便复习的样子。

1. 基础语法

1.1 变量创建与赋值

1.1.1 变量的类型

  • 整形
  • 浮点型
  • 布尔型
  • 字符串型

1.1.2 变量标识符的命名

通俗命名规则:

  • 模块和包名:小写
  • 函数名:尽量全小写,单词之间用‘_’隔开
  • 类名:首字母大写,驼峰原则
  • 常量名:全大写,单词之间用‘_’隔开

1.1.3 变量的声明和赋值

删除变量时,只是删除了栈里的,堆里的对象没被删除,最后被Python的垃圾回收器处理掉。

链式赋值:

  • x = y = 123

系列解包赋值:

  • a, b, c = 1, 2, 3
  • a, b = b, a

同一运算符判断:

  • is 判断两个标识符是不是引用同一个对象,也即比较ID地址
  • == 用于判断引用变量引用对象的值是否相等,也即对比两个堆中的value
  • 【-5,256】会缓存这部分数,因此值相等的时候,地址(ID)也是一样
  • is 要比 == 效率要高

1.1.4 变量的转换与打印

  • round(),去掉小数位
  • 时间的获取:time.time()
  • 返回值为以秒为单位,小数点后面的单位为微秒

1)格式化字符串

F-String (Python 3.6+)

age = 15
result = f"小明今年{age}岁了!"
print(result)

output:小明今年15岁了!

format()

result = "你好{},小明今年{}岁了!".format(name,age)

output:你好老王,小明今年15岁了!

2)格式化数字

pi = 3.1415926
# 对 pi 进行格式化
# 格式:“:” + “填充、对齐” + “符号” +  “宽度” + "." + "位数" + "f"
result = f"圆周率{pi:.4f}是一个无限不循环小数"

# 设置小数点后四位显示
result = f"圆周率{pi:50.4f}是一个无限不循环小数"

# 设置小数点后四位显示 且占50位空间
result = f"圆周率{pi:+50.4f}是一个无限不循环小数"

# 设置小数点后四位显示 且占50位空间 加“+”号
result = f"圆周率{pi:<.4f}是一个无限不循环小数"

# 设置小数点后四位显示 向左对齐

# 向右对齐使用 > 居中显示使用 ^
result = f"圆周率{pi:*<50.4f}是一个无限不循环小数"

# 设置填充,超出实际宽度的部分进行填充,这里是用“*”填充
result = f"圆周率{pi:.2%}是一个无限不循环小数"

# 以百分号形式展示 :.0% 表示不要小数位
result = f"圆周率{pi:#b}是一个无限不循环小数"

# 表示为二进制 :b  加了
#/显示0## 表示为十六进制 :x

1.1.5 变量的逻辑运算符

基本运算符

  • Python不支持自增和自减

  • and:与

  • or:或

  • not:非

  • 优先级:常规数学运算,如果优先级错误,直接加小括号

    1. / % //

    2. < > = ≥ ≤ == ≠

    3. and or not

    4. =

1.1.6 变量的作用域与拷贝

全局变量:

  • 在函数和类定义之外声明的变量

局部变量:

  • 函数里定义的变量
  • 函数执行完即消失
  • 局部变量与全局变量同名时,优先使用局部变量,使用全局变量前声明 global variable
  • 局部变量的引用比全局变量快,优先考虑使用

浅拷贝和深拷贝

浅拷贝:

  • 不拷贝子对象的内容,只是拷贝子对象的引用

  • 拷贝了栈里的变量标识符,并且拷贝了该变量指向的堆里的对象的地址,因此作出的部分更改会

  • copy.copy()

  • 只拷贝引用
    深拷贝:

  • 会连子对象的内容也全部拷贝一份,对子对象的修改不会影响源对象

  • 拷贝了栈里的变量标识符,拷贝了该变量指向的堆里的对象,并且拷贝了堆里对象所指向的所有子对象

  • copy.deepcopy()

  • 全部拷贝到新的内存变量

nonlocal global

  • nonlocal 声明外层的局部变量
  • global 声明全局变量

LEGB 规则

Python在查找一个名字时,按照该顺序查找:

  • Local - Enclosed - Global - Built in
  • 局部变量 - 闭包 - 全局变量 - Python保留字

短路现象

指python在执行 或 or 的时候,它在运行到or前为真值的时候,即停止运行后面的代码

1.2 函数创建

1.2.1 基础函数

If 与 Else

  • If 是 流程控制语句,用来判断
  • 条件满足则执行语句
  • 为分支语句,在Python中主要使用冒号与缩进
  • Else 是 不满足 If 条件时,执行的备选代码块
  • Elif 是 If 的额外判断情况,如果情况比较多的话,建议使用Switch

随机数获取

  • 首先导入 Import random
  • 生成随机数 random.randint(start, end)

随机整数,rand int

  • 这里的上下限都是包含在生成范围内的

画图函数

Range方法

  • range(value)
# 生成一个有序整数列表
a = list(range(100))
print(a)

$ [0,1,2,3,...,99]
  • range(start, end)
# 设置起始范围与终点范围
a = list(range(3,6))
print(a)

$ [3,4,5]
  • range(start,end,step)
# 设置步长
a = list(range(0,100,20))
print(a)$ [0, 20, 40, 60, 80]

For循环及While循环

for item in nums:
    <code stock>
while <code stock>:
    <code block>
  • 调试时,代码当前高亮表示即将被执行

1.2.2 函数用法与底层分析

  • 可重用的程序代码块
  • 注重逻辑的一致性,也即功能单一

函数大致分为:

  • 内置函数
  • 标准库函数
  • 第三方函数
  • 用户自定义

如何创建自定义函数?语法如下:

  • def funcName(para1, para2):
    • Code block

函数也是一个对象,在def语句后初始化一个对象,对象具有 ID 、 类型 、 值 三要素。因此也同样,初始化后 ID 绑定到函数名,也即标识符上。

  • 实参与形参必须一一对应
  • 调用前定义函数
  • 无参数也必须保留圆括号
  • 形式参数无需声明变量类型,也不需要指定返回值类型

1.2.3 形参、实参

形参:

  • 在函数定义时,圆括号内自己设置的参数,只在函数执行过程中生效,其余时间失效
  • 属于函数,无法被外部调用
  • 值需要在调用时,从外部传入

实参:

  • 在调用函数时,传递值给函数的变量
  • 可以被函数内部调用,但不建议
  • 一般只传递值

1.2.4 返回值详解

返回值:调用函数后,返回的值

  • 使用return 语句
  • 无需预先定义
  • 返回的变量类型、数量不受限制
  • 调用函数时需要保证有变量接收
  • 执行 return 后立马结束函数

1.2.5 函数底层

Python中一切皆对象:

  • 函数定义时,系统创建了对应的对象
  • 小括号代表调用
  • 变量名存在堆里,也叫做函数标识符,函数的ID、值和类型也即函数对象在堆里
  • 函数可以作为参数传递,高阶函数的用法
  • 函数被调用时,会生成栈帧,stack frame,这里面存放局部变量。

1.2.6 参数的传递

传递可变对象:

  • Python中一切皆对象,因此参数的传递都是对象地址的传递
  • 可变实参跟形参对应一个对象时,对形参更改后,不创建对象拷贝,直接修改这个对象,因而原本的可变实参也发生对应的变化

传递不可变对象:

  • 字符串、数字、元组都是不可变对象
  • 传参数时同样是传入对象的地址
  • 但因实参不可变,因此在对形参更改时,创建实参的拷贝并执行更改操作

引用的本质,栈内存和堆内存以及内存示意图

  • 栈里放变量,对象存放在堆里。
  • 对象为上面三类,变量存放的为对象地址。

1.3 内置函数

1.3.1 eval 函数

用法如下:

很有意思的函数,可以用于动态更新代码

递归函数

就是自己调用自己罢了,套娃,但是记得加上终止条件,一般都是迭代条件。

1.3.2 不可变对象包含可变对象

参数的传递:

  • 传递不可变对象时为浅拷贝
  • 因此当不可变对象中包含可变对象时,对可变对象部分的修改会影响源数据

1.3.3 参数的类型

  • 位置参数:根据位置、个数跟参数匹配
  • 默认值参数:如果传入参数不足时默认参数使用默认值,默认参数必须放在最后
  • 命名参数:在调用函数传参的时候,加上参数的名称,直接赋值
  • 可变参数:定义函数时,传入参数可以为可变对象
  • 强制命名参数:带星号的’可变参数’后面增加新的参数,必须是 ‘强制命名参数’

1.3.4 lambda 表达式和匿名函数

lambda para1, para2, para3, …:

1.3.5 嵌套函数

  • 设置内置嵌套函数可以降低内部重复代码
  • 很有意思

第一章完结,第二章为字符串相关。


2. 字符串操作

2.1 字符串

  • 字符串不可修改
  • 只能复制部分或者增加形成新的字符串
  • Python不支持单字符类型,单字符也是作为一个字符串使用的
  • Python3直接使用Unicode编码,默认为16位Unicode编码
  • 使用内置函数ord()可以把字符转换成对应的Unicode码
  • 使用内置函数chr()可以把十进制数字转换成对应的字符

字符串驻留

  • 当标识符仅包含下划线、字母和数字时,会启用字符串驻留机制
  • 可以节省内存空间

2.2 可变字符串

如确实需要原地修改字符串,使用io.StringIO对象或者array模块

  • import io
  • str_new = io.StringIO(str)
  • str_new.seek(7) # 移动指针到第几个字符的位置
  • str_new.write(stringNum) # 写入新的字符串
  • .replace(str1, str2) 本质上创建了一个新的字符串,原有的字符串是不可变的
  • 对原有的字符串进行更改需要重新进行赋值
  • 在对字符串进行拼接时,尽量使用list对象存储,再用.join(),效率相比+好很多
  • +号拼接时会生成新的对象

2.3 字符串截取

# 获取字符串中某段字符
string_show = "abcedfghijklmn"

# 截取字符串中第二个与第三个,语法
[start:end:step]string_show[1:3:1] 

# 编号从0开始# 字符串倒置
string_show[::-1]

# 查找并替换字符,输出
“abcdffghijklmn”string_show.replace("e","f")

2.4 字符串分割

  • str() 可以将其他数据类型转换成字符型
  • 使用 [] 提取字符
# .split(string,'code')
string_show = '1,2,3,4,5,6'

a = string_show.split(',')
print(a)

output: [1,2,3,4,5,6]

2.5 字符串方法

  • 查找方法
  • len()
  • .startswith(str) 查看是否以某字符串开头
  • .endswith(str) 查看是否以某字符串结尾
  • .find(str) 查找字符串第一次出现的index
  • .rfind(str) 查找字符串最后一次出现的index
  • .count(str) 查找字符串出现的次数
  • .isalnum() 所有字符全是字母或数字
  • .strip() 去除首尾字符信息,不填的话去掉空格符
  • .lower() 将字符串中的字母改为小写
  • .upper() 将字符串中的字母改为大写
  • .capitalize() 产生新的字符串,首字母大写
  • .title() 产生新的字符串,每个单词首字母大写
  • .swapcase() 产生新的字符串,大小写转换
  • .center(num, str) 以多少个字符显示,填充指定字符,并居中
  • .ljust() 同上,左对齐
  • .rjust() 同上,右对齐,默认以空格填充

第二章完结,第三章为Python List相关。


3. Python数组操作

3.1 序列介绍

  • 序列是一种数据储存方式,一款连续的内存空间
  • 常用的序列结构有:字符串、列表、元组、字典、集合
  • 列表:可以存储任意类型
  • 元组:存储完后,元素不可变
  • 集合:不允许出现相同元素
  • 字典:存储键值对,键不允许重复

序列也是一个对象,标识符与序列对象的ID相链接;

序列的列表里存储的是地址,也就是值对象的ID

3.2 List列表和下标

  • 列表的下标表示他们的顺序,从 0 开始
  • 列表可以使用负数下标,-1表示最后一个
  • 对List进行取值,可以使用,注意的是,不包含结尾下标值
a = [1,2,34,5]

# a[start:end:step]
print(a[1:2:1])

output: [1]
  • 对 List 对象进行反序
a = [1,2,3,4,5]
# [::-1]
print(a[::-1])

output: [5,4,3,2,1]

# .reverse() 在原List上直接进行了操作
a.reverse()
print(a)

output: [1,2,3,4,5]
  • 查找Index
# List查询的语法为下面所示,可以指定查询的开始下标与结束下标
List.index("what do you want to find", start, end)

# 查找a这个list中元素“H”的位置eg:
a = ['a','H','H','v']
print(a.index('H'))

# 从这个例子中可以看出,只返回查询到的第一个下标
output: 1

3.3 List函数方法

  • 判断字符是否在 List 中
# in / not in
a = [1,2,3,4,5]
print(4 in a)

output: True
  • 使用 len() 得到 List 长度
# len(a)
a = [1,2,3,4,5]
print(len(a))

output: 5
  • 使用 + 拼接 List
# +
a,b = [1,2,3],[2,3,4]
print(a+b)

output: [1,2,3,2,3,4]
  • 使用 * 重复某个列表
# *
a = [1,2,3] * 3
print(a)

output: [1,2,3,1,2,3,1,2,3]
  • 获取最大最小元素,对字符串List使用该方法时,会比较字符串内首个字符的大小进行排序
# max()  min()
a = [1,2,3]
print(max(a))
print(min(a))

output: 31
  • List 排序
# .sort()
a = [1,3,2,4]
a.sort()
print(a)

output: [1,2,3,4]
  • 获取List中某个元素的第一个下标
# .index(value)
a = ['a','b','c','d']
print(a.index('b')) 

# 此时有两个'b',返回第一个'b'的下标
output: 1
  • 获取某个元素在列表中出现的次数: a.count(“a”)
# .count('code')
a = ['a','b','c','d']
b = a.count('a')
print(b)

output: 1
  • List 快速交换 List 中两个位置的值
# a[x],a[y] = a[y],a[x]

a = [1,2,4,3,5]
a[2], a[3] = a[3], a[2]

print(a)
output: [1,2,3,4,5]
  • List 连接成为字符串,注意不能包含 数字
# a = ''.join(a),前面的‘’中输入的为分隔符

a = ['1','2','3','4','5']
a = '*'.join(a)

print(a)
output: '1*2*3*4*5'
  • .append(value),追加
  • .insert(index, value),插入,注意不要去使用负数下标
  • .extend([value1, value2, value3]),追加多个元素,形式为列表
# 是否加[],结果完全不一样,对于数字来说,必须要加上[]# 不加[]
a = [1,2,3,4,5]
s = 'hello'
a.extend(s)
print(a)
output: [1,2,3,4,5,'h','e','l','l','o']

# 加[]a = [1,2,3,4,5]
s = 'hello'
a.extend([s])
print(a)
output: [1,2,3,4,5,'hello']
  • .pop() 移除 List 最后一个元素,有返回值
  • .pop(index) 移除指定 index 位置的元素
  • del List[index] 与上述效果相同,移除指定 index 位置的元素
  • .remove(value) 移除指定的值,多个重复值时指第一个值
  • .clear() 清除列表中所有元素

List 的 Slice 操作

  • 跟字符串部分差不多
  • [start: end: step]
  • 可以是用负数进行检索

List排序

  • 原地排序
  • .sort(reverse = True) 括号内代表降序
  • 打乱顺序
  • random.shuffle(List)
  • 生成新的列表并排序
  • newList = sorted(List)
  • List 逆序返回迭代器对象,不对原数组做操作
  • reverseObj = reversed(List)
  • newList = List(reverseObj)

3.4 List创建与推导式

  • 列表推导式:
  • 字典推导式,也可以添加 if 语句
  • 集合推导式:
  • 生成器推导式(返回的是生成器)
  • 可迭代对象:也即可以被循环访问

列表的操作
列表的操作

3.5 不可变序列-元组

  • 排序只能使用内置的 sorted 生成新的元组
  • 将多个 List 连接成为 zip对象,list()处理后,每个元素均为元组对象
  • newTuple = zip(ListA, ListB, ListC)
  • newList = list(newTuple)

生成器推导式创建元组

  • 生成器推导式生成的不是列表也不是元组,而是一个生成器对象
  • 语法格式举例: (x for x in range(5))
  • 可以使用 .next() 方法对生成器对象进行单个访问
  • Tuple: 定义式使用 ()
  • 定义时可以不需要括号
# 元组不可修改,不可增删,只能查询值与index

mytuple = (1,2,3)

# 但有index,加减成为新元组
a = 1,2,3,4
b = 3,4,5,6
c = a + b

print(c)
output: 1,2,3,4,3,4,5,6
  • 可以使用max(),min()
# 可以使用上述函数得到最大最小值
a = 1,2,3,4,5
max(a)
min(a)

output: 51
  • 可以被截取,如[::-1]
# 截取得到的元组是新元组
a = 1,2,3,4
a[::-1]
a[1:3]

output: (4,3,2,1)
(2,3)
  • 有 .index() 方法,取得元素在元组里的下标
# 获取元组中元素的下标
a = 1,2,3,4
a.index(value)

output: None
  • 元组值可以分别同时赋值给多个元素
# 赋值说明
t = (1,2,3)
a,b,c = t
print(a)
print(b)
print(c)

output: 1
2
3

3.6 字典

  • 最简单的为 dictA = {key1: value1, key2: value2}
  • dictB = dict(key1 = value1, key2 = value2)
  • dictC = dict( [(key1, value1), (key2, value2)] )
  • dictD = dict(zip(keyListA, valueListB))
  • 可以用 None 创建空值

字典元素的访问

  • dict[key]
  • .get(key, ‘异常提示’) 不存在则抛出异常 None
  • .items() 获得所有键值对
  • .keys() / .values()

字典基础

  • 创建字典
d = {} # 空字典
d = {key1: value1, key2: value2}

# 字典 Dict 是一种可变容器类型,可以保存任意对象
# 字典中的元素与键值对 key-value 的方式存储
d = {"北京": 22, "上海": 24}

# 字典的 键 必须是 唯一的不能重复
# 字典中的 键 必须是 不可变类型
  • 字典的增删改查
# 增加元素
d[key] = valued.update({key: value})

# 删除元素
d.pop(key)d.clear

# 更改元素
d[key] = new_value

# 查找元素
d.get(key, -1)d.setdefault(key, -1)

字典补充

# 字典可以判断某个值是否在key中
dicta = {1:2, 3:4, 5:6}
dicta = dict(key1=value1,key2=value2)
print(if 3 in dicta)$ true

# 如果需要判断某个值是否在value中,需要使用.values()方法
# 字典遍历,字典是可迭代对象# 遍历字典的 key
d = {"小王": 86, "小红": 92, "小明": 85}
for i in d:
    print(i)    # 小王 小红 小明
    print(d[i]) #   86   92   85

# 或者用 .keys() / .values
for i in d.keys():
    print(i)

for i in d.values():
    print(i)

# 访问字典的键值对 .items()
for i,j in d.items():
    print(i)   # 键
    print(j)   # 值

字典实现底层原理

  • 字典通过键去查找元素
  • 本质上是散列表,也就是稀疏数组(总是含有空白元素),数组的每个单元叫做bucket,每个bucket有两部分,一个是见对象的引用,一个是值对象的引用
  • 下面的存储内容只是示例,真实存储的为键对象的地址以及值对象的地址
  • 如果存取都是这样的方式,那么效率不仅低的可怕,甚至有些数据都查找不到,以及空间占用太恐怖了吧
  • 最好不要同时遍历字典以及执行删除操作,否则可能导致扩容,次序发生变化

3.7 集合

  • 无序可变,元素不能重复
  • 本质是字典,只有键对象
  • 使用 {} 创建对象,使用 .add() 添加元素
  • 使用 set() ,将列表、元组等可迭代对象转成集合,如果存在重复项,则只保留一个
  • .remove() 删除指定元素
  • .clear() 清除所有元素
  • 集合的相关运算

3.8 zip序列解包

  • x, y, z = List[1:4]
  • a, b, c = dictA # 获得的是键
  • 加上 .values() / .items() 可以获得相应的值

使用 zip() 并行迭代

  • 就是多重同时访问,用完即停

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f279fa10-e794-4a7d-af35-9d6610287dd8/Untitled.png


第三章完结,第四章为Python类相关。


4. Python类

4.1 类对象的定义及属性

使用 “class 类名:”,实际上,当解释器执行 class 语句时,就会创建一个类对象。

  • 新建的类是type下面的一个模板
  • 类对象贼有意思

4.1.1 类的定义-类和对象的关系

  • 对象就像是一个物品
  • 类就是制造这个物品的模具

但一切都是对象,因此类本身也是对象

  • 类的本质是将行为和状态打包在一起
class Student:
    def __init__(self,name,score): # self必须在第一个参数位
        self.name = name
        self.score = score

    def say_score(self): # self必须在第一个参数位
        print(f"{self.name}的分数是{self.score}?")

s1 = Student("谁",18)
s1.say_score()s1.age = 32
s1.salary = 35200
print(f"{s1.name}的工资是:{s1.salary},也不大才{s1.age},分数才{s1.score},不知道走了什么狗屎运!")

out:谁的分数是18?谁的工资是:35200,也不大才32,分数才18,不知道走了什么狗屎运!
  • 需要注意的是,在init左右两边各有两条下划线,否则会报错。

构造函数 init()

在调用类定义对象时,先执行了__new__()方法创建对象,再执行构造函数__init__()初始化对象。

  • 要点为:名称固定,第一个参数必须为self,在类里定义的函数都必须加上self
  • 实例属性往往是名称与形参一样
  • Python中的 self 相当于C++中的 Self 指针,Java和 C# 中的 this 关键字

4.1.4 类属性

  • 类属性属于类,可以被所有实例对象共享
  • 在这里类属性 count 被调用了几次取决于初始化过几次
  • 栈堆图详解
  • 实例对象中只存储实例属性、以及方法的引用地址,类属性与方法的对象都存在类里

私有属性和私有方法

  • 需要用 “下划线 类名 下划线 下划线 私有属性” 或者 “下划线 类名 下划线 下划线 私有方法” 调用
  • 私有方法在定义的时候,前面加俩下划线
    @property 装饰器

将一个方法转为属性调用

4.1.3 实例属性

  • 实例属性一般在 构造函数 中定义
  • 可以用 对象.实例属性 的方法调用
  • self 不需要传参,解释器自己会传参
  • dir(Obj) 可以获得对象所有的属性和方法
  • pass 空语句
  • isinstance(Obj, Class) 判断对象是否属于该类
  • 类对象的类型就是 Class type

4.1.5 类方法

  • 类方法与实例函数的区别在于,该方法可以被所有实例对象共同调取,也可以被类本身直接调取;

静态方法

与类完全无关的方法,放在类里的函数

del析构函数和垃圾回收机制

上述析构方法,用于实现对象被销毁时所需要的操作,

  • 释放对象占用的资源
  • python实现自动的垃圾回收,当对象没有被引用时(引用计数为0),由垃圾回收器调用析构函数;
  • del 方法本质上是调用析构函数

call方法和可调用对象

  • 定义了 call 方法的对象,称为可调用对象,即该对象可以像函数一样被调用。
  • 最好带返回值
  • 可以直接使用 Obj() 的形式调用
    Python中没有方法重载

重载也不是个好东西啊,容易导致效率低下

4.2 面向对象

4.2.1 面向对象与面向过程区别

Python支持面向过程、面向对象、函数式编程,Python中一切皆对象。
面向过程到面向对象,编程思维的转变

4.2.2 面向对象的三大特征

  • 封装
  • 继承
  • 多态

封装

  • 隐藏对象的细节,对外只提供必要的方法,将细节封装起来,只对外暴露“相关调用方法”

继承

  • 继承可以让子类具有父类的特征,提高代码的重用性
  • 设计上是一种增量进化,原有父类设计不变的情况下,可以增加新的功能,或改进已有的算法

代码复用的重要手段

  • 定义的时候,在小括号里加上父类,可以多重继承

  • 继承了父类的所有属性,但不能直接用父类的私有属性

  • 如果没有指定父类,那么所有的类的父类都是Object

  • 子类初始化范例,通过调用父类的方法进行初始化父类方法的继承与重写

父类的重写比较常见

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

    def say_age(self):
        print("我就是个无情的测试语句")

class Student(Person):
    def __init__(self,name,age):
        Person.__init__(self,name,age)

    def say_age(self):
        print("shwta")s1 = Student("Qiu mouren",22)

s1.say_age()s2 = Person("WoJiuShuo",300)
s2.say_age()

>>>python c:/Users/ZekShawn/Desktop/test.pyshwta
我就是个无情的测试语句

Object 根类

所有的自定义类包含了Object根类的属性

  • 类的方法也是属性,只不过方法的类型为method
class A:
		pass

class B(A):
		pass

class C(B,A):
		pass

print(C.mro())

>>>python c:/Users/ZekShawn/Desktop/test.py
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

重写 str 方法

class Person():     # 默认继承根类
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_age(self):
        print("我就是个无情的测试语句")

    def __str__(self):
        print("测试是否被重写")
        return f"Name is {self.name}, and no other message!"

p = Person("swd",22)
print(p)

>>>python c:/Users/ZekShawn/Desktop/test.py
测试是否被重写Name is swd, and no other message!

多重继承

自左往右,如果子类里没有该方法,又被调用时
获得父类定义,直接调用父类方法

4.2.3 类的多态

  • 指同一个方法调用由于对象不同产生不同的行为

  • 运算符可以重载
    重载 + 运算

  • 常用函数也可以重载
    特殊属性

对于Python中的对象,有一些特殊的属性

示例如下:

class Person():     # 默认继承根类
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_age(self):
        print("我就是个无情的测试语句")

    def __str__(self):
        print("测试是否被重写")
        return f"Name is {self.name}, and no other message!"

class Student(Person):
    def __init__(self,name,age):
        Person.__init__(self,name,age)

    def say_age(self):
        super().say_age()
		    pass

p = Student("swd",22)
p.say_age(
print(p.__dict__)

>>>python c:/Users/ZekShawn/Desktop/test.py
我就是个无情的测试语句{'name': 'swd', 'age': 22}

4.2.4 类的组合

  • 组合也可以实现一个类拥有另一个类的方法和属性
  • 面向对象可以帮助更好的构建程序的实现逻辑

有时候两者之间存在联系,却不能直接继承,比如下例中的手机与CPU

  • 如下图所示,可以将一个对象传入另一个对象的属性
  • 接着从其中一个对象属性调用另一个对象的方法

4.3 设计模式

4.3.1 工厂模式

  • GOF23种设计模式
  • 工厂模式主要实现了创建者和调用者的分离
# 测试工厂模式
# GOF(Group Of Four)23
class CarFactory:
    def createCar(self,brand):
        if brand == "Benci":
            return Benci()
        elif brand == "BMD":
            return BMD()
        elif brand == "BYD":
            return BYD()
        else:
            return "Sorry, there's no this kind of brand!"

class Benci:
    pass

class BMD:
    pass

class BYD:
    pass

factory = CarFactory()
c1 = factory.createCar("Benci")
c2 = factory.createCar("BYD")
print(c1,c2)

>>>python c:/Users/ZekShawn/Desktop/test.py
<__main__.Benci object at 0x000001E6693BA280><__main__.BYD object at 0x000001E6693C3430>

4.3.2 单例模式

核心就是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。
单例模式

# 测试单例模式
# GOF(Group Of Four)23

class mySimple:
    __obj = None        # 类属性
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

    def __init__(self,name):
        if mySimple.__init_flag:
            self.name = name
            mySimple.__init_flag = False

a = mySimple("sw")
b = mySimple("wd")
print(a.name)
print(b.name)
print(a)
print(b)

>>>python c:/Users/ZekShawn/Desktop/test.py
swsw<__main__.mySimple object at 0x0000027D2C4B3610><__main__.mySimple object at 0x0000027D2C4B3610>

工厂模式的工厂对象转化为单例模式

# 测试工厂模式
# GOF(Group Of Four)23
class CarFactory:
    __obj = None
    __init_flag = True

    def createCar(self,brand):
        if brand == "Benci":
            return Benci()
        elif brand == "BMD":
            return BMD()
        elif brand == "BYD":
            return BYD()
        else:
            return "Sorry, there's no this kind of brand!"

    def __new__(cls):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

    def __init__(self): 
       if CarFactory.__init_flag:
            CarFactory.__init_flag = False

class Benci:
    pass

class BMD:
    pass

class BYD:
    pass

factory1 = CarFactory()
factory2 = CarFactory()
c1 = factory1.createCar("Benci")
c2 = factory2.createCar("BYD")

print(c1,c2)
print(factory1,factory2)

>>>python c:/Users/ZekShawn/Desktop/test.py
<__main__.Benci object at 0x0000027F74493580><__main__.BYD object at 0x0000027F744931F0>
<__main__.CarFactory object at 0x0000027F74493610><__main__.CarFactory object at 0x0000027F74493610>

太棒啦,如果你看了我前面的文章,那么恭喜你,学完Python的入门知识了,加油吧少年。

  • 总觉得上面的这段话好中二啊,哈哈哈哈,不过学完了确实很舒服。头疼,走了不少弯路,估计过段时间整理一下我的学习历程分享给电脑这端的你。
0

评论区