摘要:
此博文是初步探索python世界的经历,主要是归纳总结python的基础和特性,过程是一边观看视频一边敲代码学习并记录下笔记,文字较少,主要以代码为主通过注释标注重点,有需要步入python编程的,可参考此学习途径。
开发环境:python3.11.0,vscode
关键词
: 学习笔记,python,零基础,小甲鱼,鱼C论坛,学习途径
声明:
本文作者原创,转载请附上文章出处与本文链接。
文章目录
正文:
视频:
B站小甲鱼python教学基础扎实,也有不少拓展的知识点,零基础学习python够用,主要要跟着多敲代码,多整理笔记。鱼C论坛也有对应的python板块,每章有课后作业等,有需要可去观看解答,不一定需要,能跟着视频敲出代码运行起效果就好。
学习随笔
P1~P19主要是介绍,环境搭建以及一些基础中的基础,有一定其它语言的学习这些都非常容易入门,所以笔记记录的主要是P20之后的内容,代码都可直接运行,内容是自己的理解,想到哪里记哪里,单看云里雾里,得结合视频,随意参考即可,按自己节奏走。P20之后的内容代码采用了分支处理,只要改变一个变量即可选择不同P章节运行。
P1~P19:变量和分支循环
练手敲的代码
import decimal
x = 1 + 2j
x.real
x.imag
divmod(-3, 2) # 地板除, 取余
if True and False or False and not True: # 短路逻辑、优先级 not > and > or
print("fuck")
num = 123
match num:
case 1:
print("1")
case 2:
print("2")
case _:
print("not", end=" ")
# """ 这才是注释符号阿 """
import random
import decimal
num, count = random.randint(0, 10), 8
print("answer:" + str(num) + "\n")
while count:
temp = input("How much num?")
guess = int(temp)
if num == guess:
print("YES")
break
else:
if guess > num:
print("NO, so big")
elif guess < num:
print("NO, so small")
count -= 1
print(count)
print("END")
P20~P27:列表list,元组tuple
# 列表和地址很像
inis = 1# inis为控制运行分支变量,改变inis的值变更运行不同P,后续类同
# 列表1
if inis == 1:
real = [1, 2, 23, 4, "dasdq"]
# for each in real:
# print(each)
real[-1]
real[0:3]
real[:3]
real[3:]
real[:]
real[::2]
real[::-2]
real[::-1]
# print(real[1:3])
# 列表2
elif inis == 2:
real = [1, 2, 23, 4, "dasdq"]
real.append(123) # hulei
real.extend(["wdfk", 1.134, False]) # hulei
real[len(real):] = ["dnm"]
real[len(real):] = [88, 3.14, "wqnmd"]
real.insert(2, [123, 321])
real.remove("dnm")
print(real)
real.remove(23)
print(real)
real.clear()
# 列表3
elif inis == 3:
num = [1, 2, 3, 89, 64, 13, 57, 91, 32, 5]
num.sort()
num.reverse()
num.sort(reverse=True)
num.count(13)
num.index(91)
num1 = num.copy()
num1 = num[:]
# 列表4
elif inis == 4:
list = [1, 2, 3]
list2 = [4, 5, 6]
list + list2
list * 3 # 列表地址的拷贝,不是新建
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
A = [0] * 3
for i in range(len(A)):
A[i] = [0] * 3
print(A)
B = [[0] * 3] * 3 # 结果相同原理不同
# 列表5
elif inis == 5:
import copy
x = [1, 2, 3]
y = x.copy
y = x[:] # 一样,浅拷贝,对嵌套列表(二维数组)不行,
x = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
y = copy.deepcopy(x) # 深拷贝
# 列表6
elif inis == 6:
# 列表推导式 更快,C语言实现的
x = [i for i in range(10)]
# print(x)
x = [i * 2 for i in range(10)]
# print(x)
code = [ord(i) for i in "wdnmlgb"]
# print(code)
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
col2 = [row[1] for row in matrix] # row == ,matrix[?]
# print(col2)
col2 = [matrix[i][i] for i in range(len(matrix))] # len(matrix) == 3
print(col2)
col2 = [matrix[i][-i+2] for i in range(len(matrix))] # len(matrix) == 3
print(col2)
# 列表7
elif inis == 7:
s = [[0] * 3 for i in range(3)]
print(s)
words = ["Great", "Fishc", "Brilliant", "Excellent", "Fantistic"]
words = [i for i in words if i[0] == 'F']
print(words)
# 嵌套列表推导式
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
flatten = [col for row in matrix for col in row]
print(flatten)
_ = [[x, y] for x in range(10) if x % 2 == 0
for y in range(10) if y % 3 == 0]
print(_)
# 元组不可变,可读不可写 ; 除了跟修改相关的操作不行,和没有元组推导式。其它操作和列表类似
elif inis == 8:
rhyme = (1, 23, 7, 13, 9, 123, 10, "wdnmd")
t = (1, 22, "wdfuck")
x, y, z = t
x, y, *z = "wdfuck"
# print(z)
x = [1, 2, 3]
y = [4, 5, 6]
_ = (x, y) # 存放列表(索引/地址)就可更改
print(_)
x[1] = 9
print(_)
P28~P33:字符串string
inis = 6
# 字符串1
if inis == 1:
x = "123321" # 回文数
print("yes") if x == x[::-1] else print("no")
print(type(x))
# 字符串处理函数合集:https://fishc.com.cn/thread-183975-1-3.html
# 字符串2
elif inis == 2:
print("a lot of funcation")
# 字符串3
elif inis == 3:
import keyword
keyword.iskeyword("for")
# 字符串4
elif inis == 4:
str = ".".join(["www", "wdfk", "com"])
print(str)
str = "".join(["wdfk", "wdfk"]) # 大数据效率高
print(str)
str = "wdfk"
str += str # 小数据差不多
print(str)
# 字符串5
elif inis == 5:
num = 250
str = "wdfk num:{}".format(num)
print(str)
str = "{1}wdfk,{0}250".format("wdfk", 250)
print(str)
str = "{num}wdfk,{wdfk}250".format(wdfk="wdfk", num=250)
print(str)
# 填充空格、其它字符;数字补齐0感知正负号
# 字符串6
elif inis == 6:
# 正负号{:+}/{:-}、千位符{:,}、限制位({:2f}/{:2g} {:.2})
# 类型{:(type)}
"{:b}".format(80)
"{:e}".format(3.1415)
"{:.2%}".format(0.88)
# f-string format版“语法糖” 性能略胜一筹:V3.6
str = f"wdfk {250}"
print(str)
P34~P41:序列sequence,字典dict,集合set
inis = 8
# 序列上
if inis == 1:
# 列表、元组、字符串都是序列
"123" + "123"
"123" * 3
s = [1, 2, 3]
id(s)
t = [1, 2, 3]
print(s is t) # false is not
print("wdfk" in "wdfk 250") # true in not
del s, t
x = [1, 2, 3, 4, 5]
del x[::2]
print(x)
# 序列中
elif inis == 2:
# --list()变列表、tuple()变元组、str()变字符串
print(list("wdfk"))
# min、max、len、sum
min([1, 2, 3, 4, 5, 6])
min(1, 2, 3, 4, 5)
# sorted返回新的列表、reversed返回的是一个迭代器
# 序列下
elif inis == 3:
x = [1, 2, 0]
y = [0, 0, 0]
z = [1, 1, 1]
all(x) # false y:false z:true
any(x) # true y:false z:true
seasons = ["chun", "xia", "qiu", "don"]
# enumerate(seasons) # 创建枚举对象
print(list(enumerate(seasons)))
print(list(enumerate(seasons, 10)))
x = [1, 2, 3]
y = [9, 8, 7]
z = "wdnmd"
zipVal = zip(x, y, z)
print(list(zipVal))
import itertools
print(list(itertools.zip_longest(x, y, z)))
print(list(map(ord, "wdnmd")))
print(list(map(pow, [2,2,8], [1,8,2]))) # max
print(list(filter(str.islower, "WdnMD")))
# 迭代器一定是迭代对象。迭代对象可复用,迭代器是一次性(C++ 的传地址传变量?有点类似)
x = [1, 2, 3, 4, 6]
y = iter(x)
print(type(x), type(y))
next(y, "NULL")
next(y, "NULL")
next(y, "NULL")
next(y, "NULL")
next(y, "NULL")
print(next(y, "木了"))
# 字典上
elif inis == 4:
# 字典是python中唯一实现映射关系的内置类型
table = {",":"w", ".":"d", "/":"n", ";":"m", "'":"d"}
code = input("input:")
split_code = code.split(" ")
result = [table[each] for each in split_code]
print(result)
# 字典中
elif inis == 5:
table = {",":"w", ".":"d", "/":"n", ";":"m", "'":"d"}
type(table)
# 添加、修改
table["["] = "F"
# 创建
table = {",":"w", ".":"d", "/":"n", ";":"m", "'":"d"}
table = dict(我去你的="w", 神经病="d")
table = dict(zip([",", ".", "/", ";", "'"], ["w", "d", "n", "m", "d"]))
# ……
table = dict.fromkeys("wdfk", 250) # 创
print(table)
table.pop('f', "没找到") # 删
table.popitem()
print(table)
table.clear() # 清
# 字典下
elif inis == 6:
table = dict.fromkeys("wdfk")
print(table)
table.update(w='F', d='U') # 改
table.update({'f':250, 'k':438})
print(table)
table.get('f', "木有") # 查
table.setdefault('h', "wy")
# 视图对象
keys= table.keys()
values = table.values()
items = table.items()
# table改变,这三个都会相应改变
x = table.copy()
len(table)
# in、not in、list、iter、reversed、
# 嵌套
table = {"w":{"f":1,"u":2,"c":3,"k":4}, "d":{"q":"S","n":"B",200:"俩佰",5:"伍"}}
print(table["d"]["q"])
# 字典推导式
table = {",":"w", ".":"d", "/":"n", ";":"m", "'":"d"}
a = {v:k for k,v in table.items()} # 嵌套不行
print(a)
a = {v:k for k,v in table.items() if v == 'w'}
print(a)
# 集合上
elif inis == 7:
# 创 (元素唯一和字典key性质一致)(集合无序)
setValue = {"wdnmd", "fuck"}
print(type(setValue))
print(setValue)
setValue = set({"wdnmd", "fuck"})
print("fuck" in setValue)
len([1,2,2,3,4]) == len(set([1,2,2,3,4])) # false
setValue = set("wdnmd")
print(setValue.isdisjoint (set("fuck"))) # 集合是否 没有交集 (参数为列表等也可)
print(setValue.issubset("wdnmd,fuck")) # 集合是否为参数的子集
# setValue <= set("wdnmd,fuck")
print(setValue.issuperset("wd")) # 集合是否为参数的超集
# setValue >= set("wd")
print(setValue.union("fuck")) # 组成并集
# setValue | set("fuck")
print(setValue.intersection("fucknmd")) # 两个相交的交集
# setValue & set("fucknmd")
print(setValue.difference("fuck")) # 集合不在参数内的元素 差集
# setValue - set("fuck")
# 都是可以多参数,下面的对称差集不行
print(setValue.symmetric_difference("wdfuck"))
# setValue ^ set("wdfuck")
# 集合下
elif inis == 8:
froset = frozenset("wdnmd") # 不可变的集合
setVal = set("wdnmd")
setVal.update([1, 4], "89") # 参数添加进集合 (frozenset会异常)(*orthers,有s是多个参数)
print(setVal)
# setVal.intersection_update、setVal.difference_update、setVal.symmetric_difference_update
# 添加_update后会更改setVal的内容
setVal.add("45")
setVal.remove("45") # setVal.discard 找不到静默处理
setVal.clear()
# 嵌套集合(涉及可哈希性质,hash()) set不行,只能用frozenset
nestSet = {frozenset([1,2,3]), 8, 10}
print(nestSet)
P42~P53:函数function
inis = 12
# 函数Ⅰ
if inis == 1:
def func(name, times):
for i in range(times):
print(f"fuck {name}")
return "wdnmd"
print(func("wdfk",2))
# 函数Ⅱ
elif inis == 2:
# 关键字参数 (位置参数必须在关键字参数之前)
def func(s, vt, o):
print( "".join((o, vt, s)) )
func(o="fuck", vt="you", s="today")
# 默认参数 (和C++默认参数一致)
# 参数限制 / *
def funcxie(a, /, b, c): # / 左侧必须用位置参数,右侧可用关键字参数
print(a,b,c)
def funcxing(a, *, b, c): # * 右侧必须用关键字参数,左侧可用位置参数
print(a,b,c)
funcxing(1,b=2,c=3)
# 函数Ⅲ
elif inis == 3:
# 收集参数(多参数)
def func(*args): # args 为元组
print("{}个".format(len(args)))
print("最后一个参数{}".format(args[len(args)-1]))
return 1,2,3 # 返回多个值也是利用元组打包的性质
func(1,2.3)
def funcKey(*args, a, b):
print(args, a, b)
funcKey(1, a=2, b=3)
def funcDict(**dict): # dict字典 *限制右边必须为关键字参数
print(dict)
funcDict(a=1, b=2, c=3)
# 混合
def funcBlend(a, *b, **c):
print(a,b,c)
funcBlend(1,2,3,4,5,q=6,w=7,e=8)
# 解包参数
args = (1,2,3,4)
def funcUnpack(a,b,c,d):
print(a,b,c,d)
funcUnpack(*args)
args = dict(a=10,b=9,c=8,d=7)
funcUnpack(**args)
# 函数Ⅳ
elif inis == 4:
# 作用域 和C++类似 有global函数可以在函数内修改全局变量
# 嵌套函数
def funcA():
x = "wdnmd"
def funcB():
x = "fuck"
print("funcB:", x)
funcB()
print("funcA:", x)
funcA()
def funcA():
x = "wdnmd"
def funcB():
nonlocal x # 统一内外函数的变量
x = "fuck"
print("funcB:", x)
funcB()
print("funcA:", x)
funcA()
# (变量覆盖)LEGB规则:L:Local; E:Enclosed; G:Global; B:Build-In;
# 函数Ⅴ
elif inis == 5:
# 闭包 工厂
def power(exp):
def exp_of(base):
return print(base ** exp)
return exp_of
square = power(2)
cube = power(3)
square(3) # 3的2次方
cube(3) # 3的3次方
# 闭包工厂功能可用作游戏角色的移动
def funcInit(x = 0, y = 0):
def innerFunc(type):
def funcA(xA, yA):
nonlocal x,y
x += xA
y += yA
print("funcA:",x,y)
def funcB(xB, yB):
nonlocal x,y
x += xB
y += yB
print("funcB:",x,y)
if type == 0:
return funcA
elif type == 1:
return funcB
return innerFunc # 或者 return {'func1':funcA, 'func2':funcB} 原理就是让funcA、funcB在同一层
funcFactory = funcInit()
func1 = funcFactory(0)
func2 = funcFactory(1)
func1(1, 1)
func2(2, 2)
func1(3, 3)
# 函数Ⅵ
elif inis == 6:
# 函数作参数 制作最简单的程序⏲
import time
def timer_master(func):
print("begin")
start = time.time()
func()
stop = time.time()
print("stop")
# print(f"time:{(start-stop):.2f}秒")
print("time:{:.2f}秒".format(stop-start))
def funcTime():
time.sleep(2)
time.sleep(0.05)
print("funcTime End")
# timer_master(funcTime)
# 装饰器(原理闭包) 阔以多个装饰器作用一个函数,从近往远依次调用
def timer_master(func):
def call_func():
print("begin")
start = time.time()
func()
stop = time.time()
print("stop")
# print(f"time:{(start-stop):.2f}秒")
print("time:{:.2f}秒".format(stop-start))
return call_func
@timer_master # 语法糖 == (funcTime = timer_master(funcTime))
def funcTime():
time.sleep(2)
time.sleep(0.05)
print("funcTime End")
# funcTime()
# 装饰器传参 多套一次闭包,把参数传进去
def logger(msg):
def timer_master(func):
def call_func():
print("begin")
start = time.time()
func()
stop = time.time()
print("stop")
print("{0}time:{1:.2f}秒".format(msg, stop-start))
return call_func
return timer_master
@logger(msg="funcTime") # == (funcTime = logger(msg="funcTime")(funcTime))
def funcTime():
time.sleep(2)
time.sleep(0.05)
print("funcTime End")
funcTime()
# 函数Ⅶ
elif inis == 7:
# lambda (一行流) 最大优势就是阔以出现在def 不允许出现的地方,简单的功能就不需要def
def squareX(x):
return x * x
squareY = lambda y : y*y
# squareX == squareY
# 可出现在列表、元组等
y = [lambda x:x*x, 2, 3]
print(y[0](y[1]), y[0](y[2]))
mapped = map(lambda x:ord(x)+10, "wdnmd")
print(list(mapped))
# 函数Ⅷ
elif inis == 8:
# 生成器yield,保存调用函数的状态(闭包、全局变量)
def counter():
i = 0
while i <= 5:
yield i # 每次调用返回 yield 类似return但没return的阻断,下面语句还可运行,并会保存着
i += 1
for i in counter():
print(i)
print(next(counter())) # 生成器也是一种迭代器
# 生成器表达式 (元组?) 列表表达式是一次性全输出、生成器表达式是一次调用只输出一个
t = (i ** 2 for i in range(10))
print(type(t), next(t))
print(next(t))
print(next(t))
# 函数Ⅸ
elif inis == 9:
# 递归 和C++一样,了解就好 函数掉用函数
# 生成器实现斐波那契数列
def fib(n):
back1, back2 = 0, 1
while (n!=-1):
yield back1
back1, back2 = back2, back1+back2
n -= 1
n = 120
for val in fib(n):
if(n == 0):
print(val)
n -= 1
# 函数Ⅹ
elif inis == 10:
# 递归 汉诺塔
def hanoi(n, x, y, z):
if(n == 1):
print(x, "-->" ,z)
else:
hanoi(n-1, x, z, y)
print(x, "-->", z)
hanoi(n-1, y, x, z)
n = int(input("层数:"))
hanoi(n, 'A', 'B', 'C')
# 函数Ⅺ
elif inis == 11:
# 编写函数文档
def exchange(dollar, rate = 7.17):
"""
功能:美元转人民币
参数:美元,汇率
返回:结果
"""
return dollar * rate
help(exchange)
# 类型注释 没有强制作用,只是推荐函数参数类型, 返回的类型
def times(s:str, n:int) -> str:
return s * n
print(times(5, 5))
# 内省 __xx__ 都是函数的内省(程序自我检测的机制),内在属性说明等
print(exchange.__name__)
print(times.__annotations__)
# 函数Ⅻ
elif inis == 12:
import functools
# 高阶函数 函数做函数参数
# https://fishc.com.cn/thread-209319-1-2.html
# 偏函数 对指定的函数二次包装,例如包装pow函数的次幂
square = functools.partial(pow, exp=2)
print(square(2))
cube = functools.partial(pow, exp=4)
print(cube(2))
# @wraps装饰器,跟闭包,函数内省相关
def timer_master(func):
@functools.wraps(func) # 注释这一句的话,下面print(funcTime.__name__) 输出 call_func
def call_func():
print("begin")
start = time.time()
func()
stop = time.time()
print("stop")
# print(f"time:{(start-stop):.2f}秒")
print("time:{:.2f}秒".format(stop-start))
return call_func
@timer_master
def funcTime():
time.sleep(2)
time.sleep(0.05)
print("funcTime End")
print(funcTime.__name__)
P54~P58:永久储存memory,异常abnormal
inis = 5
# 永久存储↑
if inis == 1:
# 创建打开文件
file = open("wdnmd.txt", "w")
file.write("wdnmdlch, fuck")
file.writelines({"123\n","987\n"})
file.close() # 需要关闭刷新缓存,write才有正式写入 or open和close是一对,不可分
file = open("wdnmd.txt", "r+")
for each in file:
print(each)
print(file.tell())
file.seek(0)
print(file.read())
file.write("天王盖地虎, 宝塔镇河妖\n")
file.flush() # 刷新缓存
file.truncate(24) # 截断
file = open("wdnmd.txt", "w") # 也会截断,w打开会删内容 和mode:w有关,r+不会
file.close()
# 永久存储-
elif inis == 2:
# 路径处理 pathlib 3.4才有
from pathlib import Path
print(Path.cwd())
dirPath = Path("D:\CODE\python")
txtPath = dirPath / "wdnmd.txt"
print(dirPath.is_dir())
print(txtPath.exists()) # 路径是否存在
print(txtPath.suffix) # 文件后缀
# …………
# 相对路径、绝对路径
Path("../python").resolve() # 相对路径转绝对路径
# 看文档https://fishc.com.cn/thread-210695-1-6.html
# 永久存储↓
elif inis == 3:
# with上下文管理器 确保资源的释放,不需要close
with open("wdnmd.txt", "w") as f:
f.write("wdnmd, fuck")
# 将python对象序列化(转为二进制文件)pickle
import pickle
import time
x, y, z = 7748, 250, 438
s = "wdnmd"
a = {1:"s13", 2:"cnmlch", 3:"fuck"}
with open("./param.pkl", "wb") as f:
pickle.dump((x,y,z,s,a), f)
time.sleep(1)
with open("./param.pkl", "rb") as f:
q, w, e, r, t = pickle.load(f)
print(q, w, e, r, t)
# 异常↑
elif inis == 4:
# 查找异常 https://fishc.com.cn/thread-211613-1-2.html
# 处理异常 try -except
try:
1 / 0
except:
print("wdnmd")
try:
1
# 502 + "fuck" # 错误类型是 TypeError
except ZeroDivisionError as e: # 指定识别异常类型 e:错误原因
print("e")
try:
1 / 0
502 + "fuck"
except (ZeroDivisionError, ValueError, TypeError): # 元组聚合
pass
try:
1 / 0
502 + "fuck"
except ZeroDivisionError: # 分开处理
pass
except TypeError:
pass
# 异常↓
elif inis == 5:
# try-except-else 无异常运行else
# try-except-finally 有无异常都运行finally
# 嵌套异常
try:
try:
502 + "fuck"
except:
print("内部异常")
1 / 0
except:
print("外部异常")
finally:
print("收尾")
# raise ValueError("自爆") # 自爆,主动引发异常
s = "wdnmd"
assert s != "wdnmd" # 条件为false 主动引发异常
P59~P72:类和对象class and object(1)
inis = 11
# 类和对象Ⅰ
if inis == 1:
# 创建类 (封装)
class People:
age = 130
color = "yellow"
def speakOen(self): # 类内函数 第一个参数都要设为self,不然会异常
print("wdnmdlch, fuck")
return
def speakTwo(self, val:str="7438,cnmlch"):
print(val)
return
p = People() # self 实例对象本身
print(p.color)
p.speakTwo("123")
p.hight = 188
print(p.hight) # 和C++不同,还可以直接加属性,当然只适用当前对象,没影响到类
# 类和对象Ⅱ
elif inis == 2:
# 继承
class A:
num = 250
def func(self):
print("A:wdnmdlch")
class B(A):
num = 7438
b = B()
print(b.num)
b.func()
print(isinstance(b, B))
print(isinstance(b, A)) # 对象所属类
print(issubclass(B, A)) # 类B是否为A的子类
# 多重继承
class V:
num = 38
def func(self):
print("V:fuckcnmlch")
class C(A,V):
pass
c = C()
print(c.num) # 以继承的顺序(A,V),同名的先继承先确定(A)
# 组合(类内声明类对象)
class C:
a = A()
v = V()
def func(self):
self.a.func() # (计算机)确定存储位置吧;绑定(码农)
self.v.func()
c = C()
c.func()
# 类和对象Ⅲ
elif inis == 3:
# self 函数改属性
class C:
def setX(self, val):
self.x = val
c = C()
c.setX(250)
print(c.__dict__)
# 用空类来当字典dict,好像挺方便的?
class C:
pass
c = C()
c.x = 250
c.val = "wdnmlch"
print(c.x, "\t", c.val)
# 类和对象Ⅳ
elif inis == 4:
# 构造函数 __init__
class C:
def __init__(self, x, y, *args, **kwargs) -> None:
print('C的init被调用')
self.x = x
self.y = y
def add(self):
return self.x + self.y
c = C(4,8)
print(c.add())
#多继承 __init__ 及super初实验
class A:
def __init__(self, a, *args, **kwargs) -> None:
print('A的init被调用')
self.a = a
def mul(self):
return self.a ** 2
class D(C, A):
def __init__(self, x, y, a) -> None:
C.__init__(self, x, y)
A.__init__(self, a)
# super().__init__(x,y,a) # 这种情况不适用super.__init__ 用类名.__init__更适合
def add(self):
return C.add(self) + self.a
d = D(1,2,3)
print(d.add())
print(d.mul())
# 类和对象Ⅳ super 补充
elif inis == 4.5:
# super 适用菱形继承
# mro 继承 在搜索方法时,是按照 __mro__ 的输出结果 从左至右 的顺序查找的
# 如果在当前类中 找到方法,就直接执行,不再搜索
# 如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
# 如果找到最后一个类,还没有找到方法,程序报错
class Parent(object):
def __init__(self, name, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数
print('parent的init开始被调用')
self.name = name
print('parent的init结束被调用')
class Son1(Parent):
def __init__(self, name, age, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数
print('Son1的init开始被调用')
self.age = age
super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数
print('Son1的init结束被调用')
class Son2(Parent):
def __init__(self, name, gender, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数
print('Son2的init开始被调用')
self.gender = gender
super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数
print('Son2的init结束被调用')
class Grandson(Son1, Son2):
def __init__(self, name, age, gender):
print('Grandson的init开始被调用')
# 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍
# 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因
# super(Grandson, self).__init__(name, age, gender) 效果和下面的一样
super().__init__(name, age, gender)
print('Grandson的init结束被调用')
print(Grandson.__mro__) # 搜索顺序
gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
print('性别:', gs.gender)
# super调用过程:上面gs初始化时,先执行grandson中init方法, 其中的init有super调用,
# 每执行到一次super时,都会从__mro__方法元组中顺序查找搜索。所以先调用son1的init方法,
# 在son1中又有super调用,这个时候就就根据__mro__表去调用son2的init,然后在son2中又有super调用,
# 这个就根据mro表又去调用parent中的init,直到调用object中的init.
# 类和对象Ⅴ
elif inis == 5:
# Mix-in 混入(设计模式) 没啥
class Displayer:
def display(self, message):
print(message)
class LoggerMixin: # 本来只有Displayer、MySubClass;LoggerMixin类似插件
def log(self, message, filename="logfile.txt"):
with open(filename, "a") as f:
f.write(message)
def display(self, message):
super().display(message)
self.log(message)
class MySubClass(LoggerMixin, Displayer):
def log(self, message):
super().log(message, filename="subclasslog.txt")
subclass = MySubClass()
subclass.display("This is a test.")
# 类和对象Ⅵ
elif inis == 6:
# 多态
print(len("wdnmd")) # 内里应该判断了类型再……
print(len(["wdnmd", "cnmlch", "fuck"]))
def func(a,b,c):
print("a,b,c")
def func():
print("wdnmd")
func(1,2,3) # 异常,python没有函数重载
# 类和对象Ⅶ
elif inis == 7:
# "私有变量" 本质是换名 __name
class C:
def __init__(self, val) -> None:
self.__val = val
def __getVal(self):
return self.__val
def setVal(self, val):
self.__val = val
c = C(438)
print(c.__dict__)
# c.__val 、 c__getVal() 报异常
print(c._C__val)
# class类似dict用空间换时间,通过 __slots__ 固定class的空间
class A:
__slots__ = ['x', 'y'] # 固定就两个变量
# def __init__(self, x, y, z) -> None:
# self.x = x
# self.y = y
# self.z = z
def __init__(self, x, y) -> None:
self.x = x
self.y = y
# a = A(1,2,3) # 会报异常
a = A(1,2)
# a.z = 3 # 不能动态添加属性,会报异常
# 继承自父类的_slots属性是不会在子类中生效的
# 类和对象Ⅷ
elif inis == 8:
# 魔法方法 __new__ 、__init__ 、 __del__ # 从左往右依次调用
# __new__方法主要是当你继承一些不可变的 class 时(比如int, str, tuple),提供给你一个自定义这些类的实例化过程的途径
class CapStr(str):
def __new__(cls, string, *args, **kwargs):
string = string.upper()
return super().__new__(cls, string)
def __init__(self, x, y, *args, **kwargs) -> None:
super().__init__()
self.x = x
self.y = y
def __del__(self):
print("del~")
c = CapStr("fuck", 3)
print(c)
print(c.x)
print(c.y)
# 类和对象Ⅸ
elif inis == 9:
# 魔法方法大全 https://fishc.com.cn/thread-214869-1-7.html
class S(str):
def __add__(self, other:str):
return len(self) + len(other)
# return NotImplemented
s1 = S("wdnmd")
s2 = S("fuck")
print(s1 + s2)
# 注1:如果魔法方法中的某一个不支持与所提供参数进行运算,它应该返回 NotImplemented。
# 注2:当两个对象相加的时候,如果左侧的对象和右侧的对象不同类型,并且左侧的对象没有定义 __add__() 方法,或者其 __add__() 返回 NotImplemented,
# 那么 Python 就会去右侧的对象中找查找是否有 __radd__() 方法的定义。
# 注3:如果增强赋值运算符的左侧对象没有实现相应的魔法方法,比如 += 的左侧对象没有实现 __iadd__() 方法,
# 那么将退而求其次,使用相应的 __add__() 方法和 __radd__() 方法来实现。
# 类和对象Ⅹ
elif inis == 10:
# 魔法方法 位运算 有基础,看就行
print(bin(8))
print(3 & 2)
print(1 | 4)
print(~2) # 补码原因
print(3 ^ 4)
# << >>
import math # 数字函数
print(0.1 + 0.2 == 0.3 + math.ulp(0.3))
print(0.1 + 0.2 == 0.3)
# __index__
class C:
def __init__(self, x:int) -> None:
self.x = x
def __index__(self):
print("wdnmdcnmlch")
return self.x
def setVal(self, x:int) -> None:
self.x = x
c = C(3)
# c[3] 错误用法
s = "fuck"
print(s[c])
c.setVal(0)
print(s[c])
# 类和对象Ⅺ
elif inis == 11:
from typing import Any
# 属性访问
class C:
def __init__(self, name, age) -> None:
self.name = name
self.__age = age
c = C("wdnm", 98)
print(hasattr(c, "name"))
print(getattr(c, "_C__age")) # settattr delattr 魔法方法
class C:
def __init__(self, name, age) -> None:
self.name = name
self.__age = age
def __getattribute__(self, __name: str) -> Any:
print("__getattribute__ wdnmd")
return super().__getattribute__(__name)
def __getattr__(self, __name: str): # 访问类没有的属性会调用此函数
print("__getattr__ 访问异常才抛出")
c = C("fuck", 130)
print(getattr(c, "_C__age"))
c.name
print(getattr(c, "nokey"))
c.cnm
print("---------------------------------")
class D:
def __setattr__(self, __name: str, __value: Any):
print("self.__name = __value 会报错,这本身也会调用__setattr__")
return super().__setattr__(__name, __value)
def __delattr__(self, __name: str) -> None:
print("__delattr__ 和 __setattr__ 一样问题")
if ~hasattr(self, __name):
return None
return super().__delattr__(__name)
d = D()
d.name = "cnm"
# d.age = 8
print(d.name)
del d.name
delattr(d, "age")
# 类和对象Ⅻ
elif inis == 12:
class C:
def __init__(self, data: str) -> None:
self.data = data
def __getitem__(self, index):
return(self.data[index])
def __setitem__(self, index, value):
self.data[index] = value
c = C([1,2,3,4,5])
print(c[2])
c[2:4] = c[0:2]
print(c[:])
print(c[2::]) # slice(2, None, None)
s = "wdnmcnmlch"
print(s[slice(1)], s[1])
print(s[slice(5, None)], s[5::]) # 语法糖
print(s[slice(None, None, 2)], s[::2])
# 自定义迭代器
class D:
def __init__(self, start, stop) -> None:
self.value = start -1
self.stop = stop
def __iter__(self):
return self
def __next__(self):
if self.value == self.stop:
raise StopIteration # 主动爆异常
self.value += 1
return self.value * 2
d = D(1, 5)
for i in d:
print(i, end=' ')
# 类和对象XIII
elif inis == 13:
# 魔法方法 in not
class C:
def __init__(self, data) -> None:
self.data = data
def __contains__(self, item):
print("__contains__")
return item in self.data
# __contains__ = None # 静止关系判断 in not 会报异常,针对所有魔法方法有效
c = C([1,2,3,4,5,6,10])
print(10 in c) # 没有 __contains__ 就调 __iter__/__next__ 再没有就调 __getitem__
# bool(object) ==> 无 __bool__ 调 __len__
# __lt__(<)、__le__(<=)、__gt__(>)、__ge__(>=)、__eq__(==)、__ne__(!=)、
# 类和对象XIV
elif inis == 14:
from typing import Any
# 魔法方法 __lt__(<)
class C:
def __call__(self, *args: Any, **kwds: Any) -> Any:
print(f"位置参数-->{args}\n关键字参数-->{kwds}")
c = C()
c(438,250,w="wdnmd",f="fuck")
# str()__str__ repr()__repr__ 两个必须返回字符串
eval("print(\"wdnmdlch\")")
print(repr("fuck")) # 返回对象的规范字符串表示形式。对于许多对象类型,eval(repr(obj)=obj。
class C:
def __init__(self, data) -> None:
self.data = data
def __str__(self) -> str:
return f"data = {self.data}"
def __repr__(self) -> str:
return f"C({self.data})"
c = C(250)
print(c) # 无 __str__ 调 __repr__(适用更广,更稳)
c
P73~P83:类和对象class and object(2)
inis = 25
# 类和对象XV
if inis == 15:
#class property(fget=None,fset=None,fdel=None,doc=None) property()函数用于返回一个property属性对象
class C:
def __init__(self):
self._x = 250
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx)
c = C()
print(c.x)#250
c.x = 520
print(c.__dict__)#{'_x': 520}
del c.x
print(c.__dict__)#{}
#利用__getattr__()、__setattr__()、__delattr__()实现相同目的 比较繁琐,也不好拓展
#propert()函数第一个优点是简化类似遮遮掩掩的操作
# property属性对象(由property函数返回,根据语法糖解析是传给了x)提供了getter、setter和deleter三个方法,这些方法对应property()函数的三个参数接口
class E:
def __init__(self):
self._x = 250
# d = property()
#@d.getter
@property # ==> x = property(x) (语法糖)
def x(self):
return self._x
# d = d.getter(x)
@x.setter # x = x.setter(x)
def x(self, value):
self._x = value
# d = d.setter(x)
@x.deleter
def x(self):
del self._x
# d = d.deleter(x)
e = E()
print(e.x) #250 # print(e.d)
e.x = 520
print(e.__dict__) #{'_x': 520}
del e.x
print(e.__dict__) #{}
# 类和对象XVI
elif inis == 16:
# 类方法 classmethod 设计类属性、类继承用类方法好
class C:
count = 0
@classmethod
def add(cls):
cls.count += 1
def __init__(self) -> None:
self.add()
@classmethod
def printCcount(cls):
print(f"该类{cls.__name__}一共实例 {cls.count} 个对象")
class D(C):
count = 0
class E(D):
count = 0
c1 = C()
d1, d2 = D(), D()
e1, e2, e3 = E(), E(), E()
c1.printCcount()
d1.printCcount()
e1.printCcount()
# 静态方法 staticmethod 不涉及类属性的操作用静态方法好
class C:
count = 0
def __init__(self) -> None:
C.count += 1
@staticmethod
def printCcount(): #普通方法self(自己的类对象),类方法cls(传进来的类对象),静态方法不需要参数
print(f"该类C一共实例 {C.count} 个对象")
c1, c2 = C(), C()
c2.printCcount()
# 类和对象XVII
elif inis == 17:
# 描述符 实现__get__、__set__、__delete__魔法方法的类就为描述符
class D:
def __get__(self, instance, owner): # 三个方法主要用instance参数 :被描述符拦戳的属性所在的类的实例对象
return instance._x
def __set__(self, instance, value):
instance._x = value
def __delete__(self, instance):
del instance._x
class C:
x = D()
def __init__(self, x = 250) -> None:
self._x = 250
c = C()
print(c.x)
c.x = 438
print(c.x)
print(c.__dict__)
del c.x
print(c.__dict__)
# 用property更好,先有描述符后有 property
# 用描述符实现property;用描述符实现__getattr__()、__setattr__()、__delattr__()
# 类和对象XVIII
elif inis == 18:
# 描述符只作用类属性,不作用对象属性self.name
# 描述符访问顺序由低到高,数据描述符(只实现__get__),实例对象属性,非数据描述符(实现__set__、__delete__),类属性
# 描述符第四个魔法方法__set_name__(py3.6) 为了优雅
class D:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
print("get~")
return instance.__dict__.get(self.name)
def __set__(self, instance, value):
print("set~")
instance.__dict__[self.name] = value
def __delete__(self, instance):
print("del~")
del instance.__dict__[self.name]
class C:
x = D()
c = C()
print(c.__dict__)
c.x = 250
print(c.__dict__)
print(c.x)
del c.x
print(c.__dict__)
# 类和对象XIX
elif inis == 19:
# 解读官方文档:python怎么区分函数和方法(class);(通过描述符)
pass
# 类和对象XX
elif inis == 20:
from typing import Any
# 作用于类的装饰器
print("------------------作用于类的装饰器")
def report(cls):
def oncall(*args, **kwargs):
print("开始实例化对象")
_ = cls(*args) # args = (1,2,3)
print("准备返回实例对象")
return _
return oncall
@report # C = report(C)
class C:
def __init__(self, x, y, z) -> None:
self.x = x
self.y = y
self.z = z
print("初始化类中")
c = C(1,2,3)
print(c.__dict__)
# 类装饰函数
print("------------------类装饰函数")
class Counter:
def __init__(self, func, count = 0) -> None:
self.count = count
self.func = func
def __call__(self, *args: Any, **kwds: Any) -> Any:
self.count += 1
print(f"函数调用{self.count}次了")
return self.func(*args, **kwds)
@Counter # printCount = Counter(printCount)
def printCount():
print("wdnmdlch, fuck")
printCount()
printCount()
printCount()
# 类装饰类
print("------------------类装饰类")
def report(cls):
class Check:
def __init__(self, *args, **kwargs) -> None:
self.obj = cls(*args, **kwargs)
def __getattr__(self, name): # 访问类没有的属性会调用此函数
print(f"正在访问{name}...")
return getattr(self.obj, name)
return Check
@report # C = report(C)
class C:
def __init__(self, name) -> None:
self.name = name
def say_hi(self):
print(f"hi{self.name}~")
def say_hey(self):
print(f"hey{self.name}~")
c1 = C("c1") # 顺序:(Check)__init__、(C)__init__
c2 = C("c2")
print(c1.name) # (Check)__getattr__、getattr(c1, name)
print(c2.name)
c1.say_hi()
c2.say_hey()
print(type(c1))
# 类和对象XXI
elif inis == 21:
# type() 返回class class 是由 type 创造而来的
type(250)("250") # int("250")
type("wdnmd")(7438)
class A:
pass
print(type(A))
# type()建立类 type()文档:https://fishc.com.cn/thread-220218-1-8.html
class C:
pass
C = type("C", (), dict(x=250, y=438))
c = C()
print(c.x)
class D:
pass
def func(self, name):
print(f"wdnmdlch, fuck{name}", self.a)
D = type("D", (C,), dict(a="wdnmd", b=func))
d = D()
print(d.x, d.a)
d.b("8.8")
A = type("R",(), dict(z=1314))
a = A()
print(a.z, type(a))
# __init_subclass__ python3.6,增强父类对子类的控制 子类 __init__ 能摆脱
class C:
def __init_subclass__(cls, val1, val2) -> None:
print("__init_subclass__")
cls.val1 = val1
cls.val2 = val2
pass
class D(C, val1=250, val2=438):
val1 = 520
val2 = 1314
# def __init__(self, val1, val2) -> None:
# print("__init__")
# self.val1 = val1
# self.val2 = val2
d = D()
print(d.val1, d.val2)
# type() 最后一个参数 __init_subclass__
class A:
def __init_subclass__(cls, value) -> None:
cls.value = value
pass
class B:
pass
B = type("B", (A,), dict(value=520), value=250) # type()参数:类名、父类、类属性(变量,方法)、__init_subclass__
b = B()
print(b.value)
# 类和对象XXII
elif inis == 22:
from typing import Any
# 元类 metaclass(type是所以元类的父类也是元类)(难,用得少)是创造类的模板
# 元类主要通过 __new__ 、 __init__ 、 __call__ 魔法方法工作
class MetaC(type):
def __new__(mcls, name, bases, attrs): # name为类名,bases为父类,attrs为类里面的属性和方法
print("MetaC __new__:", f"mcls={mcls}, name={name}, bases={bases}, attrs={attrs}")
return type.__new__(mcls, name, bases, attrs)
def __init__(cls, name, bases, attrs):
print("MetaC __init__:", f"cls={cls}, name={name}, bases={bases}, attrs={attrs}")
return type.__init__(cls, name, bases, attrs)
def __call__(cls, *args: Any, **kwds: Any) -> Any:
print("MetaC __call__:", f"args={args}, kwds={kwds}")
# return type.__call__(cls, *args, **kwds)
class B:
pass
class C(B, metaclass=MetaC):
def __new__(cls):
print("C __new__:", f"cls={cls}")
return super().__new__(cls)
def __init__(self) -> None:
print("C __init__:", f"self={self}")
c = C(123, 321, x=520, y=1314)
# c = C() # 把 MetaC __call__ 注释了
# 类C创建完成 调用MetaC __new__、__init__,而MetaC的 __call__ 会截胡掉C的实例化操作(__new__、__init__)
# 类和对象XXIII
elif inis == 23:
from typing import Any
# 元类在实际开发中的作用
# 给所有的类添加属性、 对类名的定义规范做限制、修改对象的属性值、限制类实例化时的传参方式、禁止一个类被实例化、只允许实例化一个对象
class MetaC(type):
def __init__(cls, name, bases, attrs): # 大部分在 __new__ 内也可完成
# 给所有的类添加属性、
cls.author = "Sr"
# 对类名的定义规范做限制
if not name.istitle():
raise TypeError("类名必须为大写~")
# 只允许实例化一个对象(1)
cls.__instance = None
return type.__init__(cls, name, bases, attrs)
def __call__(cls, *args: Any, **kwds: Any) -> Any:
# 修改对象的属性值 -> 如:把对象的所有字符串属性值都变成大写
new_args = [each.upper() for each in args if isinstance(each, str)]
# 限制类实例化时的传参方式
if kwds:
raise TypeError("只能位置参数传参~")
# 只允许实例化一个对象(2)
if cls.__instance is None:
cls.__instance = type.__call__(cls, *new_args, **kwds)
return cls.__instance
else:
return cls.__instance
# 禁止一个类被实例化 做成单例类一样
class NoInstances(type):
def __call__(self, *args, **kwargs):
raise TypeError('该类禁止实例化!')
class C(metaclass=NoInstances):
@classmethod
def funcClass(cls):
print("类方法可调用~")
@staticmethod
def funcStantic():
print("静态方法可调用~")
pass
# c = C()
C.funcClass()
C.funcStantic()
class C(metaclass=MetaC):
def __init__(self, name) -> None:
self.name = name
c = C("wdnmd")
c2 = C()
print(c.author)
print(c.name)
print(c is c2)
# c = C(name="123")
# class e(metaclass=MetaC):
# pass
# 类和对象XXIV
elif inis == 24:
# 抽象基类 编程规范的实施手段
from abc import ABCMeta, abstractmethod
class Fruit(metaclass=ABCMeta):
def __init__(self, name) -> None:
self.name = name
@abstractmethod # 继承的类必须实现此方法;类不能直接实例化;metaclass=ABCMeta的类才能用此装饰
def good_for_health(self):
pass
# f = Fruit("pitaya") # 报错异常
class Pitaya(Fruit):
def __init__(self, name) -> None:
super().__init__(name)
def good_for_health(self):
print("10块钱5个~", self.name)
p = Pitaya("火龙果")
p.good_for_health()
# 类和对象XXV
elif inis == 25:
# 探讨
# python的 import 模组学习:https://fishc.com.cn/forum-319-1.html
pass
P84~P86:模块和包modules and packages
inis = 3
# 模块和包↑
if inis == 1:
# 模块是python中最高级别的组织结构 而包是一个模块的集合,可以将多个模块的功能组合到一起,同时还可以包含其他子包
# python高校开发主要就是导包,根据需求选择导入包 (.py其实就是一个包)
# 三种导入模块的方式
# import 模块名称
# from 模块名称 import 对象名称
# import 模块名称 as 关联名称
import modules.hello
from modules.hello import * # say_fuck # 对于包来说,如果没有定义__all__,那么 from...import * 的语法则不导入包里面的任何模块。
from modules.hello_for_diu import *
import modules.hello_for_diu as h # 模块内重名,有标识》导入顺序(最后导入的优先)
modules.hello.say_wdnmd()
say_fuck()
h.say_fuck()
# 模块和包-
elif inis == 2:
# if(__name__ == "__main__") 看modules/pc.py
from modules.pc import cTof as c, fToc as f
print(f"{c(39):.2f}")
print(f"{f(39):.2f}")
# 包 python3.3之前需要在包文件夹内创建__init__.py文件
# 编写 __init__.py 对包进行初始化操作
import package
print(package.x, package.y)
package.pc.printX()
# __all__
# 对于模块来说,如果没有定义__all__属性,那么 from...import * 的语法将导入模块中的所有东西:
# 对于包来说,如果没有定义__all__,那么 from...import * 的语法则不导入包里面的任何模块。
from modules.hello import *
say_wdnmd()
# say_fuck() # 会异常
from package import *
pc.printX()
# 模块和包↓
elif inis == 3:
# 上传代码模块、包到pipy分享
pass