python魔法方法

一、构造和析构

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)
View MyProperty Code

 练习:

一个温度类,定义两个描述符类用于描述摄氏度和华氏度, 华氏度= 摄氏度*1.8+32    2. 两个属性会自动转换,给其中一个赋值  打印另一个会显示自动转换后的结果

 

posted @ 2020-02-04 07:51  gavincc  阅读(168)  评论(0编辑  收藏  举报