跟着小甲鱼学python【Python教程】《零基础入门学习Python》最新版(2022年11月11日更新)_哔哩哔哩_bilibili
1.浅拷贝:重新分配一块内存,创建一个新的对象,但里面的元素是对原对象中各个子对象的引用,浅拷贝只是拷贝外层对象,如果包含嵌套对象的话,拷贝的只是它的引用。
2.深拷贝:重新分配一块内存,创建一个新的对象,并将原对象中的元素以递归的方式拷贝,拷贝了原对象的引用,也拷贝了子对象的引用。使用copy模块实现深拷贝。
B试图用*对列表进行拷贝,实际拷贝的是对列表的引用。 浅拷贝还包括:x=[1,2,3],y=x[:]
import copy
list1 = [[1, 2],(3, 4)]
list2 = list(list1)
list3 = copy.deepcopy(list1)
list1.append(5)
list1[0].append(10)
list1[1] += (30,40)
print(list1)
print(list2)
print(list3)
结果:
[[1, 2, 10], (3, 4, 30, 40), 5]
[[1, 2, 10], (3, 4)]
[[1, 2], (3, 4)]
计算机语言中特殊的某种语法,这种语法对语言的功能并没有影响,对于程序员有更好的易用性,能够增加程序的可读性。
比如:print(F"{year}年"),a,b=b,a, list[:]
L-local(当前所在命名,函数模块),E-Enclosed(嵌套函数的外层),G-Global(全局变量),B-Build-In(内置)
比如:str='1',str(1)就会报错
python会根据LEGB原则选择变量的作用域
闭包:利用嵌套函数记住外层变量,内层函数作为返回值
比如游戏角色位移:
#游戏角色移动
origin = (0,0) #原点
legal_x = [-100,100] #限定x轴的移动范围
legal_y = [-100,100] #限定y轴的移动范围
def create(pos_x = 0, pos_y = 0):
def moving(direction, step):
nonlocal pos_x, pos_y #外部嵌套函数内的变量
new_x = pos_x + direction[0] * step
new_y = pos_y + direction[1] * step
return new_x, new_y
return moving
move = create()
print(move([1,0],20))
装饰器:
给现有的模块添加新的小功能,符合面向对象编程的开放封闭原则
语法糖:@
import functools
import time
import functools
def logger(msg):
def time_master(fun):
@functools.wraps(fun) #使__name__返回调用函数myfun的名称
def call_fun():
print("程序开始运行")
start = time.time()
fun()
stop = time.time()
print("程序结束了")
print(f"程序运行时间{(stop - start):.2f}秒。")
return call_fun
return time_master
@logger(msg="myfun")
#myfun = logger(msg="myfun")
def myfun():
time.sleep(2)
print("运行.......")
myfun()
print(myfun.__name__)
yield
def counter():
i = 0
while i <= 5:
yield i
i += 1
print(counter())
for i in counter():
print(i)
生成器是一个特殊的迭代器,支持next(),没办法用下标索引,全部迭代完之后会生成StopIteration的异常
def fib():
back1, back2 = 0, 1
while True:
yield back1
back1, back2 = back2, back1 + back2
f = fib()
for i in range(10):
print(next(f))
生成器表达式
#生成器表达式
t = (i ** 2 for i in range(10))
for i in range(10):
print(next(t))
汉诺塔
def hanoi(n, x, y, z):
if n == 1:
print(x, '-->', z) #如果只有一层,直接将金片从x移动到z
else:
hanoi(n - 1, x, z, y) #将x上的n - 1个金片移动到y
print(x, '-->', z) #将最底下的金片从x移动到z
hanoi(n - 1, y, x, z) #将y上的n - 1个金片移动到z
n = int(input('请输入汉诺塔的层数:'))
hanoi(n, 'A', 'B', 'C')
1.绝对路径:从根目录开始一级一级地指向最终目录或文件、文件夹
2.相对路径:以当前目录为基准
from pathlib import Path
Path.cwd() #获取目录路径
p = Path(r"D:\编程学习\python\pythonProject\venv") #生成路径对象
p = p/"abc.txt" #拼接
p.is_dir()#是否是一个文件夹
p.is_file()#是否是一个文件
p.exists()#是否存在
p.name#获取路径最后一个部分
p.stem#获取文件名
p.suffix#获取后缀
p.parent#获取父级目录
p.parents#获取逻辑祖先路径构成的序列,支持索引
p.parts#返回元组
p.stat()#查询文件或文件夹的信息
p.stat().st_size#尺寸
p.resolve()#将相对路径转换为绝对路径
p.iterdir()#获取当前路径下所有子文件和子文件夹(生成器)
# p.mkdir()#创建文件夹
p.mkdir(parents=True)#创建不存在的父目录
p.mkdir(exist_ok=True)#文件夹已经存在,不报错
p.open("r")#与open()一样
p.rename()#重命名,移动
p.replace()#移动
p.rmdir()#删除
p.glob(".txt")#查找
list(p.glob("*/*.py"))
list(p.glob("**/*.py"))#当前目录下的子目录
pickle:python对象序列化,转化成二进制
import pickle
x, y, z = 1, 2, 3
l = [1,1,1,1,1]
with open("data.pkl","wb") as f:
# pickle.dump(x, f)
# pickle.dump(l, f)
pickle.dump((x, y), f)
import pickle
with open("data.pkl","rb") as f:
x = pickle.load(f)
y = pickle.load(f)
print(x, y, sep="\n")
1.try-except
2.try-except-else
3.try-except-finally
4.raise,assert
5.利用异常实现goto
try:
while True:
while True:
for i in range(10):
if i > 3:
raise
print(i)
print("被跳过~")
print("被跳过~")
print("被跳过~")
except:
print("到这儿")
class Turtle:
head = 1
eyes = 2
def run(self):#self实例对象本身
# 因为可以生成非常多的实例对象,self传递调用对象的信息
print(self)
print("跑")
def eat(self):
print("吃")
t1 = Turtle()#实例对象
print(t1.head)
t1.run()
t1.eat()
t1.mouse = 1#添加属性
print(t1.mouse)
self:默认的第一个参数,传递实例对象的信息
1.继承
(1)isinstance继承关系
(2)issubclass检测一个类是否是某个类的子类
(3)支持多重继承,从左到右的顺序访问
(4)组合
class Turtle:
def say(self):
print("龟")
class Cat:
def say(self):
print("喵喵")
class Dog:
def say(self):
print("汪汪")
class Gardom:
t = Turtle()
c = Cat()
d = Dog()
def say(self):
self.t.say()
self.c.say()
self.d.say()
g = Gardom()
g.say()
(5)绑定
class C:
def get_self(self):
print(self)
def set_x(self, v):#设置实例属性
self.x = v
c = C()#C.get_self(c)
print(c.get_self())
#<__main__.C object at 0x00000212BA599300>
c.set_x(250)
c.__dict__
#{'x':250}
实例对象跟类的方法进行绑定,类的实例对象有千千万万,而实例对象共享类的方法,调用c.get_self()的时候,实际的含义是调用类C的get_self()方法,进而将实例对象作为参数传递进去进行绑定。
(6)内省 __dict__
(7)利用最小的类实现字典的功能
class C:
pass
C.x = 250
C.y = [1, 2]
C.z = '小甲鱼'
(8)钻石继承
A会被初始化两次
super()能在父类中搜索指定方法,并自动绑定好self参数
(9)mixin
(10)鸭子类型
鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。
class Duck:
def quack(self):
print("嘎嘎嘎嘎。。。。。")
class Bird:
def quack(self):
print("bird imitate duck....")
class geese:
def quack(self):
print("doge imitate duck....")
def in_the_forest(duck):
duck.quack()
duck = Duck()
bird = Bird()
doge = geese()
for x in [duck, bird, doge]:
in_the_forest(x)
(11)name mangling名字改编,如私有变量__name,但是还是可以访问到,可以用__dict__查询。
_单个下横线开头的变量,仅供内部使用,单个下横线结尾的变量_,比如用到class,可以写成class_。
(12)__slots__
不能动态添加属性,不使用字典减少对空间的使用,同时也失去python动态语言的灵活性。
继承自父类的__slots__属性是不会在子类中生效的。
(13)魔法方法
1.在调用__init__(self[, .... ])之前实际上先调用了__new__(cls[, ....])返回self,使用到__new__有两种情况,一种是在元类中去定制类,另一种情况是在继承不可变数据类型的时候。
2.__del__销毁类,python有垃圾回收机制,对象被销毁的时候才会调用__del__,当对象没有任何引用的时候才会被销毁。del是对象被销毁前的最后拦截,可以利用del实现对象的重生。del方法可以通过创建一个该实例的新引用来推迟其销毁。
3.加法拦截
4.位运算
5.其它
math和__index__