内置方法
1.计算机基础2.编程语言和Python语言介绍3.八大基本数据类型4.python语法入门变量和常量5.python和pycharm相关补充6.计算机五大部件补充7.文件操作8.编码和解码9.字符编码10.基本数据类型的内置方法11.循坏结构12.流程控制13.基本运算符14.程序与用户交互15.迭代器16.闭包函数17.装饰器18.多层语法糖嵌套19.函数的参数20.函数的可变长参数21.命名关键字参数22.名称空间与作用域23.异常处理24.深浅拷贝问题25.函数的定义和调用26.控制文件读写内容的模式27.主动控制文件内指针移动28.文件的操作方法29.垃圾回收机制GC30.可变与不可变类型31.元类
32.内置方法
33.pickle模块34.单例模式35.方法补充issubclass和isinstance36.多态37.继承38.面向对象的三大特性39.封装40.内置函数41.面向对象42.logging模块43.subprocess模块44.正则45.datetime模块46.time模块47.绝对路径和相对路径48.random模块49.os模块50.hashlib模块51.模块与包52.json模块53.生成器54.三元运算符内置方法
引入
- Python的Class机制内置了很多特殊的方法来e帮助使用者高度定制自己的类
- 这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发
__init__ :初始化类时触发
__del__ :删除类时触发
__new__ :构造类时触发
__str__ :str函数或者print函数触发
__repr__ :repr或者交互式解释器触发
__doc__ :打印类内的注释内容
__enter__ :打开文档触发
__exit__ :关闭文档触发
__getattr__ : 访问不存在的属性时调用
__setattr__ :设置实例对象的一个新的属性时调用
__delattr__ :删除一个实例对象的属性时调用
__setitem__ :列表添加值
__getitem__ :将对象当作list使用
__delitem__ :列表删除值
__call__ :对象后面加括号,触发执行
- __init__方法:初始化对象的时候被触发
- __str__方法:打印对象的时候会触发,有返回值,返回值必须是字符串
- __call__方法:使对象像函数一样被调用---对象()
- __getattr__方法:获取不存在的属性的时候会被触发
- __setattr__方法:设置对象属性的时候被触发
- __delattr__方法:删除对象的属性的时候被触发
"""魔法方法"""
# 魔法方法就是双下划线__init__的方法
# 为什么叫魔法方法:这些方法在类中会自动触发
class Person(object):
# __init__方法:初始化对象的方法:在初始化对象的属性的时候会触发
def __init__(self,name):
self.name=name
# __str__方法:在打印的时候会触发,返回值必须是字符串
# 用处就是用来打印对象的时候显示对象的信息
def __str__(self):
print("打印的时候触发")
return f"当前打印的是{self.name}的信息"
# __getattr__方法:获取不存在的属性触发,他不会报错
def __getattr__(self, item):
# item : 就是对象.属性名时候的那个属性名称
return f'{item}不存在!'
# 设施实例对象的一个新属性的时候调用
def __setattr__(self, key, value):
print(f"{key} {value}")
# 删除一个实例化对象的属性的时候调用
def __delattr__(self, item):
print(f"{item}已经被删除!")
# __call__方法:当想把对象当函数调用的时候可以给类加入一个__call__方法,让对象可以像函数一样调用
def __call__(self, *args, **kwargs):
print(args)
print(kwargs)
print(f"使对象像函数一样被调用的时候触发我")
s=Person(name='syh')
# 打印实例化得到的对象 可以触发__str__方法
print(s)
# 打印的时候触发
# 当前打印的是syh的信息
print(s.sex)# sex不存在!
del s.name# name已经被删除!
s.sex='female' #sex female
s()
# ()
# {}
# 使对象像函数一样被调用的时候触发我
- __new__方法:构造类的时候触发
class Person(object):
_instence=None
# __new__方法:构造类的时候触发
def __new__(cls, *args, **kwargs):
# cls :指的是当前的类
if cls._instence is None:
cls._instence=super().__new__(cls,*args,**kwargs)
# print(super())# <super: <class 'Person'>, <Person object>>
# print(cls._instence)# <__main__.Person object at 0x000001DB87529EA0>
return cls._instence
P=Person()
(一)__init__()
,__del__()__
,__new__()
- Python的Class机制内置了很多特殊的方法来帮助使用者高度定制自己的类
- 这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发
- 这个方法是一个类的构造函数,与之对应的
__del__()
是析构函数,通过此方法我们可以定义一个对象的初始操作。 - 但实际上,新式类的
__new__()
才是真正的初始化函数。
class A(object):
def __init__(self):
print('__init__')
def __new__(cls, *args, **kwargs):
print('__new__')
# cls表示一个类,一个当前要被实例化的类,参数由py解释器自动提供
return super().__new__(cls, *args, **kwargs)
def __del__(self):
print('__del__')
a = A()
print('do something')
# __new__
# __init__
# do something
# __del__
# 实际上,
# __new__()负责创建一个对象,
# __init__负责定制化该对象,即是在对象创建好之后初始化变量
- 既然知道了
__new__()
方法,我们是不是可以考虑一下,如何应用它呢?最常见的就是单例模式了,下面给出实现实例。
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
"""
注意这实际上是一个类方法, cls 表示当前类
:param args:
:param kwargs:
:return:
"""
if cls._instance is None:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
s1 = Singleton()
s2 = Singleton()
if s1 is s2:
print('yeah')
(二)__str__
,__repr__
【1】__str__
-
__str__
方法会在对象被打印时自动触发
- print功能打印的就是它的返回值
- 我们通常基于方法来定制对象的打印信息
- 该方法必须返回字符串类型
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
# 返回类型必须是字符串
return f'<Name:{self.name} Age:{self.age}>'
person = People('dream', 18)
print(person) # 触发p.__str__(),拿到返回值后进行打印
# <Name:dream Age:18>
【2】__repr__
- repr或者交互式解释器触发
class School:
def __init__(self, name, addr, type):
self.name = name
self.addr = addr
self.type = type
def __repr__(self):
return 'School(%s,%s)' % (self.name, self.addr)
def __str__(self):
return '(%s,%s)' % (self.name, self.addr)
s1 = School('dreamCity', '北京', '私立')
print('from repr: ', repr(s1))
print('from str: ', str(s1))
print(s1)
【3】小结
- str函数或者print函数--->
obj.__str__()
- repr或者交互式解释器--->
obj.__repr__()
- 如果
__str__
没有被定义,那么就会使用__repr__
来代替输出 - 注意:这俩方法的返回值必须是字符串,否则抛出异常
(三)del`方法
__del__
会在对象被删除时自动触发。- 由于Python自带的垃圾回收机制会自动清理Python程序的资源,所以当一个对象只占用应用程序级资源时,完全没必要为对象定制
__del__
方法 - 但在产生一个对象的同时涉及到申请系统资源(比如系统打开的文件、网络连接等)的情况下
- 关于系统资源的回收,Python的垃圾回收机制便派不上用场了
- 需要我们为对象定制该方法,用来在对象被删除时自动触发回收系统资源的操作
class MySQL:
def __init__(self, ip, port):
# 伪代码,发起网络连接,需要占用系统资源
self.conn = connect(ip, port)
def __del__(self):
# 关闭网络连接,回收系统资源
self.conn.close()
# 在对象obj被删除时,自动触发obj.__del__()
obj = MySQL('127.0.0.1', 3306)
class Person():
def __init__(self, name, age):
print(f'这是 :>>>> {name} , age :>>>> {age}')
def __del__(self):
print(f"我离开你了")
person = Person("dream", 18)
print("这是断层")
(四)isinstance(obj,cls)
和issubclass(sub,super)
isinstance(obj,cls)
检查是否obj
是否是类cls
的对象
class Bar():
pass
class Foo(object):
pass
foo = Foo()
bar = Bar()
# isinstance(obj,cls)检查是否obj是否是类cls的对象
res_Foo = isinstance(foo, Foo)
res_Bar = isinstance(foo, Bar)
print(res_Foo)
print(res_Bar)
issubclass(sub, super)
检查sub
类是否是super
类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
res = issubclass(Bar, Foo)
print(res)
(五)doc`
class Foo:
'我是描述信息'
pass
print(Foo.__doc__)
class Foo:
'我是描述信息'
pass
class Bar(Foo):
pass
# 该属性无法继承给子类
print(Bar.__doc__)
(六)__enter__
和__exit__
# 我们知道在操作文件对象的时候可以这么写
with open('a.txt') as f:
'代码块'
- 上述叫做上下文管理协议,即with语句
- 为了让一个对象兼容with语句,必须在这个对象的类中声明
__enter__
和__exit__
方法
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
with Open('a.txt') as f:
print('=====>执行代码块')
# print(f,f.name)
__exit__()
中的三个参数分别代表- 异常类型
- 异常值
- 追溯信息
- with语句中代码块出现异常,则with后的代码都无法执行
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
print('0' * 100) # ------------------------------->不会执行
-
如果
__exit__()
返回值为True,那么异常会被清空,就好像啥都没发生一样
- with后的语句正常执行
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
return True
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
print('0' * 100) # ------------------------------->会执行
# 出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
# =====>执行代码块
# with中代码块执行完毕时执行我啊
# <class 'AttributeError'>
# ***着火啦,救火啊***
# <traceback object at 0x000002591C0AC140>
# 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
(七)__setattr__
,__delattr__
,__getattr__
【1】方法介绍
__getattr__(self, name)
: 访问不存在的属性时调用__setattr__(self, name, value)
:设置实例对象的一个新的属性时调用__delattr__(self, name)
:删除一个实例对象的属性时调用
class Foo:
x = 1
def __init__(self, y):
self.y = y
def __getattr__(self, item):
print(f'----> from getattr:你找的属性不存在 :>>>> {item}')
def __setattr__(self, key, value):
print(f'----> from setattr key : {key} value : {value}')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print(f'----> from delattr :>>>> {item}')
# del self.item #无限递归了
self.__dict__.pop(item)
# __setattr__添加/修改属性会触发它的执行
f1 = Foo(10)
# 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
print(f1.__dict__)
f1.z = 3
print(f1.__dict__)
# __delattr__删除属性的时候会触发
f1.__dict__['a'] = 3 # 我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
# __getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
- 对象属性查找顺序
- 首先访问
__getattribute__()
魔法方法(隐含默认调用,无论何种情况,均会调用此方法 - 去实例对象t中查找是否具备该属性:
t.__dict__
中查找,每个类和实例对象都有一个__dict__
的属性 - 若在
t.__dict__
中找不到对应的属性, 则去该实例的类中寻找,即t.__class__.__dict__
- 若在实例的类中也招不到该属性,则去父类中寻找,即
t.__class__.__bases__.__dict__
中寻找 - 若以上均无法找到,则会调用
__getattr__
方法,执行内部的命令(若未重载__getattr__
方法,则直接报错:AttributeError)
- 首先访问
【2】二次加工标准类型(包装)
(1)包装
- 包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)
# 继承list所有的属性,也可以派生出自己新的,比如append和mid
class List(list):
def append(self, p_object):
' 派生自己的append:加上类型检查'
if not isinstance(p_object, int):
raise TypeError('must be int')
super().append(p_object)
@property
def mid(self):
'新增自己的属性'
index = len(self) // 2
return self[index]
l = List([1, 2, 3, 4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #报错,必须为int类型
print(l.mid)
# 其余的方法都继承list的
l.insert(0, -123)
print(l)
l.clear()
print(l)
(2)授权
- 授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。
- 授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
- 实现授权的关键点就是覆盖
__getattr__
方法
import time
class FileHandle:
def __init__(self, filename, mode='r', encoding='utf-8'):
# 定义一个文件句柄 ---- 文件打开 并 将文件句柄给 self.file
self.file = open(filename, mode, encoding=encoding)
def write(self, line):
t = time.strftime('%Y-%m-%d %T')
self.file.write('%s %s' % (t, line))
def __getattr__(self, item):
# 返回 映射方法 ---- 映射自己self.file 是否存在 read 方法
# print(item) # read
return getattr(self.file, item)
# 实例化类得到对象
f1 = FileHandle('b.txt', 'w+')
# 写入文本内容
f1.write('你好啊')
# 移动光标
f1.seek(0)
# 触发 __getattr__(self, item) 方法 , self 是 f1 对象 ,item 是 read 方法
print(f1.read())
# 关闭 对象
f1.close()
# 自定义文件处理器
class FileHandle:
def __init__(self, filename, mode='r', encoding='utf-8'):
if 'b' in mode:
self.file = open(filename, mode)
else:
self.file = open(filename, mode, encoding=encoding)
self.filename = filename
self.mode = mode
self.encoding = encoding
def write(self, line):
if 'b' in self.mode:
if not isinstance(line, bytes):
raise TypeError('must be bytes')
self.file.write(line)
def __getattr__(self, item):
return getattr(self.file, item)
def __str__(self):
if 'b' in self.mode:
res = "<_io.BufferedReader name='%s'>" % self.filename
else:
res = "<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" % (self.filename, self.mode, self.encoding)
return res
f1 = FileHandle('b.txt', 'wb')
# f1.write('你好啊啊啊啊啊')
# #自定制的write,不用在进行encode转成二进制去写了,简单,大气
f1.write('你好啊'.encode('utf-8'))
print(f1)
f1.close()
(八)__setitem__
,__getitem__
,__delitem__
__getitem__()
将对象当作list使用- 如obj = ACLASS(), obj_first=obj[0]
class Foo:
def __init__(self, name):
self.name = name
def __getitem__(self, item):
print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item)
f1 = Foo('sb')
f1['age'] = 18
f1['age1'] = 19
del f1.age1
del f1['age']
f1['name'] = 'alex'
print(f1.__dict__)
(九)__call__
- 对象后面加括号,触发执行。
- 注:构造方法的执行是由创建对象触发的
- 即:对象 = 类名() ;
- 而对于
__call__
方法的执行是由对象后加括号触发的- 即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
(十)__gt__()
,__lt__()
,__eq__()
,__ne__()
,__ge__()
- 定义对象比较方法,为关系运算符>,>=,<,==等提供接口
class SavingsAccount(object):
def __init__(self, name, pin, balance=0.0):
self._name = name
self._pin = pin
self._balance = balance
def __lt__(self, other):
return self._balance < other._balance
s1 = SavingsAccount("dream", "1000", 0)
s2 = SavingsAccount("hope", "1001", 30)
print(s1 < s2)
- 其实,类似的数值运算的魔法方法非常非常之多,好吧,我真的用了两个,现在是三个非常来形容,以下列出部分
class Point(object):
def __init__(self):
self.x = -1
self.y = 5
# 正负,取反、绝对值
def __pos__(self):
pass
def __neg__(self):
pass
def __invert__(self):
pass
def __abs__(self):
pass
# 加减乘除、取余,指数
def __add__(self, other):
pass
def __sub__(self, other):
pass
def __divmod__(self, other):
pass
def __mul__(self, other):
pass
def __mod__(self, other):
pass
def __pow__(self, power, modulo=None):
pass
# 逻辑运算符
def __and__(self, other):
pass
def __or__(self, other):
pass
def __xor__(self, other):
pass
# 位移
def __lshift__(self, other):
pass
def __rshift__(self, other):
pass
# 赋值语句
def __iadd__(self, other):
pass
def __imul__(self, other):
pass
def __isub__(self, other):
pass
def __idiv__(self, other):
pass
def __imod__(self, other):
pass
def __ipow__(self, other):
pass
def __ilshift__(self, other):
pass
def __irshift__(self, other):
pass
(十一)__iter__()
- 为for … in提供接口,返回一个迭代对象,并调用对象next()方法,直到StopIteration
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def __next__(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 10: # 退出循环的条件
raise StopIteration()
return self.a # 返回下一个值
for i in Fib():
print(i)
(十二)描述符(__get__()
,__set__()
,__delete__()
)
【1】什么是描述符
- 描述符本质就是一个新式类,在这个新式类中
- 至少实现了
__get__()
,__set__()
,__delete__()
中的一个 - 这也被称为描述符协议
- 至少实现了
__get__()
:调用一个属性时,触发__set__()
:为一个属性赋值时,触发__delete__()
:采用del删除属性时,触发
class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
pass
def __delete__(self, instance):
pass
【2】描述符的作用
- 描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
【3】描述符分两种
- 数据描述符:至少实现了
__get__()
和__set__()
class Foo:
def __set__(self, instance, value):
print('set')
def __get__(self, instance, owner):
print('get')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)