• python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法


    1. 元类type

    • type:获取对象从属的类

      Python中一切皆对象,类在某种意义上也是一个对象

      Python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的

      # type 获取对象从属于的类
      print(type(A))
      print(type(str))
      print(type(dict))
    • type与object的关系:

      object类是type类的一个实例 print(type(object))
      object类是type类的父类 print(issubclass(type,object))

    2. 反射

    • 定义:通过字符串操作对象的方式,程序对自己内部代码的一种自省方式

    • 内置函数:hasattr getattr setattr delattr (attr 是属性的意思)

    • 反射可以作用的对象:实例对象,类,本模块,其他模块

      从对象角度应用反射

      class A:
          country = '中国'
          def __init__(self,name,age):
              self.name = name
              self.age = age
          def func(self):
              print('in A func')
      obj = A('张三',66)
      
      # hasattr: 判断有无属性
      print(hasattr(obj,'name'))
      print(hasattr(obj,'country'))   # 报错
      print(hasattr(obj,'func'))   # 报错
      
      # getattr: 获取属性
      if hasattr(obj,'name'):
          getattr(obj,'name')
          
      # setattr: 设置属性/delattr: 删除属性
      setattr(obj,'sex','')
      delattr(obj,'name')

      从类的角度应用反射

      class A:
          country = '中国'
          def __init__(self,name,age):
              self.name = name
              self.age = age
          def func(self):
              print(self)
              print('in A func')
      
      if hasattr(A,'func'):
          obj = A('张三', 26)
          getattr(obj,'func')()
          getattr(A,'func')(obj)

      从其他模块应用反射

      import tbjx
      
      # 1. 找到tbjx对象的C类,实例化一个对象.
      obj = getattr(tbjx,'C')('123')
      
      # 2. 找到tbjx对象的C类,通过对C类这个对象使用反射取到area.
      print(getattr(tbjx.C,'area'))
      
      # 3. 找到tbjx对象的C类,实例化一个对象,对对象进行反射取值.
      obj = getattr(tbjx,'C')('张三')
      print(obj.name)
      print(getattr(obj,'name'))

      从当前模块应用反射

      def func1():
          print('in func1')
      
      def func2():
          print('in func2')
      
      def func3():
          print('in func3')
      
      def func4():
          print('in func4')
      
      
      import sys
      print(sys.modules[__name__])
      getattr(sys.modules[__name__],'func1')()
      getattr(sys.modules[__name__],'func2')()
      getattr(sys.modules[__name__],'func3')()
      
      # 本模块的模块名:sys.modules[__name__]
    • 反射应用示例:

      class User:
          def login(self):
              print('欢迎来到登录页面')
      
          def register(self):
              print('欢迎来到注册页面')
      
          def save(self):
              print('欢迎来到存储页面')
      
      choose_dic = {
          1: User.login,
          2: User.register,
          3: User.save,
      }
      
      while 1:
          choose = input('请输入序号: 
      1: 登录
      2: 注册
      3: 存储').strip()
          obj = User()
          choose_dic[int(choose)](obj)

    3. 函数与类的区别

    • 函数都是显性传参,方法都是隐形传参

      class A:
          @classmethod
          def func(cls,a):
              pass
          @staticmethod
          def func1():
              pass
      
      A.func(666)
      A.func()
    • 通过打印函数名的方式,区别什么是方法,什么是函数

      def func1():
          pass
      class A:
          def func(self):
              pass
      print(func1)
      print(A.func)
      obj = A()
      print(obj.func)
      
      # 结果:
      <function func1 at 0x000000A9C59C1EA0>
      <function A.func at 0x000000A9C75DE268>
      <bound method A.func of <__main__.A object at 0x000000A9C744D4A8>>
    • 可以借助模块判断类中的是方法还是函数

               

    from types import FunctionType
    from types import MethodType
    def func():
        pass
    class A:
        def func(self):
            pass
    obj = A()
    print(isinstance(func,FunctionType))  # True
    print(isinstance(A.func,FunctionType))  # True
    print(isinstance(obj.func,FunctionType))  # False
    print(isinstance(obj.func,MethodType))  # True

    4. 特殊的双下方法

    • 特殊的双下方法: 原本是开发python这个语言的程序员用的.源码中使用的,双下方法: 你不知道你干了什么就触发某个双下方法

      # 1.__len__   len(b)执行b类从属父类的__len__方法,必须要有return int(返回值)
      class B:
          def __init__(self,name,age):
              self.name = name
              self.age =age
          def __len__(self):
              return len(self.__dict__)  # 2
      b = B('张三',28)
      print(len(b))
      
      
      # 2.__hash__  hash()触发__hash__双下方法
      class A(object):
          def __hash__(self):
              return 123456
      obj = A()
      print(hash(obj))
      
      
      # 3.__str__ 里边必须有return "字符串"类型  (优先级高于__repr__)
      #   -  打印对象的时候,会触发__str__方法
      #   -  str转化也可以触发
      class A:
          def __init__(self,name,age):
              self.name = name
              self.age =age
          def __str__(self):
              print('触发str方法')
              return f'姓名: {self.name} 年龄: {self.age}'
      a = A('张三',35)
      
      # 打印对象触发__str__方法
      print(f'{a.name}  {a.age}')
      print(a)
      
      # 直接str转化也可以触发.
      print(str(a))
      
      
      
      # 4.__repr__  里边必须有return "字符串"类型
      #   -  打印对象的时候,会触发__repr__方法
      class A:
          def __init__(self,name,age):
              self.name = name
              self.age =age
          def __repr__(self):
              print(666)
              return f'姓名: {self.name} 年龄: {self.age}'
      
      a = A('张三',35)
      print(a)
      print(repr(a))
      
      
      # 5.__call__  对象()触发对象从属类(父类)的__call__方法
      class Foo:
          def __init__(self):
              pass
          def __call__(self, *args, **kwargs):
              print('__call__')
      obj = Foo()
      obj()
      
      
      # 6.__eq__   两对象==时触发,return True/false(可以返回数字,字符串 一般返回布尔值)
      class A(object):
          def __init__(self):
              self.a = 1
              self.b = 2
      
          def __eq__(self,obj):
              print('__eq__')
              return True
      x = A()
      y = A()
      print(x == y)
      
      
      # 7.__del__ 析构方法 回收对象时触发__del__方法
      class A:
          def __del__(self):
              print('__del__')
      obj = A()
      del obj
      
      
      # 8.__new__  new一个对象(构造方法),实例化对象的时候会触发,对象是object类的__new__方法,产生了一个对象
      class A(object):
          def __init__(self):
              print('in init function')
      
          def __new__(cls, *args, **kwargs):
              print('in new function')
              return object.__new__(A)
      
      # 对象是object类的__new__方法 产生了一个对象.
      a = A()
      
      # 类名()
      # 1. 先触发 object的__new__方法,此方法在内存中开辟一个对象空间.
      # 2. 执行__init__方法,给对象封装属性.
      
      # def __init__(self):(不能写返回值,因为__new__已经有返回值了,不能同时接收两个返回值,只能接收__new__的返回值)
          
      
      
      # 9.__item__系列(4个)
      # __getitem__ __setitem___ __delitem__ 对对象做类似于字典的(增删改查)触发__item__系列
      class Foo:
          def __init__(self,name):
              self.name=name
      def __getitem__(self, item):
          # print(item)
          # print(666)
          return self.__dict__[item]
      
      def __setitem__(self, key, value):
          # self.__dict__[key]=value
          print(key)
          print(value)
      
      def __delitem__(self, key):
          print('del obj[key]时,我执行')
      
      f1=Foo('zhangsan')
      f1['age']
      f1[1] = 2
      del f1[1]
      
      
      # 10.__enter__ __exit__  with 上下文管理(2个)
      class A:
      
          def __init__(self, text):
              self.text = text
      
          def __enter__(self):  # 开启上下文管理器对象时触发此方法
              self.text = self.text + '您来啦'  # 第一步
              print(11111)
              return self  # 必须!!!将实例化的对象返回f1
      
          def __exit__(self, exc_type, exc_val, exc_tb):  # 执行完上下文管理器对象f1时触发此方法
              print(333)  # 第三步
              self.text = self.text + ',这就走啦'
      
      with A('大爷') as f1:
          print(2222)
          print(f1.text)  # 第二步
      print(f1.text)  # 第四步
      
      
      
      # 11.__iter__  for循环会触发此方法
      class A:
          def __init__(self,name):
              self.name = name
      
          def __iter__(self):
              for i in range(10):
                  yield i
      
      obj = A('张三')
      for i in obj:
          print(i)
      
      # 12.__getattr__(self,item),__setattr__(self,key,value),__delattr__ 
      #   obj.属性会触发__getattr__(self,item)方法
      #   obj.属性=123 会触发__setattr__(self,key,value)   
      #   del obj.属性 就会触发__delattr__ 此方法
    • def func1():
          pass
      class A:
          def func(self):
              pass
      print(func1)
      print(A.func)
      obj = A()
      print(obj.func)
      
      # 结果:
      <function func1 at 0x000000A9C59C1EA0>
      <function A.func at 0x000000A9C75DE268>
      <bound method A.func of <__main__.A object at 0x000000A9C744D4A8>>
      
  • 相关阅读:
    总结ORACLE学习8023
    set @CurrentID=@@IDENTITY
    一个IT人:跳槽一定要谨慎
    SQL Server数据库开发(转自CSDN)
    46个不得不知的生活小常识
    CodeProjectSome Cool Tips For .Net 之一
    数据库原理综合习题答案
    EDM
    CodeProject Some Cool Tips for .NET之二
    The operation is not valid for the state of the transaction.
  • 原文地址:https://www.cnblogs.com/qiu-hua/p/12862265.html
Copyright © 2020-2023  润新知