文章目录
- 一、isinstance和issubclass
- 二、\_\_getattribute__
- 三、\_\_setitem\_\_,\_\_getitem\_\_,\_\_delitem\_\_
- 四、\_\_str\_\_、\_\_repr\_\_、\_\_format\_\_
- 五、\_\_slots__
- 六、\_\_doc__
- 六、\_\_module__、\_\_class__
- 七、\_\_call__
- 八、\_\_iter__、\_\_next__
- 九、\_\_del__
- 十、\_\_enter__,\_\_exit\_\_
- 十一、__new__方法
- 十二、__eq__方法
- 十三、__hash__方法
- 十四、__len__方法
一、isinstance和issubclass
-
isinstance(obj,cls)
判断某一个实例是否属于某一个类,若属于返回True,否则返回False -
isinstance(sub,super)
判断某一个子类是否属于某一个父类,若属于返回True,否则返回False
二、__getattribute__
__getattribute__(self,item)
这个方法和__getattr__有点类似,当某个实例访问类属性的时候会触发这个函数,但实际上它的触发顺序优先级在__getattr__之前,当有相应类属性时,它会返回这个属性;而当对应类属性不存在的时候他会抛出一个异常AttributeError的,从而触发__getattr__的执行。
class Foo():
x = 10
def __getattr__(self,item):
print("执行getattr")
def __getattribute__(self,item):
print("执行getattr")
raise AttributeError('xxx')
f1 = Foo()
print(f1.y)
##执行结果
#执行getattribute
#执行getattr
#None
上面的程序片段模拟了执行getattribute的执行,无论是否能找到相应属性,都会先执行,抛出异常由getattr执行。
三、__setitem__,__getitem__,__delitem__
这三个函数在类的内部定义之后,可以让类属性的访问方式变成字典的访问的形式
class Foo():
def __setitem__(self,key,value):
print("执行属性赋值")
def __getitem__(self,item):
print("执行获取属性")
def __delitem__(self, item):
print("执行删除属性")
f1 = Foo()
f1["name"] = "hyj"
del f1["name"]
##执行结果
#执行属性赋值
#执行删除属性
四、__str__、__repr__、__format__
__str__
类里面关于将实例对象转换成字符串的内置函数,执行str(x)就是在执行x.__str__()方法,输出格式话%s也是在执行str方法
class Foo():
x = 10
def __str__(self):
return "这是str方法的函数"
f1 = Foo()
print(f1)
# 这是str方法的函数
__repr__
是在解释器中会用于将实例对象转换成字符串的内置函数,其中当str方法不存在的时候会默认执行repr方法__format__
这是类内置的实例对象格式化的函数
class Foo():
def __format__(self, format_spec):
return "这是format内置方法"
f1 = Foo()
print("{0} is".format(f1))
#这是format内置方法 is
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
def __format__(self, format_spec):
if not format_spec:
format_spec = date_type['y-m-d']
return format_spec.format(self)
date_type = {"y-m-d":"{0.year}-{0.month}-{0.day}",
"y.m.d":"{0.year}.{0.month}.{0.day}"
}
date1 = Date(2019,10,31)
print(format(date1))
#2019-10-31
五、__slots__
该内置方法主要是为了节省内存空间。我们知道当每一个实例生成的时候,都会生成一个属于自己的内存空间和__dict__字典。因此当生成大量的实例对象的时候就会造成大量的内存占用,而使用__slots__方法可以替代这个__dict__字典,将所有实例对象的属性保存在__slots__中,并且所有对象或者类都共用一个地址空间,并且没有定义在slots中的属性是无法创建的。
class Foo:
__slots__ = ['name','age']
f1 = Foo()
f1.name = 'hyj'
f2.job = 'rich'
print(f1.__slots__)
#['name', 'age']
#AttributeError: 'Foo' object has no attribute 'job'
#此时若打印__dict__则会报错
六、__doc__
这个方法用于保存类的文档信息,这个方法特殊之处在于它无法被继承。
六、__module__、__class__
__module__
这个内置方法可以打印出某个实例对象来自于哪个模块__class__
这个内置方法可以打印出某个实例对象来自于哪个类
七、__call__
在一个实例方法后面加一个(),可以直接执行类下面的__call__内置方法
class Foo:
def __call__(self, *args, **kwargs):
print("这是call方法")
f1 = Foo()
f1()
#这是call方法
八、__iter__、__next__
这是类中实现迭代器的两个方法,首先当实例实行iter()方法后将对象实例变成一个迭代器。
迭代器再调用next()方法,来返回一个值,而当next捕捉到StopIteration异常就会停止迭代。
class Foo:
def __init__(self,n):
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.n > 100:
raise StopIteration("停止了")
self.n += 1
return self.n
f1 = Foo(10)
for i in f1:
print(i)
# i = iter(f1)
# print(next(i))
九、__del__
这个方法又叫析构函数,这个函数是用于再删除实例对象或者当实例对象所有运行完毕的时候回收内存地址使用的,因此如果你希望在删除之前做一些收尾工作,比如关闭文件句柄,那就可以重写该方法。
十、__enter__,__exit__
这是用于上下文管理的两个内置方法,最常见的是with…as的使用方法中,当进入with的代码段时就会触发__enter__方法,结束的时候就会触发__exit__方法。
其中__exit__方法中,exc_type为错误的类型,exc_val为错误的值,exc_tb为错误追踪信息。当__exit__函数捕捉到一个异常的时候,就会结束程序的运行。
使用场景为:1、当with结束后完成一些清理工作 2、在网络编程中释放资源
class Foo:
def __enter__(self):
print("这是enter方法")
def __exit__(self, exc_type, exc_val, exc_tb):
print("这是exit方法")
print(exc_type)
print(exc_val)
print(exc_tb)
with Foo() as f:
print("---->")
print(f1.ssss)
print("结束")
###
这是enter方法
---->
这是exit方法
#exc_type
<class 'AttributeError'>
#exc_val
'NoneType' object has no attribute 'ssss'
#exc_tb
<traceback object at 0x103308808>
###出现异常最后 “结束”字样没有被打印
class Foo:
def __enter__(self):
print("这是enter方法")
def __exit__(self, exc_type, exc_val, exc_tb):
print("这是exit方法")
print(exc_type)
print(exc_val)
print(exc_tb)
return True #当exit返回真值,则异常则会被exit处理掉,程序继续往下执行
with Foo() as f:
print("---->")
print(f1.ssss)
print("结束")
###
这是enter方法
---->
这是exit方法
<class 'AttributeError'>
'NoneType' object has no attribute 'ssss'
<traceback object at 0x103b08808>
结束
十一、__new__方法
class A:
def __init__(self,x):
self.x = x
print("开始对象初始化")
def __new__(cls, *args, **kwargs):
print("产生一个实例对象")
return object.__new__(cls)
a = A(10)
#####
产生一个实例对象
开始对象初始化
new方法是类产生实例对象的方法,它会在init方法之前运行。往往使用在无法改写类的方法 如 int str等
class Capstr(str): #继承str类
def __new__(cls,string): #由于str类无法被改写,使用new重写
string = string.upper() #将传入字符大写
return str.__new__(cls,string) 返回改写的实例对象
单例模型
类每生成一个对象都会为对象分配一个内存地址,而如果我们希望每一个实例对象都是相同的内存地址,也就是说只生成一个实例对象的话,我们就要用new方法实现单例模型。
class A:
__instance = False #这表示类生成的时候,没有产生实例
def __init__(self,name):
self.name = name
def __new__(cls, *args, **kwargs):
if cls.__instance:
return cls.__instance
cls.__instance = object.__new__(cls)
return cls.__instance
a = A("1号")
b = A("2号")
print(a)
print(b)
########
<__main__.A object at 0x102f2c278>
<__main__.A object at 0x102f2c278>
十二、__eq__方法
因为每个类实例对象的内存地址是不同的,所以两个类实例对象就算其他属性都相同,那么也不是两个相等的对象,而eq就定义了 ,当某些属性相同的时候可以返回True值
class B:
def __init__(self,name):
self.name = name
def __eq__(self, other):
if self.name == other.name:
return True
e1 = B("jack")
e2 = B("jack")
print(e1==e2)
十三、__hash__方法
hash方法原本是按照类实例对象的内存地址进行hash,但是重写hash方法后,我们可以对指定属性来进行hash
class B:
def __init__(self,name,age):
self.name = name
self.age = age
def __hash__(self):
return hash(self.name+self.age)
十四、__len__方法
__len__方法是实现len()方法的内部函数,如果一个对象没有此内置方法,则无法计算长度
class B:
def __init__(self,name,age):
self.name = name
self.age = age
def __len__(self):
return 3
x1 = B("YJ",18)
print(len(x1))
#####
3