• 反射,__setattr__,__getattr__,__delattr__


    1.isinstance用法

    isinstance(x,y):用于判断x是不是y类型的数据,返回布尔值

               判断x对象是不是由y这个类实例化的

    a="egon"
    class People:
        def walk(self):
            print("walking")
    
    p=People()
    isinstance(a,str)
    res=isinstance(p,People)
    print(res)

    2.issubclass用法

    issubclass(x,y):用于判断x是不是y的子类,返回布尔值

    class Anmail:
        def __init__(self,an_type):
            self.name=an_type
    
        def walk(self):
            print("walking")
    
    class People(Anmail):
        def __init__(self,name):
            self.name=name
    
    print(issubclass(People,Anmail))

    3反射(hasattr,setattr,getattr,delattr)用法

    hasattr(x,“name”)判断x中是否含有字符串name属性或者方法

    判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
    需要注意的是name要用括号括起来

    x:可以是类,可以是对象

    y:属性的变量名

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    
    p=People("egon","20","")
    
    print(hasattr(p,"name"))      #True
    print(hasattr(p,"walk"))      #True

    setattr(x,"name",value)把x对象中字符串name(属性)的值修改为value

    给对象的属性赋值,若属性不存在,先创建再赋值。

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    
    p=People("egon","20","")
    
    print(setattr(p,"name","alex"))           #p.name=alex
    print(setattr(p,"walk","zou"))            #{'sex': '男', 'name': 'alex', 'walk': 'zou', 'age': '20'}

    getattr(x,"name",None)

    获取到x中name的属性,如果name是数据属性则返回的是一个值,如果name是一个方法则返回一个内存name的内存地址

    多加参数None表示,如果x中没有name属性,不会报错,会返回一个None值

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    
    p=People("egon","20","")
    
    
    print(getattr(p,"name"))             #egon
    print(getattr(p,"walk"))             #<bound method People.walk of <__main__.People object at 0x000001FCE4FFFBA8>>
    getattr(p,"walk")()                  #======>walking

    delattr(x,"name")

    删除x中name的数据属性,不能删name的方法

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    
    p=People("egon","20","")
    
    delattr(p,"name")
    print(p.__dict__)           #{'sex': '男', 'age': '20'}

    4__setattr__,__getattr__,__delattr__的用法

    __setattr__

    `__setattr__`函数是用来设置对象的属性,通过object中的__setattr__函数来设置属性:

    class People:
        def __init__(self,name,age,sex):
            self.name=name             #走到self.name的时候就会先执行__setattr__,self.name表示self.__dict__[name]
            self.age=age
            self.sex=sex
    
        def __setattr__(self, key, value):
            if not isinstance(value,str):    #可实现在实例化的时候定制一套规则,必须是什么样的数据类型
                raise TypeError("参数必须是字符串")
            self.__dict__[key]=value   #往字典__dict__中加入属性key=value
    
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    
    p=People("egon",20,"")          #报错
    p=People("egon","20","")        #正常

    __getattr__

    从对象中读取某个属性时,首先需要从self.__dicts__中搜索该属性,再从__getattr__中查找,如果类中没有对象调用的属性时,就会执行__getatter__这个函数

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def __getattr__(self, item):  #如果类中没有对象调用的属性时,就会执行这个函数
            print("没有这个属性")
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    p=People("egon","20","")
    p.drink                        #没有这个属性

    __delattr__

    `__delattr__`函数式用来删除对象的属性:

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def __delattr__(self, item):      #找到self.__dict__[item],删除
            #self.__dict__.pop(item)
            del self.__dict__[item]
    
    
        def walk(self):
            print("======>walking")
    
        def eat(self):
            print("======>eatting")
    p=People("egon","20","")
    del p.name
    print(p.__dict__)                   #{'sex': '男', 'age': '20'}

    5 定制自己的数据类型:

    1.继承的方式

    #用继承的方式定制一个新list的方法
    class List(list):
        def append(self, object):             #派生出自己新的append功能,可以添加一个验证追加元素的必须是字符串
            if not isinstance(object,str):
                raise TypeError("追加的必须是字符串")
            super().append(object)            #super()只能使用到该类的上一级
    
    l=List([7,8,9])
    l.append("s")                             #正常
    # l.append(5)                             #报错
    l.insert(0,4)                             #由于是继承的关系,可继续使用list的所有功能

    2.授权的方式

    #用授权的方式来自制一个日志的记录文件
    """
    思路:日志文件必须包括日期,使用者全部记录到一个文件中
    方法:先获取到文件的句柄,把句柄当做一个对象来操作
    """
    
    import time
    
    class Open:
        def __init__(self,name,mode="r",encoding="utf-8"):
            self.name=name
            self.mode=mode
            self.encoding=encoding
            self.x=open(name, mode=mode, encoding=encoding)
    
        def write(self,line):
            t=time.strftime("%Y-%m-%d %x")
            self.x.write("%s %s"%(t,line))
            self.x.flush()
    
        def __getattr__(self,item):
            print("zhao budao gongnege")
            if not hasattr(self.x,item):
                print("没有%s功能"%item)
            else:
                print(item)
                return getattr(self.x,item)
    
    f=Open("log.log","w",encoding="utf_8")
    f.write("22222222")

    6 通过字符串导入模块

    通过__import__导入(官方不推荐使用)

    #输入time
    m=input("请输入需要导入的模块:")
    model=__import__(m)
    print(model.time())

    推荐使用

    import importlib
    t=importlib.import_module("time")
    print(t.time())

    7 练习

    # 基于授权定制自己的列表类型,要求定制的自己的__init__方法,
    class List:
        def __init__(self,*args):
            self.x=list(*args)
    
        def __str__(self):
            return str(self.x)
    # 定制自己的append:只能向列表加入字符串类型的值
        def append(self, object):
            if not isinstance(object, str):
                raise TypeError("必须追加字符串类型的数据")
            return self.x.append(object)
    
    # 定制显示列表中间那个值的属性(提示:property)
        @property
        def middle(self):
            n=int(len(self.x)/2)
            return self.x[n]
    
    # 其余方法都使用list默认的(提示:__getattr__加反射)
        def __getattr__(self, item):
            if not hasattr(self.x,item):
                print("没有%s方法"%(item))
            else:
                return getattr(self.x,item)
    
    l=List((1,2,4,5))
    l.append("2")
    print(l)
    res=l.middle
    print(res)
    

      

     
  • 相关阅读:
    利用事件委托实现用户控件中的行为触发所在页面的处理函数
    mootools系列:打造属于你自己的Popup(弹出框)——基本结构篇
    mootools系列:打造属于你自己的Popup(弹出框)——外观及应用篇
    所见即所得的Excel报表生成(二)——从Html table到Excel Cell
    Excel操作服务器端配置
    顺丰单号生成规则
    代理模式Proxy
    解释器模式Interpreter
    线性表
    总有一款合适的框架
  • 原文地址:https://www.cnblogs.com/amiee-785563694/p/6757024.html
Copyright © 2020-2023  润新知