一、构造和析构
1.构造方法,类在实例化对象的时候首先调用的方法。
__init__(self[,....])
一般传参的时候在__init__里创建,__init__只能返回None,不能返回其他
class A: def __init__(self, x, y): self.x = x self.y = y
2.对象实例化时调用的第一个方法
__new__(cls[, ....])
如果这里有参数,会原封不动的传给init方法。需要一个实例对象作为返回值。
当继承不可变类型的时候,而又需要修改的时候调用它
class CapStr(str): def __new__(cls, string): string = string.upper() return str.__new__(cls, string) a = CapStr("I love you.") print(a) >>> I LOVE YOU.
因为str是不可改变的类型,不能在__init__ 里面对它自身进行修改。所以要在子类的__new__里面替换,并且传给str的__new__
3.析构方法
__del__(self)
当所有的调用都销毁的时候,才会调用__del__方法。如果多处引用,只删除其中几个__del__不会被调用。
二、 算术运算魔法方法
__add__(self, other) |
定义加法的行为:+ |
__sub__(self, other) | 定义减法的行为:- |
__mul__(self, other) | 定义乘法的行为:* |
__truediv__(self, other) | 定义真除法的行为:/ |
__floordiv__(self, other) | 定义整除法的行为:// |
__mod__(self, other) | 定义取模算法的行为:% |
__divmod__(self, other) | 定义当被divmod()调用时的行为,返回商和余数 |
__pow__(self, other[, modulo]) | 定义当被power()调用或**运算时的行为 |
__lshift__(self, other) | 定义按位左移位的行为 :<< |
__rshift__(self, other) | 定义按位右移位的行为:>> |
__and__(self, other) | 定义按位与操作的行为:& |
__xor__(self, other) | 定义按位异或操作的行为: ^ |
__or__(self, other) | 定义按位或操作的行为: | |
class NewInt(int): def __add__(self, other): return int.__sub__(self, other)
如上所示,一般是对int的方法进行修改,可以将一个NewInt的数字实例的加法改成减法。
还有反运算(当前面的元素没有加方法的时候,后面对前面执行加法__radd__)以及增量运算(__iadd__),一元操作符(__neg__, __pos__, __abs__, __invert__),类型转换(__complex__,__int__,__float__,__round__等)
用到的时候再查一下。
三、字符串打印相关魔法方法
class A: def __repr__(self): return '我是谁' a = A() >>> a 我是谁 class B: def __str__(self): return '我只有在print的时候打印' b = B() >>>b 内存地址+名字 >>>print(b) 我只有在print的时候打印
四、属性访问
class C: def __init__(self): self.x = 'X-man' c = C() print(c.x) result = getattr(c, 'x', '没有这个属性') print(result)
以上是2种常见的访问类属性的方法,getattr可以指定没有属性的时候的默认返回值
class C: def __init__(self, size=10): self.size = size def get_size(self): return self.size def set_size(self, value): self.size = value def del_size(self): del self.size x = property(get_size, set_size, del_size) c = C() c.x = 20 print(c.x) print(c.size) del c.x print(c.size)
>>>20 >>>20 Traceback (most recent call last): File "C:/Users/wqk/Desktop/OnlinePay/Pay/test_2.py", line 22, in <module> print(c.size) AttributeError: 'C' object has no attribute 'size'
以上是用property方法的get, set, del来便捷管理size属性
property类似的魔法方法:
class A: # 定义当用户试图获取一个不存在的属性时的行为 def __getattr__(self, item): pass # 定义当该类的属性被访问时的行为 def __getattribute__(self, item): pass # 定义当一个属性被设置时的行为 def __setattr__(self, key, value): pass # 定义当一个属性被删除时的行为 def __delattr__(self, item): pass
例子:
class C: # 定义当用户试图获取一个不存在的属性时的行为 def __getattr__(self, item): print("getattr") # 定义当该类的属性被访问时的行为 def __getattribute__(self, item): print('getattribute') return super().__getattribute__(item) # 定义当一个属性被设置时的行为 def __setattr__(self, key, value): print('setattr') super().__setattr__(key,value) # 定义当一个属性被删除时的行为 def __delattr__(self, item): print('delattr') super().__delattr__(item) if __name__ == '__main__': c = C() c.x >>>getattribute -getattr c.x = 1 >>>setattr c.x >>>1 -getattribute del c.x >>>delattr
为了避免死循环, 在设置和获得属性的时候一般用super().__setattr__(name,value)去获得,
或者使用 self.__dict__[name] = value 进行设置
五、描述符
描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
class MyDescriptor: def __get__(self, instance, owner): print("getting", self, instance, owner) def __set__(self, instance, value): print("setting", self, instance, value) def __delete__(self, instance): print("deleting", self, instance) class Test: x = MyDescriptor() test = Test() test.x >>> getting <__main__.MyDescriptor object at 0x0000023CD493B898> <__main__.Test object at 0x0000023CD493B860> <class '__main__.Test'> print(test) >>> <__main__.Test object at 0x0000023CD493B860> test.x = "X-man" >>> setting <__main__.MyDescriptor object at 0x0000023CD493B898> <__main__.Test object at 0x0000023CD493B860> X-man del test.x >>> deleting <__main__.MyDescriptor object at 0x0000023CD493B898> <__main__.Test object at 0x0000023CD493B860>
通过这里的__get__, __set__, __delete__我们可以自己编辑自己的property! 下面就是代码:
class MyProperty: def __init__(self, fget=None, fset=None, fdel=None): self.fget = fget self.fset = fset self.fdel = fdel def __get__(self, instance, owner): return self.fget(instance) def __set__(self, instance, value): return self.fset(instance, value) def __delete__(self, instance): print('deleting...') return self.fdel(instance) class C: def __init__(self): self._x = None def getX(self): return self._x def setX(self, value): self._x = value def delX(self): del self._x x = MyProperty(getX, setX, delX) if __name__ == '__main__': c = C() print(c.x) c.x = 'X-man' print(c.x) print(c._x) del c.x # print(c._x)
练习:
一个温度类,定义两个描述符类用于描述摄氏度和华氏度, 华氏度= 摄氏度*1.8+32 2. 两个属性会自动转换,给其中一个赋值 打印另一个会显示自动转换后的结果