zoukankan      html  css  js  c++  java
  • 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. 两个属性会自动转换,给其中一个赋值  打印另一个会显示自动转换后的结果

  • 相关阅读:
    广播BroadcastReceiver(2)
    hunnu11544:小明的烦恼——找字符串
    Systemd启动图形界面过程
    大数据.......
    2014百度之星第一题Energy Conversion
    基于zookeeper简单实现分布式锁
    LeetCode OJ 215. Kth Largest Element in an Array 堆排序求解
    Leetcode
    Linux文件系统(七)---系统调用之open操作(一)
    Go语言Slice操作.
  • 原文地址:https://www.cnblogs.com/djflask/p/12258310.html
Copyright © 2011-2022 走看看