• python面向对象之反射


    #!/usr/bin/env python
    # coding:utf-8
    
    # 反射
    # 对象的自省
    # python中四种方法 hasattr  getattr  setattr  delattr 都可用于类和对象, 因为python中一切皆对象, 类也是对象。
    # python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
    class black_intro: feture = 'Ugly' def __init__(self, name, addr): self.name = name self.addr = addr def sell_house(self): print('%s 正在卖房子,SB才买呢。' % self.name) def rent_house(self): print('%s 正在租房子,SB才租。' % self.name) b1 = black_intro('众家地产', '苏州') print(hasattr(b1, 'name')) print(hasattr(b1, 'rent_house')) print(hasattr(b1, 'sale_house')) # False print(getattr(b1, 'name')) r = getattr(b1, 'rent_house') r() print(getattr(b1, 'age', '没找到它.')) setattr(b1, 'group', '二货') setattr(b1, 'age', '11') print(b1.__dict__) setattr(b1, 'agea', lambda x: x + 3) setattr(b1, 'func', lambda self: self.name + 'SB公司') print(b1.func(b1)) print(b1.agea(12)) delattr(b1, 'name') delattr(b1, 'age') print(b1.__dict__) ### 反射的应用场景 可插拨设计 # 可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用 from ftp_client import FtpClient f1 = FtpClient('1.1.1.1') # f1.put()
    ### hasattr 和 getattr 通常是配合使用,如果有xx方法,才去执行xx方法。 if hasattr(f1, 'put'): func_get = getattr(f1, 'put') func_get() else: print('其他的逻辑') import sys obj = sys.modules[__name__] # 当前模块 即自己所在模块 print('--------->',hasattr(obj,'black_intro')) # 判断当前模块是否有属性

    上面代码中用到的一个示例模块:

    class FtpClient:
        'ftp客户端,但是还么有实现具体的功能'
        def __init__(self,addr):
            print('正在连接服务器[%s]' %addr)
            self.addr=addr
        # def put(self):
        #     print('正在上传文件')

    类中使用的带有双下划线的 几个: __getattr__     __delattr__     __setattr__

    #!/usr/bin/env python
    # coding:utf-8
    
    # 类中内置的 __getattr__   __delattr__   __setattr__
    # 只有 __getattr__ 最常用
    
    class Foo:
        x = 1
        def __init__(self,y):
            self.y = y
    
        def __getattr__(self, item):  # 调用不存在的属性的时候会被执行
            print("---------------------")
    
        def __delattr__(self, item): # 删除的时候会调用
            print("执行了删除操作__delattr__")
            self.__dict__.pop(item)
    
        # def __setattr__(self, key, value):
        #     print("执行了__setattr__")
        #     # self.key=value # 这样会无限递归, 溢出
        #     self.__dict__[key] = value  # 直接操作字典,才是正确方式
    
    
    f1 = Foo(9) # 当设置了__setattr__ 时,实例化的同时会自动执行它
    print(f1.x)
    f1.xxx # 触发 __getattr__
    
    del f1.y # 删除时触发 __delattr__
    
    f1.y1 = 33 # 设置时触发 __setattr__
    print(f1.__dict__)
    #!/usr/bin/env python
    # coding:utf-8
    
    class Foo:
        x = 1
        def __init__(self,name):
            self.name = name
    
        # def __getattr__(self, item):  # 调用不存在的属性的时候会被执行
        #     print("---------------------")
        #
        # def __delattr__(self, item): # 删除的时候会调用
        #     print("执行了删除操作__delattr__")
        #     self.__dict__.pop(item)
    
        def __setattr__(self, k, v):
            print('设置操作 __setattr__ ')
            # self.key=value # 这样会无限递归, 溢出
            # self.__dict__[k] = v  # 直接操作字典 是正确方式 
            if type(v) is str:
                print('可以设置')
                self.__dict__[k] = v.lower() # 且可以加上可控制的方法
            else:
                print('值 必须是字符串')
    
    
    f2 = Foo('Alex')
    f2.age =18
    f2.gender ='Male'
    print(f2.__dict__)
    #!/usr/bin/env python
    # coding:utf-8
    
    class Foo:
        x = 1
        def __init__(self,name):
            self.name = name
    
        # def __getattr__(self, item):  # 调用不存在的属性的时候会被执行
        #     print("---------------------")
    
        def __delattr__(self, item): # 删除的时候会调用
            # print("执行了删除操作__delattr__")
            # self.__dict__.pop(item)
            print('不允许删除%s'% item) # 可以控制不允许删除
    
        def __setattr__(self, k, v):
            print('设置操作 __setattr__ ')
            # self.key=value # 这样会无限递归, 溢出
            # self.__dict__[k] = v  # 直接操作字典
            if type(v) is str:
                print('可以设置')
                self.__dict__[k] = v.lower() # 且可以加上可控制的方法
            else:
                print('值 必须是字符串')
    
    
    f2 = Foo('Alex')
    f2.age =18
    f2.gender ='Male'
    print(f2.__dict__)
    del f2.name
    print(f2.__dict__)
    #!/usr/bin/env python
    # coding:utf-8
    
    # 包装,来自于继承和派生的概念,根源是基于继承的标准类型。用来定制自己的方法
    class List(list):
        def show_middle(self):
            mid_index = int(len(self)/2)
            return self[mid_index]
    
        # 自定义的append
        def append(self, obj):
            if type(obj) is str:
                super().append(obj)
            else:
                print("只能添加字符串")
    
    
    l2 = list("azkaban")
    print(l2,type(l2))
    l3 = List(l2)
    print(l3.show_middle())
    
    l3.append('232')
    print(l3)
    #!/usr/bin/env python
    # coding:utf-8
    
    # 二次加工标准类型(包装)
    
    class Foo:
        x = 1
        def __init__(self,y):
            self.y = y
    
        def __getattr__(self, item):  # 调用不存在的属性的时候会被执行
            print("[%s]属性不存在" % item)
    
        def __getattribute__(self, item): # 不管是否找到属性都会执行。
            print("执行了getattribute")
            raise AttributeError('抛出异常了。')  # 而在使用抛出异常之后,才会去执行 __getattr__
    
    
    f2 = Foo(9)
    print(f2.y)
    # print(f2.age)

    授权

    #!/usr/bin/env python
    # coding:utf-8
    
    import time
    
    ## 类似于组合的方法
    class FH:
        def __init__(self,na,mo,ec="utf-8"):
            self.file = open(na,mo,encoding=ec)
            self.mode = mo
            self.encoding = ec
    
        def write(self,line):
            t = time.strftime('%Y-%m-%d %X ')
            self.file.write('%s %s'%(t,line))
    
        def __getattr__(self, item):
            return getattr(self.file,item)
    
    f1 = FH('a.txt', 'r+')
    f1.write('aaaaaaaaaaaaaaa
    ')
    f1.write('CPU温度过高
    ')
    f1.write('内存不足
    ')
    f1.write('硬盘剩余空间警告
    ')
    f1.seek(0)  # 其实执行的是打开的文件对象的seek方法
    
    print(f1.read())

    判断实例是否属于类:

    #!/usr/bin/env python
    # coding:utf-8
    
    class Foo:
        pass
    
    class bar(Foo):
        pass
    
    
    f1 = Foo()
    
    print(isinstance(f1,Foo)) # 实例是否属于类
    print(issubclass(bar,Foo)) # 参数1 是否 参数2 的子类
    
    b1 = bar()
    print(isinstance(b1,Foo)) # 也是True
    
    print(type(b1)) # 查看实例的类是谁

    动态导入模块:

    #!/usr/bin/env python
    # coding:utf-8
    
    # 动态导入的方法:
    
    # mt = __import__('m1.t') # 只能导入最顶级模块 点后面的不会被导入
    # print(mt)
    # m1.t.test1()
    #
    # from m1.t import test1,_test2
    #
    # test1()
    # _test2()
    
    import importlib
    
    m = importlib.import_module('m1.t') # 动态导入就是基于反射的
    
    print(m)
    m.test1()
    m.test2()
    
    '''
    动态导入模块方法1: __import__ 
    
    说明:
    
      1. 函数功能用于动态的导入模块,主要用于反射或者延迟加载模块。
    
      2. __import__(module)相当于import module
    
    举例说明:
    
    首先创建一个模块目录lib,然后在目录内创建一个模块为:aa.py
    
    模块代码为:
    
    class c(object):
        def __str__(self):
            return 'C language'
    在lib目录平级新建一个测试的模块,使用 __import__ 动态以字符串形式导入lib下的aa模块。
    
    lib = __import__('lib.aa') # 相当于import lib
    c = lib.aa.c()
    print(c)
    动态导入模块方法2:import importlib
    
    实例还是上面的lib.aa模块,这里使用importlib进行动态导入(这个方法好理解,也是官方建议使用的)
    
    import importlib
    aa = importlib.import_module('lib.aa')
    c = aa.c()
    print(c)
    '''
  • 相关阅读:
    android 打包错误
    mysql innoDB 挂了的临时解决方案
    android notification 传值关键
    maven eclipse 插件下载地址
    微信html5开发选哪一个
    android AsyncTask 只能在线程池里单个运行的问题
    关于Fragment 不响应onActivityResult的情况分析 (
    Android-BaseLine基础性开发框架
    linux网络流量实时监控工具之iptraf
    android 圆角按钮和按钮颜色
  • 原文地址:https://www.cnblogs.com/frx9527/p/python_attr.html
Copyright © 2020-2023  润新知