文章目录
- 一、模块调用中attr类函数的运用
- 1、执行模块以外的模块调用
- 2、执行模块调用自己
- 二、\_\_getattribute__()方法的运行逻辑
- 三、item系列方法
- 四、\_\_str__()方法
- 五、\_\_repr__()方法
- 六、自定制格式化方法
- 七、__slots__属性
- 八、\_\_doc__属性
- 九、__module__和__class\_\_
- 十、析构方法
- 十一、\_\_call__()方法
- 十二、迭代器协议的进一步理解
一、模块调用中attr类函数的运用
1、执行模块以外的模块调用
import test as t # test模块中有Pr函数print(hasattr(t,"Pr")) # True
print(hasattr(t,"Pr1")) # False
2、执行模块调用自己
x = 10import sys
obj = sys.modules[__name__]
print(getattr(obj,"x")) # 10
二、__getattribute__()方法的运行逻辑
系统自己写的__getattribute__()方法运行逻辑:实例化时,先运行__getattribute__()方法。__getattribute__()方法会去查询实例和类的属性字典,如果字典中有对应的key,则返回value。如果属性字典中没有key,则会raise AttributeError,然后运行__getattr__()。
如果代码中重写了__getattribute__()方法,实例化时,则会运行重写的__getattribute__()方法,不去运行系统写的。
class Foo:x = 10def __init__(self,y):self.y = ydef __getattr__(self, item):print("运行__getattr__",item)def __getattribute__(self, item):print("__getattribute__", item)raise AttributeError("no has attr!")f1 = Foo(5)
f1.y
'''
__getattribute__ x
运行__getattr__ x
'''
三、item系列方法
class Foo:def __getitem__(self, item):print("getitem!")return self.__dict__[item]def __setitem__(self, key, value):print("setitem!")self.__dict__[key] = valuedef __delitem__(self, key):print("delitem!")self.__dict__.pop(key)f1 = Foo()f1["age"] = 18 # setitem!
print(f1.__dict__) # {'age': 18}print(f1["age"])
'''
getitem!
18
'''
del f1["age"] # delitem!
print(f1.__dict__) # {}
四、__str__()方法
print对象,实际是调用str()函数,进而调用其类的__str__()方法。
如果不重写__str__()方法,则用系统自己写的。
class Foo:def __init__(self):passdef __str__(self):return "output me!"f1 = Foo()
print(f1) # output me!
print(str(f1)) # output me!
print(f1.__str__()) # output me!
五、__repr__()方法
在交互式解释器中执行代码,会触发repr()函数,调用__repr__()方法。
在非交互式时执行代码,会先去执行__strr__()方法,没有的话,再去执行__repr__()方法。
同样,如果不改写__repr__()方法,则会执行系统自己写的。
此外,__str__()方法和__str__()方法返回的数据类型必须是字符串
交互式:
非交互式:
class Foo:def __init__(self):pass# def __str__(self):# return "output str!"def __repr__(self):return "output repr!"f1 = Foo()
print(f1) # output repr!
六、自定制格式化方法
format()函数实际上就是调用 对象.__format__()
format_dic = {"ymd": "{0.year}{0.month}{0.day}","y-m-d": "{0.year}-{0.month}-{0.day}","y:m:d": "{0.year}:{0.month}:{0.day}"
}
class Date:def __init__(self,year,month,day):self.year = yearself.month = monthself.day = daydef __format__(self, format_spec):if not format_spec or format_spec not in format_dic:format_spec = "ymd"fm = format_dic[format_spec]return fm.format(self)d1 = Date(2024,2,24)print(format(d1)) # 2024224
print(format(d1,"y:m:d")) # 2024:2:24
七、__slots__属性
__slots__是一个类变量,变量值是列表、元组,也可以是字符串等。
作用:字典会占用大量内存,如果有个属性很少的类,但是有很多实例,可以使用__slots__来减少内存开销。
类中定义了__slots__后,其对应的实例则不会有__dict__属性。
class Foo:__slots__ = ["name","age"] # 实例只能定义name和age属性f1 = Foo()
f1.name = "CRTao"
f1.age = 18print(f1.name,f1.age) # CRTao 18
f2 = Foo()
f2.age = 10
print(f1.age ,f2.age) # 18 10
八、__doc__属性
文档描述信息。不能被子类继承。
class Parent():"我是父类"passclass Child(Parent):passprint(Parent.__doc__) # 我是父类
print(Child.__doc__) # None
九、__module__和__class__
from test import Foof1 = Foo()
print(f1.__module__) # test 显示其类所在模块名
print(f1.__class__) # <class 'test.Foo'> 显示类名'''test.py代码
class Foo:pass
'''
十、析构方法
del 实例 会触发 实例.__del__()
程序运行完毕会自动回收内存,也会触发__del__
class Foo:def __init__(self,name):self.name = namedef __del__(self):print("执行del")f1 = Foo("CRTao")del f1.name # 不会触发__del__方法
print("exc me!")'''
exc me!
执行del
'''
注:在 Python 中,当对象被删除时,解释器会调用对象的 del 方法,但是 del 方法并不负责删除对象,它只是在对象即将被销毁时执行一些清理工作。对象的实际删除是由 Python 的垃圾回收机制完成的,它会在对象没有任何引用时将其从内存中删除。
十一、__call__()方法
对象() 触发执行。
class Foo:def __call__(self, *args, **kwargs):print("实例执行!")f1 = Foo()
f1() # 实例执行! 触发f1的类下的__call__()方法
一切皆对象,类本质也可以看成对象,而Foo()可以理解为是触发Foo的类(创造类Foo的类)下的__call__()方法。
十二、迭代器协议的进一步理解
class Foo:def __init__(self,n):self.n = ndef __iter__(self):return selfdef __next__(self):if self.n > 20:raise StopIteration('终止了')self.n += 1return self.nf1 = Foo(5)for i in f1: # 先obj=f1.__iter__(),再i=obj.__next__()print(i)