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

    1. 类的反射

    程序对自己内部代码的一种自省方式。
    定义:通过字符串取操作对象的方式。
    可应用于实例对象、类、本模块、其他模块。 带有点 . 的方式都可用反射方法。
    
    四种方法:
    	1. hasattr(object, name)  # 判断、检测
    	2. getattr(object, name)  # 获取
    	3. setattr(object, name)  # 设置
    	4. delattr(object, name)  # 删除属性
    

    1.1 实例对象

    class A:
        country = '中国'
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print('in A func')
    
    obj = A("meet", 18)
    
    print(hasattr(obj, 'name'))	# True 检测是否有name属性
    print(hasattr(obj, 'sex'))  # False 
    
    print(getattr(obj, 'name')) # 获取obj的name属性
    print(getattr(obj, 'sex', None))      
    	#指定获取不到,返回None
    getattr(obj,'func')()    
    	# 调用obj的func方法,自动将obj地址传入参数中
    if hasattr(obj, 'func'):
        getattr(obj, 'func')()
        
    setattr(obj, 'sex', '男')  # 给obj增加 sex='男' 属性
    deltattr(obj,'name')	# 删除obj的name属性
    print(obj.__dict__)
    

    1.2 类

    # 通过类名
    class A:
        country = '中国'
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print('in A func')
            
    if hasattr(A, 'country')
    	print(getattr(A, 'country'))  # 中国
    
    if hasattr(A, 'func'):
        obj = A("meet", 18)
        getattr(A, 'func')(obj)
    #或:getattr(obj,'func')()
    
    

    1.3 其他模块 -- 其他.py文件

    # 名字为 tbjx.py 的文件
    
    name = "太白金星"
    
    def func():
        print("这是func函数")
    
    class C:
        area = '北京'
    
        def __init__(self, name):
            self.name = name
    
        def func1(self):
            print('in C func1')
    
    # 本文件
    import tbjx    # 导入
    
    print(getattr(tbjx,'name'))  # 获取变量name
    getattr(tbjx, 'func')()		# 执行func函数
    
    obj = getattr(tbjx,'C')('meet')	# 实例化对象
    
    print(getattr(tbjx.C, 'area'))	# 查找C类的area属性
    
    ret = getattr(tbjx,'C')	# 实例化对象后执行类的func1方法
    obj = ret('meet')
    getattr(obj, 'func')()
    

    1.4 本模块 -- 当前.py文件

    import sys
    sys.modules[__name__]  # 获取当前py文件的模块对象
    
    def func1():
        print('in func1')
    
    def func2():
        print('in func2')
    
    def func3():
        print('in func3')
    
    def func4():
        print('in func4')
    
    import sys
    content = input('请输入:')    # 输入函数名
    ret = sys.modules[__name__]  # 获取本文件模块的对象
    getattr(ret, content)()
    
    class User:
        user_list = [('login', '登录'), ('register', '注册'), ('save', '存储')]
    
        def login(self):
            print('欢迎来到登录页面')
    
        def register(self):
            print('欢迎来到注册页面')
    
        def save(self):
            print('欢迎来到存储页面')
    
    while True:
        obj = User()
        for i in enumerate(obj.user_list, 1):
            print(f'{i[0]}.{i[1][1]}')
        choose = input('请输入序号:').strip()
        getattr(obj, obj.user_list[int(choose)-1][0])()
    

    2. 函数与方法的区别

    2.1区别的方法:

    方法一:
    	通过打印函数名的方式。 通过类名调用的方法是函数,通过对象调用类中的实例方法,是方法。
    方法二:借助模块
    	from types import FunctionType
    	from types import MethodType
    
    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
    

    2.2 总结

    总结:
    	函数都是显性传参,方法都是隐形传参;
        类方法是一个方法,静态方法是一个函数。
    扩展:Java中只有方法,C中只有函数,C++么,则取决于是否在类中。
    

    3. 特殊的双下方法

    ​ 原本是开发python这个语言的程序员用的,源码中使用的。不能轻易使用、使用。

    3.01 __len__ (len一下对象就触发)

    class B:
        def __len__(self):
            print(666)
    
    b = B()
    len(b) 		# len 一个对象就会触发 __len__方法。
    
    # 返回a对象的属性的个数
    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    a = A()
    print(len(a))
    

    3.02 __hash__ (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))   # 若本类没有,就会从object父类找
    

    3.03 __str__ (打印对象触发、str()也会触发)

    class A:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def __str__(self):
            return f'姓名:{self.name} 年龄:{self.age}'
        # 必须是 return 字符串
    a = A('meet', 18)
    print(a)    # 触发  
    

    3.04 __repr__ (打印对象和repr()都会触发)

    class A:
        def __init__(self):
            pass
        def __repr__(self):
            return '太白'
    a = A()
    print(repr(a))
    print('%r'%a)    # 优先级低于str
    

    3.05 __call__ (对象名(),触发)

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

    3.06 __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)	# 触发
    

    3.07 __del__ (析构方法)

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

    3.08 __new__ (构造方法 类名()触发)

    class A:
        def __init__(self):
            self.x = 1
            print('in init function')
        def __new__(cls, *args, **kwargs):
            print('in new function')
            return object.__new__(A, *args, **kwargs)
    
    a = A()		#触发
    print(a.x)
    
    # 类名(),触发object类的__new__方法,产生了一个对象空间并返回到  类名(), 再触发__init__方法,封装对象属性。
    

    单例模式:

    一个类只允许实例化一个对象。 将对象唯一化(延用同一个对象空间)。节省内存,减少开销。
    方便对实例个数的控制并节约系统空间。  如:电脑的任务管理器。
    
    class A:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if cls.__instance is None:
                obj = object.__new__(cls)
                cls.__instance = obj
            return cls.__instance
    obj = A()
    print(obj)
    obj1 = A()
    print(obj1)   # 两次地址相同
    

    3.09 _item_ 类似字典操作触发

    # 1. __getitem__  对对象进行类似于字典取值操作时触发
    
    class A:
        def __init__(self, name):
        	self.name = name
        def __getitem__(self, item):
            return self.__dict__[item]
    obj = A('meet')
    print(obj['name'])		# meet
    
    # 2.__setitem__  对对象进行类似字典的增改触发
    
    class A:
        def __init__(self, name):
            self.name = name
            
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    obj = A('meet')
    obj['age'] = 18
    print(obj.__dict__)		# {'name': 'meet', 'age': 18}
    
    # 3.__delitem__ 对对象进行类似字典的删除
    
    class A:
        def __init__(self, name):
            self.name = name
            
        def __delitem__(self, key):
            self.__dict__.pop(key)
    obj = A('meet')
    
    del obj['name']
    print(obj.__dict__)		# {}
    

    3.10 _delattr_ del 对象.属性 会触发

    # 删除对象属性,找不到属性会报错;并不是真正的删除,而是触发__delattr__方法,delattr中有写入删除的功能。
    
    class A:
        def __init__(self, name):
            self.name = name
            
        def __delattr__(self, item):
            self.__dict__.pop(item)
    obj = A('meet')
    
    del obj.name
    print(obj.__dict__)		# {}
    

    3.11 _enter_ _exit_ : with 上下文管理

    # 实例化对象的第二种方法: 必须基于__enter__、__exit__方法。
    # 再进f1前执行enter、退出后执行exit
    
    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)				# 大爷您来啦,这就走啦
    

    3.12 _iter_

    # 在类中加入__iter__(self),将对象转换为可迭代对象,for循环可触发
    
    class A:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __iter__(self):
    
            for j in range(10):
                yield j
    
    obj = A('meet', 18)
    # print(dir(obj))
    for i in obj:
        print(i)     # 打印 0 1 2 ...
    
  • 相关阅读:
    在插入一条记录后 取得自动增长ID
    hashtable,dictionary 从原理上说说有什么异同,哪个性能高一些
    单例模式
    聚簇索引与非聚簇索引的区别
    基于SQL SERVER2008的SCCM2007部署
    XML架构下的表结构设置主键
    IE6与IE7下一点样式的区别
    Session丢失原因与解决方案小结
    Python_如何去除字符串里的空格
    Python_让人脑阔疼的编码问题(转)+(整理)
  • 原文地址:https://www.cnblogs.com/liwenhu/p/11401577.html
Copyright © 2011-2022 走看看