#1、__new__() // 实例化对象调用第一个方法并不是__init__而是__new__,一般Python默认调用, 一般只有在继承了不可变的类要去修改里面内容,需要重写 #eg: class CapStr(str): def __new__(cls, string): string = string.upper() return str.__new__(cls, string) #调用: cap = CapStr('aa') print(cap) # AA #2、__init__() // 构造方法不能有任何返回 #3、__del__() // 对象将要被销毁,会自动被调用,跟php中的_destroy ,垃圾回收机制,当所有对象引用都被删除,才会调用 #eg: class YO: def __init__(self): print('111') def __del__(self): print('22') #调用: yo = YO() yo1 = yo del yo # 此时不会调用__del__ del yo1 # 两个都删掉才会调用__del__ #22 #4、算数运算 #4.1正向运算 class New_int(int): def __add__(self, other): return int.__sub__(self, other) def __sub__(self, other): return int.__add__(self, other) a = New_int(2) b = New_int(3) print(a + b) # -1 print(a - b) # 5 #4.2逆向运算 class New_int(int): def __radd__(self, other): return int.__sub__(self, other) a = 3 b = New_int(2) print(a + b) # -1,因为3不是New_int,找不到,就会执行b的逆向运算radd,self是b,other是a #5、__setattr__()、__getattr() #__、__getattribute() #__、__delattr__() #__setattr__():对象给属性赋值会调用此方法 #__getattribute__():读取对象属性调用此方法(不管属性是否存在都会调用) #__getattr__():对象属性不存在才会调用,此方法在__getattribute__()之后调用 #__delattr__():删除一个对象的属性,调用此方法 class MyTime: def __setattr__(self, name, val): print('setattr') return super().__setattr__(name, val) def __getattribute__(self, name): print('getattribute') return super().__getattribute__(name) def __getattr__(self, name): print('getattr') def __delattr__(self, name): print('delattr') return super().__delattr__(name) m = MyTime() print(m.a) m.a = 2 print(m.a) del m.a #6、描述符__get__ 、__set__、__delete__ #6.1实例一: class MyProperty: def __init__(self, fget=None, fset=None, fdel=None): self.fget = fget self.fset = fset self.fdel = fdel def __set__(self, instance, val): self.fset(instance, val) def __get__(self, instance, owener): return self.fget(instance) def __delete__(self, instance): self.fdel(instance) class C: def __init__(self): self._x = 0 def getContent(self): return self._x def setContent(self, val): self._x = val def delContent(self): del self._x x = MyProperty(getContent, setContent, delContent) c = C() print(c.x) c.x = 11 print(c.x) #6.2实例二: class A: def __init__(self, value=0): self.value = value def __set__(self, instance, val): self.value = val def __get__(self, instance, owener): return self.value class B: def __init__(self, value=0): self.value = value def __set__(self, instance, val): instance.a = val + 1 def __get__(self, instance, owener): return instance.a class C: a = A() b = B() c = C() print(c.a) c.a = 11 print(c.a) c.b = 10 print(c.a) print(c.b) #7、定制序列 class Test: def __init__(self, *args): self.values = [x for x in args] self.count = {}.fromkeys(range(len(self.values)), 0) def __len__(self): return len(self.count) def __getitem__(self, key): self.count[key] += 1 return self.values[key] t = Test(1, 2, 3, 4, 5, 6) print(t[1]) print(t[2]) print(t[1]) print(t.count) #8 类属性与实例属性:实例对象属性优先级高于类对象属性,当类对象与实例对象属性相同的时候,通过对象调用该属性会优先调用对象中的,如果对象中没有此属性才会调用类中的属性 class Test(): count = 0 t1 = Test() t1.count = 10 t2 = Test() t3 =Test() print(t1.count,t2.count,t3.count)#10 0 0 del t1.count print(t1.count,t2.count,t3.count)#0 0 0 #9 正常情况下可以给该实例、类绑定任何属性和方法,但是可以使用__slots__限制只允许绑定哪些属性、方法 from types import MethodType class Test(): pass t = Test() #9.1给实例绑定属性 t.name = '张三' print(t.name) #张三 #9.2给实例绑定方法,【注】:给一个实例绑定方法,其他实例无法使用,但是给类绑定方法所有实例都可以使用 from types import MethodType def setAge(self, age): self.age = age class Test(): pass t = Test() t.setAge = MethodType(setAge,t) t.setAge(12) print(t.age) #12 #9.3给类绑定方法 from types import MethodType def setAge(self, age): self.age = age class Test(): pass Test.setAge = MethodType(setAge, Test) t = Test() t.setAge(12) print(t.age) #12 #9.4 使用__slots__限制允许绑定的属性与方法 class Test(): __slots__ = ('age','name') t = Test() t.age=12 print(t.age) t.name = '张三' print(t.name) t.score = 21 #__slots__限制只能绑定age、name,当绑定score时就报错了,__slots__仅仅对当前类起作用,对子类不起作用 #10 @property、@方法.setter,将方法变为外部可以调用属性 class Test(): @property # 将get方法变为属性访问 def name(self): return self.__name @name.setter # 将set方法变为实行设值 def name(self, name): if(len(name) > 4): raise ValueError('超出字符长度') self.__name = name t = Test() t.name = '张三' print(t.name)#张三 #11 mixin设计混合,通过多继承特性实现类似java接口多个功能混合作用的一种设计,java、php这种单继承无法实现mixin,但可以类似Interface class A(BMixin,CMixin): #这样A就有了BMixin、CMixin相关功能,避免单一继承 pass; #12 定制类 #12.1 __slots__限制绑定属性、方法,__len__(),当调用len(obj)会触发obj.__len()__,除了这两个还有很多定制方法 class Student(): def __init__(self,name): self.name='张三' def __str__(self): return 'Student object(name:%s)' % self.name __repr__ = __str__ #最懒得方法,不需要在重新定义一次 #12.2、__str__ print(Student('张三')) #Student object(name:张三),触发__str__方法 #2、__repr__ s = Student('张三') s #交互模式下直接输入,不是出发__str__,而是出发__repr__() #12.3、__iter__ class Fib(object): def __init__(self): self.a,self.b = 0,1 def __iter__(self): return self #实例本身就是迭代对象,故返回自己 def __next__(self): self.a,self.b = self.b,self.a+self.b if self.a > 100000: raise StopIteration return self.a #下一个返回值 #调用: for n in Fib(): print(n) #1 1 2 3 5... #__iter__()方法返回一个迭代对象,然后python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到StopIterration停止 #12.4、__getitem__,虽然Fib()能循环想list一样,但不能像list一样用下标输出数据,如:Fib()[2],想要下表取出数据,就要有__getitem__ class Fib(): def __getitem__(self, item): a,b = 1,1 for x in range(n): a,b = b,a+b return a f = Fib() print(f[0]) #1 print(f[2]) #2 #但是list有切片list(range(1,100)[5:30]),对于Fib()却报错。原因是__getitem__()传入的参数可能是一个int,也可能是一个切片对象slice,所以要判断: class Fib(object): def __getitem__(self, item): if isinstance(item,int): a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(item,slice): start = item.start stop = item.stop if start is None: start = 0 a,b = 1,1 L = [] for x in range(stop): if x >= start: L.append(a) a,b = b,a+b return L f = Fib() print(f[0:5]) #但是还没有对step步长做处理,还有__setitem__()、__delitem__()与之对应设置、删除,后续自己补充 #12.5、__getattr__:正常情况下调用类的方法或者属性,不存在就报错,当调用不存在的属性时,python解释器会试图调用__getattr__ class Student(object): def __init__(self): self.name = 'Michael' def __getattr__(self, attr): if attr == 'score': return 99 else: raise AttributeError('%s属性不存在' % attr) s = Student() print(s.name) #Michael print(s.age) #属性不存在 #12.6、__call__():直接对实例进行调用 class Student(object): def __init__(self,name): self.name = name def __call__(self): print('My name is %s.' % self.name) #调用: s = Student('Michael') s() #My name is Michael.