zoukankan      html  css  js  c++  java
  • 反射 双下方法

    一 : 元类 type

    1. Type 获取对象从属的类
    class A:
        pass
    print(type('abc'))     #  <class 'str'>
    print(type([1,2,3]))    #  <class 'list'>
    print(type((22,33)))    #  <class 'tuple'>
    
    1. python 中一切皆对象,类在某种意义上也是一个对象,python 中自己定义的类,以及大部分内置类,都是由 type元类实例化得来的

    2. type 与 object 的关系

      object 是 type 类的一个实例

      object 是type类的父类

      print(issubclass(type,object))
      #  True
      

    二 : 反射

    1. 程序对自己内部代码的一种自省

    2. 反射是什么?

      通过字符串去操作对象的方式

    ​ 四种使用场所

    ​ 实例对象

    ​ 类

    ​ 本模块

    ​ 其他模块

    1. hasattr  getattr  setattr delattr
      

    实例对象

    **hasattr : 判断是否存在,存在返回True,不存在返回 False **

    print(hasattr(obj,'name'))      #  True
    print(hasattr(obj,'country'))   #  True
    print(hasattr(obj,'func'))      #   True
    

    getattr : 返回的是具体值,相当于取代那个万能的点

    print(getattr(obj,'name'))      #  赵海狗
    
    print(getattr(obj,'country'))   #  中国
    
    print(getattr(obj,'func'))     #  <bound method A.func of <__main__.A object at 0x10a3d3b70>>
    
    print(getattr(obj,'func')())   已经调用了这个函数了
    # in A func
    # None
    
    print(getattr(obj,'sex',None))  #  指定查不到就返回 None
    print(getattr(obj,'sex'))  # 报错
    

    setattr : 相当于增加一个属性

    setattr(obj,'sex','公')  #  增加一个
    print(obj.__dict__)
    # {'name': '赵海狗', 'age': 78, 'sex': '公'}
    

    **delattr : 删除一个属性 **

    delattr(obj,'name')  # 删除里面的值
    print(obj.__dict__)
    {'age': 78, 'sex': '公'}
    
    从类的角度
    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,'country'):
    #     print(getattr(A,'country'))  # 中国
    if hasattr(A,'func'):
        obj = A('赵海狗',26)
        getattr(obj,'func')()            在对象中调用,隐性传参
    #<__main__.A object at 0x10966c240>  在函数中调用,显性传参   两种是一样的
    # in A func
       getattr(A,'func')(obj)
    # <__main__.A object at 0x10966c240>
    # in A func
    
    从其他模块
    import tbjx  (从其他文件导过来的)
    
    # 1.找到tbjx对象的C类,实例化一个对象
    # print(getattr(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')) #   赵海狗
    
    
    tbjx 文件如下
    name = '太白金星'
    
    def func():
        print('in tbjx func')
    class C:
        area = '北京'
    
        def __init__(self,name):
            self.name = name
    
        def func(self):
            print('in B func')
    
    

    从当前模块研究反射

    a = 666
    def func():
        print('in 本模块这个对象')
    def func1():
        print('in func1')
    def func2():
        print('in func2')
    def func3():
        print('in func3')
    def func4():
        print('in func4')
    
    # func1()
    # func2()
    # func3()
    # func4()
    
    
    import sys
    print(sys.modules[__name__])
    # <module '__main__' from '/Users/zhl/Desktop/python_24/day26/课堂练习.py'>
    # 相当于一个字典   查找都有
    print(getattr(sys.modules[__name__],'a'))
    # 666
    
    
    func_lst = [f'func{i}' for i in range(1,5)]
    print(func_lst)
    for func in func_lst:
        getattr(sys.modules[__name__],func)()
        
    in func1
    in func2
    in func3
    in func4
    
    
    
    反射的应用
    class User:
        user_list = [('login','登录'),('register','注册'),('save','存储')]
        def login(self):
            print('欢迎来到登录界面')
        def register(self):
            print('欢迎来到注册界面')
        def save(self):
            print('欢迎来到存储界面')
    while 1:
        choose = input('请输入序号:
    1:登录
    2:注册
    3:存储
    ').strip()
        obj = User()
        getattr(obj,obj.user_list[int(choose) - 1][0])()
        #  getattr(obj,'login)
    #  这样简化代码 显得更高大上一些
    
    

    三 : 函数与方法的区别

    通过打印函数名的方式区别什么是方法,什么是函数(了解)

    def func1():
        pass
    class A:
        def func(self):
            pass
    print(func1)
    print(A.func)    #  通过类名调用的类中的实例方法叫做函数
    obj = A()
    print(obj.func) # 通过对象调用类中的实例方法叫做方法
    
    
    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
    #  所以这个类名调用的类中的实例方法叫做函数
    #  通过对象调用类中的实例方法叫做方法
    
    

    **总结 : **

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

    以及大部分内置类,都是由type 元类实例化而来

    Python 中一切皆对象,函数在某种意义上也是一个对象,函数这个对象是从 FunctionType这个实例化出来的

    Python 中一切皆对象,方法在某种意义上也是一个对象,方法这个对象是从 MethodType这个类实例化出来的

    如何判断类中的是方法还是函数 ? ?

    class A:
        @classmethod
        def func(cls,a):  # 显性和隐性是从这里判断
            pass
        @staticmethod
        def func1( ):
            pass
    A.func(222)
    # A.func()
    obj = A()
    obj.func('是')
    # 只要参数不对等,并且有 self  cls 就是隐性传参  函数
    
    

    四 : 特殊的双下方法

    用途 : 原本是开发Python这个语言的程序员用的,源码中使用

    str : 我们不能轻易使用,慎用

    双下方法 : 不知道触发某个方法走下去

    __len__

    class B:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __len__(self):
            print(self.__dict__)
    
            return len(self.__dict__)
    b = B('liye',28)  #  {'name': 'liye', 'age': 28}
    print(len(b))     # 2
    
    print(len({'name':'liye','age':28}))   # 2
    
    字典的话就是键值对的个数  其他就是元素的个数
    
    

    __str__ 用来返回字符串表达式

    class A:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __str__(self):
            print(666)
            return f'姓名:{self.name} 年龄:{self.age}'
    a = A('赵海狗',35)
    b = A('李业',33)
    c = A('华丽',18)
    #  打印对象触发 __str__
    print(f'{a.name} {a.age}')  # 赵海狗 35
    print(f'{b.name} {b.age}')  # 李业 33
    print(f'{c.name} {c.age}')  # 华丽 18
    print(a)  
    #666
    # 姓名:赵海狗 年龄:35
    print(b)
    print(c)  
    
    
    print(str(a))    直接 str 也可以触发
    #666
    # 姓名:赵海狗 年龄:35
    
    打印了对象就触发了 str 所以是这个意思
    
    

    __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)
    b = A('李业',12)
    c = A('华丽',18)
    print(a)
    print(repr(a))
    # 666
    # 姓名:赵海狗 年龄:35
    # 666
    # 姓名:赵海狗 年龄:35
    # 两个结果是一样的
    #  打印对象后也是触发 repr 吗?  他两有什么区别呢?和 str
    
    
    print('我叫%s' % ('alex'))  # 我叫alex
    print('我叫%r' % ('alex'))  # 我叫'alex'
    print(repr('fdsaf'))        #  'fdsaf'
    
    看这个结果是把字符串啥的引号都给表现出来了
    
    

    _call_

    对象() 自动触发对象从属于类(父类)的__call__方法

    class Foo:
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    obj = Foo()
    obj()
    #  __call__
    
    

    _eq__

    class A(object):
        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
            # return True
    x = A()
    y = A()
    print(x == y)
    # True 
    两种比较
    
    

    __del__

    class A:
        def __del__(self):
            print(666)
    obj = A()
    del obj
    #  666
    
    

    _new_

    class A(object):
    
        def __init__(self):
    
            self.x = 1
            print('in init function')
    
        def __new__(cls, *args, **kwargs):
            print('in new function')
            return object.__new__(A)  # object 342534
    
    # # 对象是object类的__new__方法 产生了一个对象.
    a = A()
    
    #in new function
    in init function
    
    
    # 类名()
    # 1. 先触发 object的__new__方法,此方法在内存中开辟一个对象空间.
    # 2. 执行__init__方法,给对象封装属性.
    
    我自己的理解是先执行 new  然后再执行 init
    
    

    五 : python 中单例模式 重要必须会默写

    class A:
        __instance = None
    
        def __init__(self,name):
            self.name = name
    
        def __new__(cls,*args,**kwargs):
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    obj = A('alex')
    print(obj)
    obj1 = A('李业')
    print(obj1.name)
    print(obj.name)
    #  <__main__.A object at 0x106e8cf28>
    # 李业
    # 李业
    
    
  • 相关阅读:
    研发环境容器化实施过程(docker + docker-compose + jenkins)
    Java虚拟机-字节码执行引擎
    Java虚拟机-类加载机制
    Java虚拟机-字节码指令
    Java虚拟机-类文件结构
    Java虚拟机理解-内存管理
    单元测试实践(SpringCloud+Junit5+Mockito+DataMocker)
    Git基础概念与Flow流程介绍
    谷歌最佳实践
    谷歌最佳实践
  • 原文地址:https://www.cnblogs.com/hualibokeyuan/p/11330872.html
Copyright © 2011-2022 走看看