面向对象的反射和双下方法

1.函数vs方法

  • 函数:全部都是显性传参

  • 方法:存在隐性传参

  • 判断方法

    • 通过函数名可大致判断

    • 通过types模块去验证

    • from types import FunctionType
      from types import MethodType
      
      
      def func():
          pass
      
      
      class A:
      
          def func(self):
              pass
      
          @staticmethod
          def f():
              pass
      # print(isinstance(func, FunctionType))
      # print(isinstance(func, MethodType))
      
      # 类名调用func 就是一个函数
      # print(isinstance(A.func, FunctionType))
      # print(isinstance(A.func, MethodType))
      # obj = A()
      # 对象调用func 就是一个方法
      # print(isinstance(obj.func, FunctionType))
      # print(isinstance(obj.func, MethodType))
      
      # 对于静态方法的研究
      # print(isinstance(A.f, FunctionType))
      # print(isinstance(A.f, MethodType))
      
      # obj = A()
      # # 对象调用func
      # print(isinstance(obj.f, FunctionType))
      # print(isinstance(obj.f, MethodType))
      

2.反射

  • 概念:主要是指程序员可以访问,检测和修改它本身状态或行为的一种能力(自省),

  • python中面向对象的反射 : 通过字符串的形式操作对象的相关属性,python中的一切事物都是对象(都可以使用反射)

    • ['从实例的角度去研究反射']

    • # class A:
      #
      #     static_field = '静态属性'
      #
      #     def __init__(self,name,age):
      #         self.name = name
      #         self.age = age
      #
      #     def func(self):
      #         print('in A func')
      # obj = A('MC骚Q',18)
      # print(obj.name)
      
      # print(hasattr(obj,'name'))  #检查是否有'name'属性
      # print(getattr(obj,'name1','没有该属性')) #获取属性,如果没有设置第三个元素,查询不到就会报错
      # print(getattr(obj,'name'))
      # print(getattr(obj,'name1')) #报错
      #
      # setattr(obj,'hobby','玩')  #增加新的属性
      # print(getattr(obj,'hobby'))
      #
      # delattr(obj,'name')         #删除该属性
      # print(hasattr(obj,'name'))
      
      
      # if hasattr(obj,'static_field'):
      #     print(getattr(obj,'static_field'))
      #
      # if hasattr(obj,'func'):
      #     getattr(obj,'func')()#不用实例化,可直接调用方法
      
    • 从类的角度研究反射

    • # class A:
      #
      #     static_field = '静态属性'
      #
      #     def __init__(self,name,age):
      #         self.name = name
      #         self.age = age
      #
      #     def func(self):
      #         print('in A func')
      # obj = A('大表哥',18)
      # print(getattr(A,'func'))
      # getattr(A,'func')(obj)
      
    • 从脚本的角度研究反射

    • # import sys
      # def func1():
      #     print('in func1')
      # this_modules = sys.modules[__name__]  #获取当前脚本这个对象
      # print(this_modules)
      # print(getattr(this_modules,'func1'))
      # getattr(this_modules,'func1')()
      
      # class B:
      #     static = "B类"
      # import sys
      # this_modules = sys.modules[__name__]
      # cls = getattr(this_modules,"B")
      # obj = cls()
      # print(obj.static)
      
    • 应用场景

    • '选择界面'      
      # class Auth:
      #
      #     def login(self):
      #         print('登陆函数')
      #
      #     def register(self):
      #         print('注册函数')
      #
      #     def exit(self):
      #         print("退出")
      #
      # while 1:
      #     function_list = [('login','登录'),('register','注册'),("exit",'退出')]
      #     for num,option in enumerate(function_list,1):
      #         print(num,option[1])
      #     func_name = input("群输入选择:").strip()
      #     obj = Auth()
      #     if hasattr(obj,func_name):
      #         getattr(obj,func_name)()
      #     else:
      #         print('输入错误')
      

3.双下方法

  • 双下方法是特殊方法,主要供python源码程序员使用

  • __len__

    • # class A:
      #     def __init__(self,name):
      #         self.name =name
      #
      #     def __len__(self):
      #         print('触发__len__方法')
      #         return 10
      #
      # obj = A('MC')
      # ret = len(obj)
      # print(ret)
      
  • __hash__

    • class A:
          def __init__(self):
              self.a = 1
              self.b = 2
      
          def __hash__(self):
              return hash(str(self.a)+str(self.b))
      a = A()
      print(hash(a))
      
  • __str__

    • # class A:
      #
      #     def __init__(self):
      #         self.name = '太白'
      #
      #     def __str__(self):
      #         return self.name
      #
      # obj = A()
      # print(obj)
      # print(str(obj))
      
  • __repr__

    • # class Student:
      #     def __init__(self,name,age,sex):
      #         self.name = name
      #         self.age =age
      #         self.sex = sex
      #
      #     def __repr__(self):
      #         return "12"
      #
      #     def __str__(self):
      #         return f"{self.sex}123"
      #
      # object = Student(1,2,3)
      # object1 = Student(1,2,4)
      # object2 = Student(1,2,5)
      #
      # print(str(object))  #会触发__str__
      # print(object)
      # print(object1)
      # print(object2)
      # print(f"此对象为%s" %object) #格式化输出会触发__str__
      # print(f"此对象为%r" %object) #格式化输出会触发__repr__
      #
      # print(obj) #同时存在__str__和__repr__会优先选择__str__执行,优先级别高
      
  • __call__

    • # class A:
      #     def __init__(self):
      #         self.a =1
      #         print(111)
      #
      #     def __call__(self, *args, **kwargs):
      #         print(666)
      #
      # obj = A()
      # obj()
      
  • __eq__

    • class A:
          def __init__(self):
              self.a = 1
              self.b = 2
      
          def __eq__(self,obj):
              if  self.a == obj.a and self.b == obj.b:
                  return True
      a = A()
      b = A()
      print(a == b)
      
  • __del__

    • 析构方法,当对象在内存中被释放时,自动触发执行
    • 此方法一般无需定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因此此工作都是交给python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发和执行的.
  • __new__

    • # class A(object):
      #
      #     def __init__(self):
      #         print('in __init__')
      #
      #     def __new__(cls, *args, **kwargs):
      #         print(cls) #A
      #         print('in __new__')
      #         object1 = object.__new__(cls)  #2. 其次利用object类的__new__产生一个对象空间
      #         return object  # #3. 将这个对象空间返回给了A()即obj
      #
      # obj = A()#1. 先触发__new__,将类名自动传给cls
      
  • __item__

    • class Foo:
          def __init__(self,name):
              self.name=name
      
          def __getitem__(self, item):
              print(self.__dict__[item])
      
          def __setitem__(self, key, value):
              self.__dict__[key]=value
          def __delitem__(self, key):
              print('del obj[key]时,我执行')
              self.__dict__.pop(key)
          def __delattr__(self, item):
              print('del obj.key时,我执行')
              self.__dict__.pop(item)
      
      f1=Foo('sb')
      f1['age']=18
      f1['age1']=19
      del f1.age1
      del f1['age']
      f1['name']='alex'
      print(f1.__dict__)
      
  • 上下文管理器相关__enter__和__exit__

    • # 如果想要对一个类的对象进行with  as 的操作 不行。
      class A:
          def __init__(self, text):
              self.text = text
      
      with A('大爷') as f1:
          print(f1.text)
      
    • class A:
          
          def __init__(self, text):
              self.text = text
          
          def __enter__(self):  # 开启上下文管理器对象时触发此方法
              self.text = self.text + '您来啦'
              return self  # 将实例化的对象返回f1
          
          def __exit__(self, exc_type, exc_val, exc_tb):  # 执行完上下文管理器对象f1时触发此方法
              self.text = self.text + '这就走啦'
              
      with A('大爷') as f1:
          print(f1.text)
      print(f1.text)
      
    • 自定义上下文管理器

    • class Diycontextor:
          def __init__(self,name,mode):
              self.name = name
              self.mode = mode
       
          def __enter__(self):
              print "Hi enter here!!"
              self.filehander = open(self.name,self.mode)
              return self.filehander
       
          def __exit__(self,*para):
              print "Hi exit here"
              self.filehander.close()
       
       
      with Diycontextor('py_ana.py','r') as f:
          for i in f:
              print i
      
原文地址:https://www.cnblogs.com/W-Y-C/p/11178071.html