一. 内置方法
1.__call__
class Da(object): def __init__(self,a1,a2): self.a1=a1 self.a2=a2 def cc(self): print("我是啊哈哈哈") def __call__(self, *args, **kwargs): print(self.a1) print(self.a2) print(args) print(kwargs) print("对象自动执行!!!!!!!!!!!!!!!!!!!1")obj=Da(11,22)print(obj.a1)print(obj.a2)print("**********************************************8")# 这是使用__call__ 方法 对象传参数自动执行obj(1,2,3,name="张三",age=555)
# 11 # 22 # **********************************************8 # 11 # 22 # (1, 2, 3) # {'name': '张三', 'age': 555} # 对象自动执行!!!!!!!!!!!!!!!!!!!1
2. __getitme__
class Da(object): def __init__(self, a1, a2): self.a1 = a1 self.a2 = a2 @property def cc(self): print("我是啊哈哈哈") def __getitem__(self, item): # print(item) print(self.a1) self.cc return item # return self.__dict__[itme] obj = Da(11, 22) aa = obj["k1"] print(aa) # k1 print("*********************************") bb = obj["name", "哈哈哈", "66666"] print(bb) # ('name', '哈哈哈', '66666') # 11 # 我是啊哈哈哈 # k1 # ********************************* # 11 # 我是啊哈哈哈 # ('name', '哈哈哈', '66666')
3.__setitem__
# __setitem__class Da(object): def __init__(self, a1, a2): self.a1 = a1 self.a2 = a2 def cc(self): print("我是啊哈哈哈") def __setitem__(self, key, value): print(key,value) print(self.a1) self.cc() # self.__dict__[key]=valueobj = Da(11, 22)obj.cc()print("***********************")aa=obj["k1"]=588888# 我是啊哈哈哈# ***********************# k1 588888# 11# 我是啊哈哈哈
4.__delitme__
# __delitme__class Da(object): def __init__(self, a1, a2): self.a1 = a1 self.a2 = a2 def cc(self): print("我是啊哈哈哈") def __delitem__(self, key): print(key) # del self.__dict__[key]obj = Da(11, 22)obj.cc()print("*****************************************")del obj["lover"]print(obj.__dict__)# 我是啊哈哈哈# *****************************************# lover# {'a1': 11, 'a2': 22}
5.__iter__
# __iter__class Da(object): def __init__(self, a1, a2): self.a1 = a1 self.a2 = a2 def cc(self): print("我是啊哈哈哈") def __iter__(self): # return iter([11,22,333]) yield 1 yield 22a=Da(1,2)for i in a: print(i)# 如果 要把不可迭代对象 -》可迭代对象# 在类中定义 __iter__方法# iter 内部返回一个迭代器 生成器也是迭代器的一种 所以生成器也可以# 1# 22
6 . __getattr__
class Da(object): num=666 def __init__(self,name): self.name=name def aa(self): print(f'我的名字叫---{self.name}') def __getattr__(self, item): # print("我是") print(item)cc=Da("张无忌")cc.age #调用了一个不存的属性 才会触发 __getattr___cc.bb# age# bb
class Test(object): def __init__(self, name): self.name = name def __getattr__(self, value): if value == 'address': return 'China' test = Test('美国') print(test.name) print(test.address) test.address = '北京' print(test.address) # 美国 # China # 北京
# __getattribute__ 查找属性无论是否存在,都会执行 class Da(object): def __init__(self,age): self.age=age def __getattribute__(self, item): print(item,"嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡") print("********************") # print(self.age) aa=Da(55) aa.bbbbbbbb print(aa.age)
class Test(object): def __init__(self, name): self.name = name def __getattribute__(self, value): if value == 'address': return 'China' test = Test('上海') print(test.name) print(test.address) test.address = '北京' print(test.address) # None # China # China
7. __setattr__
class Da(object): num=666 def __init__(self,name): self.name=name def aa(self): print(f'我的名字叫---{self.name}') def __setattr__(self, key, value): self.__dict__[key] = value print(key,value)cc=Da("张无忌") # __setattr__ 设置属性时会促发 __setattr__cc.age=18cc.hod="篮球"print(cc.__dict__)# name 张无忌# age 18# hod 篮球# {'name': '张无忌', 'age': 18, 'hod': '篮球'}
8.__delattr__
# __delattr__ 删除一个会促发这个方法class Fa(object): def __init__(self, name): self.name = name def __setattr__(self, key, value): if type(value) is str: print("执行__setattr__方法", key, value) self.__dict__[key] = value else: print("必须是字符串") def __delattr__(self, item): print("执行 __delattr__ 方法", item)a4 = Fa("张三")a4.age = "25岁"a4.sex = "男"a4.shenggao = 188 # type 是数字就添加不进去print(a4.__dict__)del a4.name # __delattr__ 删除一个会促发这个方法"""执行__setattr__方法 name 张三执行__setattr__方法 age 25岁执行__setattr__方法 sex 男必须是字符串{'name': '张三', 'age': '25岁', 'sex': '男'}执行 __delattr__ 方法 name"""
9. __new__ __init__
class Da(object): def __init__(self, a1, a2): self.a1 = a1 self.a2 = a2 def cc(self): print("我是啊哈哈哈") def __new__(cls, *args, **kwargs): print(1)obj = Da(11, 22)# print(obj.a1) 执行不到# 1print("************************************************************************************88")# 注意 在类中 使用__init__初始化函数前 是自动默认会执行__new__构造方法# 虽然我们不用添加__new__ 但是我们要知道 在使用 __init__初始化 前 python 内部就自动调用了 __new__构造方法class Da(object): def __init__(self, a1, a2): print("这里是初始化") self.a1 = a1 self.a2 = a2 def cc(self): print("我是啊哈哈哈") def __new__(cls, *args, **kwargs): print("这里是构造方法") print(cls) return object.__new__(cls) # 构造方法必须返回 object.__new__(cls) 才能执行__init__初始化对象obj = Da(11, 22)print(obj.a1)# 这里是构造方法## 这里是初始化# 11
# __new__ 的作用
# # 1、__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。# # 假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。### # 3、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))# # __new__出来的实例,或者直接是object的__new__出来的实例## # 4、__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值10 . __add__
# __add__# 对象可以相加 加减 乘 除class Da(object): def __init__(self, a1, a2): self.a1 = a1 self.a2 = a2 def cc(self): print("我是啊哈哈哈") def __add__(self, other): return self.a1+other.a1a=Da(1,2)b=Da(100,20)print(a+b)# 101
11. __del__
# 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作# (例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。# 析构函数 :__del__()释放对象自动调用class person(object): def run(self): print("run") def __init__(self, name, age, height, weight): self.name = name self.age = age self.height = height self.weight = weight def __del__(self): print("这里是析构函数") per = person("张三", 25, 300, 100)# 释放对象 就相当于删除了 就不能访问了 这是手动释放del per# 在函数里定义的对象会在函数结束时自动释放(删除) 可以减少内存浪费空间def fun(): per2 = person("李四", 1000, 2000, 30000) print(per2.name)fun() #这里是析构函数
# 李四 # 这里是析构函数
# __del__也称之为析构方法 # # __del__会在对象被删除之前自动触发 class People: def __init__(self, name, age): self.name = name self.age = age self.f = open('test.txt', 'w', encoding='utf-8') def __del__(self): print('run======>') # 做回收系统资源相关的事情 self.f.close() obj = People('egon', 18) del obj # del obj会间接删除f的内存占用,但是还需要自定制__del__删除文件的系统占用 print('主') # run======> # 主
13. __len__
# __len__ 和 len配合使用class Students(object): def __init__(self, *args): self.names = args def __len__(self): return len(self.names)aa=Students("111",222)print(aa)print(len(aa))# 2
14. __str__
# __str__()函数的作用:# 不知道大家再写程序是,打印一个实例化对象时,打印的其实时一个对象的地址。而通过__str__()函数就可以帮助我们打印对象中具体的属性值,或者你想得到的东西。## 因为再python中调用print()打印实例化对象时会调用__str__()如果__str__()中有返回class ss: def __init__(self,age,name): self.age = age self.name = name def __str__(self): return str(self.age)+",,wozenmezhemeshuai,,"+self.names = ss(21,'aitebao')print(s)# 21,,wozenmezhemeshuai,,aitebao
15. __hash__
# __hash__ hash() 用于获取取一个对象(字符串或者数值等)的哈希值。class F(object): def __init__(self,name,sex): self.name=name self.sex=sex def __hash__(self): return hash(self.name+ self.sex)a=F("张三","男")b=F("张三","1111")print(hash(a))print(hash(b))
16.__eq__
# 如果不实现__eq__方法,那么自定义类型会调用默认的__eq__方法, 通过默认方法进行比较的相等条件相当严格,只有自己和自己比才会返回True,表现如下# __eq__# class B(object):# def __int__(self,name):# self.name=name# def __eq__(self,other):# if self.name==other.name:# return True# c1=B("张三")# c2=B("李四")class Item: def __init__(self, name): self. name= name def __eq__(self, other): if self. name== other. name: return True else: return Falsefirst = Item('hello')second = Item('hello')print(first == second) # True
17.__slots__
__slots__是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
-
字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
-
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
class Foo: __slots__='x'f1=Foo()f1.x=1f1.y=2#报错print(f1.__slots__) #f1不再有__dict__class Bar: __slots__=['x','y'] n=Bar()n.x,n.y=1,2n.z=3#报错
# __slots__ 省内存class Person(object): # 意思__slots__ 里面定义的属性 在实例化对象赋值时 只能使用里面定义好了的字段 不然会报错 这样会省内存 __slots__ = ("name", "age", "speak")per = Person()per.name="哈哈哈哈"per.age=666per.speak=4444444# 意思就是只能添加__slots__里面定义的属性#per.aa=6666 #会报错因为__slotl__里面没有定义# 使用__slots__时 __dict__ 也不能用print(per.__slots__)print(Person.__slots__)print("*************************************************************************8")class Foo: __slots__=['name','age']f1=Foo()f1.name='alex'f1.age=18print(f1.__slots__)# ['name', 'age']f2=Foo()f2.name='egon'f2.age=19print(f2.__slots__)# ['name', 'age']# f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存print(Foo.__dict__)# {'__module__': '__main__', '__slots__': ['name', 'age'], 'age':, 'name': , '__doc__': None}
from types import MethodType# 创建一空类class Person(object): # 想添加什么属性就写在里面 __slots__ = ("name", "age", "speak")per = Person()per.name = "张师傅"print(per.name)# 动态的添加方法 必须引入一个模块def say(self): print("动态的添加方法" + self.name) print("啊哈哈哈哈哈哈哈")per.speak = MethodType(say, per)per.speak()"""思考: 如果我们想要 限制实例的属性怎么办比如 只允许给对象添加name age height 特定的属性解解方法: 定义类的时候 定义一个特殊的属性 (__slots__)可以限制动态属性的添加 """per.age = 222222print(per.age)# 张师傅# 动态的添加方法张师傅# 啊哈哈哈哈哈哈哈# 222222
from types import MethodType# 创建一空类class Person(object): passper = Person()per.name = "张师傅"print(per.name)# 动态的添加方法 必须引入一个模块def say(self): print("动态的添加方法" + self.name)per.speak = MethodType(say, per)per.speak()# 张师傅# 动态的添加方法张师傅print(per.__dict__)# 张师傅# 动态的添加方法张师傅# {'name': '张师傅', 'speak':>}
18 __doc__返回类的注释信息
class Foo: '我是描述信息' passprint(Foo.__doc__)# 我是描述信息print("**********************************************")# 该属性无法继承给子类class Foo: '我是描述信息' passclass Bar(Foo): passprint(Bar.__doc__) #该属性无法继承给子类# None
19 .__class__ __module__