面向对象内置方法
【一】方法
-
Python的Class机制内置了很多特殊的方法来帮助使用者高度定制自己的类
-
这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发
__init__ :初始化对象时触发
__del__ :销毁类时触发
__new__ :构造类时触发
__str__ :str函数或者print函数触发
__repr__ :repr或者交互式解释器触发
__doc__ :打印类内的注释内容
__enter__ :打开文档触发(with语句打开的时候触发)
__exit__ :关闭文档触发(with语句关闭的时候触发)
__getattr__ : 访问不存在的属性时调用
__setattr__ :设置实例对象的一个新的属性时调用
__delattr__ :删除一个实例对象的属性时调用
__setitem__ :列表添加值
__getitem__ :将对象当作list使用
__delitem__ :列表删除值
__call__ :对象后面加括号,触发执行
__iter__ :迭代器
-
方法
__init__()
,__del__()
,__init__()
-
这个方法是一个类的构造函数,与之对应的
__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')
print("111")
# __new__
# __init__
# do something
# 111
# __del__
-
方法
__str__
:str函数或者print函数触发-
__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>
-
方法
__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))#from repr: School(dreamCity,北京)
print('from str: ', str(s1))#from str: (dreamCity,北京)
print(s1)#(dreamCity,北京)
-
__del__
方法-
__del__
会在对象被删除时自动触发。
-
class Person():
def __init__(self, name, age):
print(f'这是 :>>>> {name} , age :>>>> {age}')
def __del__(self):
print(f"我离开你了")
person = Person("dream", 18)
print("这是断层")
# 这是 :>>>> dream , age :>>>> 18
# 这是断层
# 我离开你了
-
方法
isinstance(obj,cls)
-
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)#True
print(res_Bar)#False
-
方法
issubclass(sub,super)
-
issubclass(sub, super)
检查sub
类是否是super
类的派生类
-
class Foo(object):
pass
class Bar(Foo):
pass
res = issubclass(Bar, Foo)
print(res)#True
-
方法
__doc__
-
打印类内的注释内容
-
class Foo:
'我是描述信息'
pass
print(Foo.__doc__)
#我是描述信息
-
方法
__enter__
和__exit__
-
打开文档触发
-
-
为了让一个对象兼容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('=====>执行代码块')
#出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
# =====>执行代码块
# with中代码块执行完毕时执行我啊
-
__exit__()
中的三个参数分别代表-
异常类型
-
异常值
-
追溯信息
-
-
with语句中代码块出现异常,则with后的代码都无法执行
-
方法
__setattr__
,__delattr__
,__getattr__
-
__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)#----> from setattr key : y value : 10
# 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
print(f1.__dict__)#{}
f1.z = 3#----> from setattr key : z value : 3
print(f1.__dict__)#{}
# # __delattr__删除属性的时候会触发
f1.__dict__['a'] = 3 # 我们可以直接修改属性字典,来完成添加/修改属性的操作
print(f1.__dict__)#{'a': 3}
del f1.a#----> from delattr :>>>> a
print(f1.__dict__)#{}
# __getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx#----> from getattr:你找的属性不存在 :>>>> xxxxxx
-
对象属性查找顺序
-
首先访问
__getattribute__()
魔法方法(隐含默认调用,无论何种情况,均会调用此方法 -
去实例对象
t
中查找是否具备该属性:t.__dict__
中查找,每个类和实例对象都有一个__dict__
的属性 -
若在
t.__dict__
中找不到对应的属性, 则去该实例的类中寻找,即t.__class__.__dict__
-
若在实例的类中也招不到该属性,则去父类中寻找,即
t.__class__.__bases__.__dict__
中寻找 -
若以上均无法找到,则会调用
__getattr__
方法,执行内部的命令(若未重载__getattr__
方法,则直接报错:AttributeError
)
-
-
方法
__setitem__
,__getitem__
,__delitem__
-
__setitem__
:列表添加值 -
__getitem__
:将对象当作list使用 -
__delitem__
:列表删除值
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')
#执行def __setitem__
f1['age'] = 18
#执行def __delitem__
del f1['age']#del obj[key]时,我执行
#执行def __getitem__
f1['age1'] = 19
#执行__delattr__(self, item)
del f1.age1#del obj.key时,我执行
#给实例化对象添加属性
f1['name'] = 'alex'
print(f1.__dict__)#{'name': 'alex'}
-
方法
__call__
-
对象后面加括号,触发执行
-
注:构造方法的执行是由创建对象触发的
-
即:对象 = 类名() ;
-
-
而对于
__call__
方法的执行是由对象后加括号触发的-
即:对象() 或者 类()()
-
-
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
-
方法
__iter__()
-
迭代器
-
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)
# 1
# 1
# 2
# 3
# 5
# 8
-
方法
isinstance()
-
判断当前对象是否是某一个类的类型
-
#数据
print(isinstance("tom",str))#True
print(isinstance(4,str))#False
#类
class Person:
...
class Student(Person):
...
student = Student()
person = Person()
print(isinstance(student, Student)) # True
print(isinstance(person, Person)) # True
print(isinstance(person, Student)) # False
# 因为Person是Student父类,所以返回True
print(isinstance(student, Person)) # True
-
方法
issubclass()
-
检验一个类是否属于另一个类的子类
-
class Person:
...
class Student(Person):
...
print(issubclass(Student, Person)) # True
【二】小总结(属性名,属性值)
-
对象[属性名] = 属性值---》触发
__setitem__
方法 -
print(对象[对象])--->>触发了
__getitem__
方法 -
对象.属性名 = 属性值---》>>触发
__setattr__
方法 -
对象.对象 = 属性值 --- >>触发了
__setattr__
方法