【Python】 类特殊成员,属性和方法

类的专有方法:

  • __init__ : 构造函数,在生成对象时调用

    • 每当创建一个类的实例对象时,Python 解释器都会自动调用构造方法__init__,且 __init__不允许有返回值
      # self 参数,每个类对象只能调用自己的类变量和类方法
      class eg(object):
          # 构造函数中的 self 参数,其代表的是当前正在初始化的类对象
         def __init__(self):
              print("pass")
              pass
      
      if __name__ == "__main__":
          # 创建e 对象
          e = eg()  
      pass
      
      进程已结束,退出代码0
      __init__(self,a,b) 存在多个参数
      # 创建对象时会调用类的构造方法,如果构造函数有多个参数时,需要手动传递参数
      class eg(object):
          # 类属性就相当与全局变量,实例对象共有的属性
          name = 'testname'
          # 类属性 私有
          __age = 12
          # 类的构造方法,最少有一个self参数,可以包含多个参数
          def __init__(self,a,b):
              # 传递的参数
              self.a = a
              # 传递的参数
              self.b = b
              # 定义的参数,可以同类中self.c 调用
              self.c = 15
              # 实例对象的属性为实例对象自己 私有
              d = 2
              print("构造方法中 计算:a + b = " + str(self.a + self.b) ," c * d = "+ str(self.c * d))
              pass
      
          # 定义实例方法
          def aa(self):
              print("实例方法 fun(aa) >>> c = ",self.c)
              print("实例方法 fun(aa) >>> b = ",self.b)
      
      if __name__ == "__main__":
          # 创建实例对象
          e = eg(5,3)
      
          # 第一种 直接调用类方法 实例化调用函数
          print("直接调用类方法")
          e.aa()
          # 第二种 函数调用
          print("函数调用")
          ea = e.aa
          ea()
          
          print("类属性name返回 :",e.name)   #调用对象中的类属性
          print("类方法中的参数 :",e.a) # 调用e中的参数值
          
          e.name = "enametest update"
          print("实例属性会屏蔽同名的类属性" ,e.name)
      
          # 删除实例属性
          del e.name
          print("实例属性被删除后,再调用同名称的属性,会调用类属性" ,e.name)
      构造方法中 计算:a + b = 8 c * d = 30
      直接调用类方法
      实例方法 fun(aa) >>> c = 15
      实例方法 fun(aa) >>> b = 3
      函数调用
      实例方法 fun(aa) >>> c = 15
      实例方法 fun(aa) >>> b = 3
      
      类属性name返回 : testname
      类方法中的参数 : 5
        实例属性会屏蔽同名的类属性 enametest update
        实例属性被删除后,再调用同名称的属性,会调用类属性 testname
      
      进程已结束,退出代码0
    • 注意@staticmethod 可以声明一个静态方法,不强制要求传递参数(self);@classmethod 装饰器 也不需要self参数,但第一个参数需要是表示自身类的cls参数

      class funa():
          def __init__(self):
              pass
          # 正常函数
          def oro(self):
              print("oro")
      
          @staticmethod   # self表示一个类的实例对象本身。如果用了staticmethod就无视这个self了,就将这个方法当成一个普通的函数使用了
          def ara():
              v = 12
              print("method ara")
      
          @classmethod    # cls表示这个类本身,可以来调用 类的属性,类的方法,实例化对象等
          def brb(cls):
              print("method brb",cls)
              cls.ara()   # 静态调用
              cls().oro() # 实例化调用
      
      o = funa() # 常用的调用方法
      o.oro() # 实例化调用
      
      funa.ara()  # 无需实例化静态调用
      funa.brb()  # 无需实例化静态调用
      
      print(funa)
      
      # 》》》执行结果
      # oro
      # method ara
      # method brb <class '__main__.funa'>
      # method ara
      # oro
      # <class '__main__.funa'>

 

  • __new__: 是一种负责创建类实例的静态方法

    • __new__() 是一种负责创建类实例的静态方法,它无需使用 staticmethod 装饰器修饰,且该方法会优先 __init__() 初始化方法被调用

      class run_case:
          """临时验证脚本"""
      
          def __new__(cls, name, age):
              """覆写 __new__() 的实现将会使用合适的参数调用其超类的 super().__new__(),并在返回之前修改实例"""
      
              print("__new__")
              return super(run_case, cls).__new__(cls)
      
          def __init__(self, name, age):
              print("__init__")
              self.name = name
              self.age = age
      
      
      if __name__ == "__main__":
          t = run_case("1", "2")
          print(t)

       执行结果

      __new__
      __init__
      <__main__.run_case object at 0x057A59E8>
      
      进程已结束,退出代码为 0
    • super  调用父类的方法

      # 单继承,主要是用来调用父类的方法# 父类Aclass A:
          def __init__(self):
              self.n = 5  # A类 n=5
          def sum(self, m):
              print('self is {0} @A.sum'.format(self))    # A类sum方法
              self.n += m
      
      # B类 单继承 A类
      class B(A):
          def __init__(self):
              self.n = 10 # B类n=10
      
          def add(self, m):
              print('self is {0} @B.add'.format(self))  # B类add方法
              super().sum(m)  # 调用父类A的方法 sum n=n+m
              self.n += 2 # 不调用父类A sum n = n+2
      
      if __name__ == "__main__":
      
          a = A()
          b = B()
          b.add(10)
          print("B 类调用方法add(add调用父类A的sum) n = ",b.n)  # B 类调用方法add(add调用父类A的sum) n =  22
          print("获取 A 类 n值 ",a.n)
      
          a.sum(10)
          print("A 类调用方法sum , n = ",a.n)  # A 类调用方法sum , n =  15
      self is <__main__.B object at 0x04AC0028> @B.add
      self is <__main__.B object at 0x04AC0028> @A.sum
      B 类调用方法add(add调用父类A的sum) n =  22
      获取 A 类 n值  5
      self is <__main__.A object at 0x04A34F58> @A.sum
      A 类调用方法sum , n =  15
      
      进程已结束,退出代码0
      # 多继承
      # 父类A
      class A:
          def __init__(self):
              self.n = 1  # A类 n=5
          def sum(self, m):
              print('self is {0} @A.sum'.format(self))    # A类sum方法
              self.n += m
      
      # B类 单继承 A类
      class B(A):
          def __init__(self):
              self.n = 10 # B类n=10
      
          def addb(self, m):
              print('self is {0} @B.addb'.format(self))  # B类addb方法
              super().sum(m)  # 调用父类A的方法 sum n=n+m
              self.n += 2 # 不调用父类A sum n = n+2
      
      # C类 单继承 A类
      class C(A):
          def __init__(self):
              self.n = 100
      
          def addc(self, m):
              print('self is {0} @C.addc'.format(self))   # C类addc方法
              super().sum(m)  # 调用父类A的方法 sum n=n+m
              self.n += 3
      
      # D类 多继承 B类  C 类
      class D(B, C):
          def __init__(self):
              self.n = 1000
      
          def addd(self, m):
              print('self is {0} @D.addd'.format(self))    # D类addd方法
              super().sum(m)  # 调用父类B/C的父类A的方法 sum n=n+m
              super().addb(m) # 调用父类B的方法 sum n=n+2
              super().addc(m) # 调用父类C的方法 sum n=n+3
              self.n += 4
      
      if __name__ == "__main__":
      
          a = A()
          b = B()
          c = C()
          d = D()
      
          b.addb(20)
          print("B 类调用方法addb(add调用父类A的sum) n = ",b.n)  # B 类调用方法add n =  32   B类addb 调用A类sum
          print("获取 A 类 n值 ",a.n)
      
          a.sum(10)
          print("A 类调用方法sum , n = ",a.n)  # A 类调用方法sum , n =  11  调用A类sum
      
          c.addc(30)
          print("C 类调用方法addc , n = ", c.n)  # C 类调用方法sum , n =  133   C类 调用A类
      
          d.addd(40)
          print("D 类调用方法addd , n = ", d.n)  # D 类调用方法sum , n =  1129  D类 调用A类 调用B类(调用A类)调用A类 调用C类(调用A类)
      # B
      self is <__main__.B object at 0x04BD10D0> @B.addb
      self is <__main__.B object at 0x04BD10D0> @A.sum
      B 类调用方法addb(add调用父类A的sum) n =  32
      获取 A 类 n值  1
      # A
      self is <__main__.A object at 0x04BD10A0> @A.sum
      A 类调用方法sum , n =  11C
      # C
      self is <__main__.C object at 0x04BD1100> @C.addc
      self is <__main__.C object at 0x04BD1100> @A.sum
      C 类调用方法addc , n =  133
      # A
      self is <__main__.D object at 0x04BD1130> @D.addd
      self is <__main__.D object at 0x04BD1130> @A.sum
      # B
      self is <__main__.D object at 0x04BD1130> @B.addb
      self is <__main__.D object at 0x04BD1130> @A.sum
      #C
      self is <__main__.D object at 0x04BD1130> @C.addc
      self is <__main__.D object at 0x04BD1130> @A.sum
      
      D 类调用方法addd , n =  1129

 

  • __del__ : 析构函数,释放对象时使用

    • 对象资源被释放时触发,在对象即将被删除时的最后操作
    • # coding:utf-8
      from loguru import logger as logs
      
      
      class demo:
      
          def __init__(self):
              """对象资源被创建时调用"""
              logs.debug("构造函数")
      
          def __del__(self):
              """对象资源被释放时触发,在对象即将被删除时的最后操作"""
              logs.debug("析构函数")
      
          def run(self):
              logs.debug("run函数")
      
      
      if __name__ == "__main__":
          demo().run()

       执行结果

    •  
    • 注册析构函数
      # coding:utf-8
      import xlrd
      from atexit import register
      from loguru import logger as logs
      
      
      class demo:
      
          def __init__(self):
              """对象资源被创建时调用"""
              logs.debug("构造函数")
              # 注册一个析构函数,拥有与__del__函数同样的效果
              register(self.regfun)
      
          def __del__(self):
              """对象资源被释放时触发,在对象即将被删除时的最后操作"""
              logs.debug("del析构函数")
      
          def regfun(self):
              """被注册的析构函数"""
              logs.debug("注册的析构函数")
      
          def run(self):
              logs.debug("run函数")
      
      
      if __name__ == "__main__":
          demo().run()

       执行结果

    •  

       

       

<Tips:在del中直接使用open方法,或调用的函数中包含open方法时会报错>

Exception ignored in: <function playThread.__del__ at 0x0B8A8070>
……
NameError: name 'open' is not defined

 

   解决方法:将open方法挪到其他位置调用,或者注册析构函数实现

 

  • __repr__ : 打印,转换

    •  __repr__() 方法是类的实例化对象用来做“自我介绍”的方法,默认情况下,它会返回当前对象的“类名+object at+内存地址”,对该方法进行重写,可以为其制作自定义的自我描述信息
      class run_case:
      
          def __init__(self, name, age):
              print("__init__")
              self.name = name
              self.age = age
      
          def __repr__(self):
              """__repr__() 方法是类的实例化对象用来做“自我介绍”的方法[即:制作自定义的自我描述信息]
      
              :return: 类名+object at+内存地址
              """
              return "run_case [name = %s, age = %s]" %(self.name, self.age)
      
      
      if __name__ == "__main__":
          t = run_case("1", "2")
          print(t)

       执行结果

      # 默认
      <__main__.run_case object at 0x04B83F10>
      
      # __repr__描述后
      __init__
      run_case [name = 1, age = 2]
      
      进程已结束,退出代码为 0

       

       

  • __str__:方法需要返回一个字符串,当做这个对象的描写

    类似?  __repr__

 

  • __setitem__ :  按照索引赋值

  • __getitem__:  按照索引获取值

  • __delitem__:按照索引删除值

  • # coding:utf-8
    
    class Foo:
        def __init__(self, name):
            self.name=name
    
        def __getitem__(self, item):
            print("调用 __getitem__")
            return self.__dic__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key]=value
            print("调用 __setitem__")
    
        def __delitem__(self, key):
            print("调用 __delitem__")
            self.__dict__.pop(key)
    
        def __delattr__(self, item):
            print("调用 __delattr__")
            self.__dict__.pop(item)
    
    if __name__ == "__main__":
        f=Foo('sb')
        print(f.__dict__)
        #f.age=18
        f['age']=18
        print(f.__dict__)
        #f.age1=19
        f['age1']=19
        print(f.__dict__)
        del f.age1
        print(f.__dict__)
        del f['age']
        print(f.__dict__)
        f['name'] = 'alex'
        print(f.__dict__)
        f['moon'] = "shiliuyuan"
        print(f.__dict__)
        print(f.moon)
    get、set、del item及delattr示例

     

   执行结果

  

 

 

 

  • __len__: 返回容器中元素的个数;即获得长度
    # coding:utf-8
    from loguru import logger as logs
    
    class Demo:
        def __init__(self, name):
            self.name=name
    
        def __len__(self):
            logs.info("调用__len__")
            return len(self.name)
    
    class DemoTwo:
        def __init__(self, name):
            self.name=name
    
    
    
    if __name__ == "__main__":
        # __len__
        d =  Demo("sunnine")
        logs.debug(d)
        logs.debug(d.name)
        logs.debug(len(d))
        logs.debug(len(d.name))
        # 无__len__
        dt = DemoTwo("lucy")
        logs.debug(dt)
        logs.debug(dt.name)
        logs.debug(len(dt))
        logs.debug(len(dt.name))
    示例

     执行结果:

     

     

      

  • __cmp__: 即可实现对实例对象进行排序;即比较运算

 

  • __call__: 函数调用
    # coding:utf-8
    from loguru import logger as logs
    
    class Demo:
        def __call__(self, a, b):
            logs.debug(f"调用__call__:{a},{b}")
    
    
    
    if __name__ == "__main__":
        dic = [12, 10, 55, 23, 99, 0]
    
        d = Demo()
        d("name", "zhangsan")   # 方法一
    
        d.__call__("age", "28")

     执行结果:

     

      

  • __add__: 加运算
    # coding:utf-8
    from loguru import logger as logs
    
    class Demo:
        def __init__(self):
            self.f = 2
    
        def __add__(self, other):
            return other+self.f
    
    if __name__ == "__main__":
        dic = [12, 10, 55, 23, 99, 0]
    
        d = Demo()
        logs.debug(d.__add__(dic[0]))  #方法一
        logs.debug(d.f.__add__(10))  #方法二

     执行结果: 

  • __sub__: 减运算
  • __mul__: 乘运算
  • __truediv__: 除运算
  • __mod__: 求余运算
  • __pow__: 乘方
    # coding:utf-8
    from loguru import logger as logs
    
    class Demo:
        def __init__(self):
            self.f = 2
    
    if __name__ == "__main__":
        dic = [12, 10, 55, 23, 99, 0]
    
        d = Demo()
        logs.debug(d.f.__add__(dic[1]))     # 加运算
        logs.debug(d.f.__sub__(dic[1]))     # 减运算
        logs.debug(d.f.__mul__(dic[1]))     # 乘运算
        logs.debug(d.f.__truediv__(dic[1]))     #除运算
        logs.debug(d.f.__mod__(dic[1]))     # 求余运算
        logs.debug(d.f.__pow__(dic[1]))     # 乘方

     执行结果:

     

     

     

 

posted @ 2021-09-10 10:11  Phoenixy  阅读(125)  评论(0编辑  收藏  举报