zoukankan      html  css  js  c++  java
  • issubclass和isinstance,反射,内置方法

    面向对象进阶

    一、issubclass 和 isinstance

    1.1 issubclass

    issubclass()

    作用:用来判断括号内的第一个类是不是第二个类的子类,返回结果为True或False。

    例如:

    class A:
        pass
    class B(A):
        pass
    class C:
        pass
    
    print(issubclass(B,A))  # True
    print(issubclass(C,A))  # False
    
    

    1.2 isinstance

    isinstance()

    作用:用来判断括号内第一个参数是不是第二个参数的对象,返回结果为True或False。

    例如:

    class A:
    	pass
    class B:
        pass
    
    a = A()
    print(isinstance(a,A))  # True
    print(isinstance(a,B))  # False
    

    二、反射

    2.1 什么是反射

    通过字符串来判断、获取、设置、删除对象(包括类、模块等,一切皆对象)中的属性或方法。

    2.2 四个可以通过字符串操作对象属性和方法的内置函数

    四个函数括号里的第一个参数都是对象

    hasattr(): 判断一个属性是否在对象中,返回True或者False

    getattr(): 通过字符串获取属性或方法,如果获取到了,就会返回相应的属性或方法

    setattr(): 通过字符串来设置属性或方法

    delattr(): 通过字符串来删除属性或方法

    2.2.1 hasattr()

    判断一个属性是否在对象中,第一个参数是对象,第二个参数是属性,返回True或False

    class Foo:
        def run(self):
            print('run')
        def speak(self):
            print('speak')
    
    p=Foo()
    cmd=input('请输入命令:')
    if hasattr(p,cmd):  # 先判断属性cmd是否在对象p中
        run=getattr(p,cmd)   # 如果输入run,该属性或方法就在对象p中,就会返回,加括号就可以调用
        run()
    else:
        print('该命令不存在')  # 输入的属性不在对象中的话,就执行这步
    

    2.2.2 getattr()

    通过字符串获取属性或方法,如果获取到了,就会返回相应的属性或方法,用法在上面的代码里已经写了

    2.2.3 setattr()

    1、通过用户输入key和value往对象中赋值

    class Foo:
        def run(self):
            print('run')
        def speak(self):
            print('speak')
    
    p=Foo()
    key=input('请输入key:')  # 输入age
    value=input('输入value:')  # 输入18
    setattr(p,key,value)  # 将{'ag':'18'}赋值给对象p
    print(p.age)  # 18
    

    2、动态的往对象中放方法

    class Foo:
        def run(self):
            print('run')
        def speak(self):
            print('speak')
    
    p=Foo()
    def test(a):
        print(a)
    print(p.__dict__)  # {}
    setattr(p,'test',test)  
    print(p.__dict__)  # {'test': <function test at 0x000001DF69C81E18>}
    p.test(0) # 0
    

    2.3.4 delattr()

    动态删除对象p中属性为变量a的属性

    class Foo:
        def run(self):
            print('run')
        def speak(self):
            print('speak')
    
    p=Foo()
    p.name='lqz'
    p.age=18
    p.sex='male'
    a=input('请输入要删除的属性:')  # 输入sex
    print(p.__dict__)  # {'name': 'lqz', 'age': 18, 'sex': 'male'}
    delattr(p,a)   #把属性sex删除
    print(p.__dict__)  # {'name': 'lqz', 'age': 18}
    # 直接p.a是不对的
    # del p.a  这个会报错
    

    三、内置方法

    之前学过__init__

    3.1 __str____repr__

    1、__str__:如果不重写__str__,print打印会打印出内存地址,如果重写了,会打印出你想要的

    2、__repr__:和__str__类似,在交互式命令下直接写变量名,会执行__repr__

    class Foo:
        def __init__(self,name):
            self.name=name
        def __str__(self):
            return '['+self.name+']'
    
    f=Foo('nick')
    print(f.__str__())  # [nick]
    print(f)     #相当于上面那句  # [nick]
    l=[1,2,3]
    #本质也是已经调用list的__str__方法
    print(l)
    

    3.2 点拦截方法:__setattr__,__delattr__,__getattr__

    如果去对象中获取属性,一旦取不到,会进入到__getattr__

    如果去对象中赋值属性,一旦取不到,会进入到__setattr__

    如果删除对象中的属性,会进入__delattr__

    class Foo:
        def __init__(self,name):
            self.name=name
        def __getattr__(self, item):
            # print('xxxx')
            return '你傻逼啊,没有这个字段'
        def __setattr__(self, key, value):
            print('yyyyy')
        def __delattr__(self, item):
            print('zzzzz')
    f=Foo('nick')  # 给对象f赋值属性,对象中没有这个属性,进入到__setattr__方法  # yyyyy
    print(f.name)  # 获取name属性,对象中没有属性,进入__getattr__方法  # 你傻逼啊,没有这个字段
    print(f.age)   # 没有age属性,进入__getattr__方法  # 你傻逼啊,没有这个字段
    print(f.__dict__)   # {}
    print(f.name)  # 没有name属性,进入__getattr__方法  # 你傻逼啊,没有这个字段
    f.sex='male'   # 给对象f赋值属性,对象中没有sex这个属性,进入到__setattr__方法  # yyyyy
    
    del f.name    # 删除对象name属性,对象中没有这个属性,进入__delattr__方法  # zzzzz
    print(f.__dict__)  # {}
    

    应用举例

    写一个类继承字典,让它可以.取值,.赋值,中括号取值

    class Mydict(dict):
        def __init__(self,**kwargs):   # 这个方法可以不写,实例化的时候会自动调用父类dict的__init__方法0.
            super().__init__(**kwargs)   # super关键字继承字典的属性和方法
    	
        def __getattr__(self, item):
    		# a = self[item]
    		# return a 
            return self[item]  # 相当于上面两行作用
        def __setattr__(self, key, value):
            self[key]=value
    
    di=Mydict(name='lqz',age=18)  # 自动调用__init__方法,**kwargs接收传入的两个关键字实参
    print(di['name'])  # 中括号取值,跳到__getattr__方法
    print(di.name)     # .取值 
    di.sex='male'      # .赋值 ,进入__setattr__方法
    di['sex']='male'   # 中括号赋值 ,进入进入__setattr__方法
    

    3.3 __item__

    对象通过[] 中括号取值、赋值、删除值得时候会调用__item__方法

    class Foo:
        def __init__(self, name):
            self.name = name
        def __getitem__(self, item):
            name=getattr(self,item)
            # print(name)
            # print(self.__dict__[item])
            return name
            # return self.__dict__[item]
        def __setitem__(self, key, value):
            print('obj[key]=lqz赋值时,执行我')
            self.__dict__[key] = value
        def __delitem__(self, key):
            print('del obj[key]时,执行我')
            self.__dict__.pop(key)
    f=Foo('nick')
    print(f['name'])
    

    3.4 __call__

    对象加括号会调用它

    class Foo:
        def __call__(self):
            print('xxxx')
    
    f=Foo()
    f()  # xxxx
    

    3.5 __enter____exit__

    with管理上下文的本质

    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
            # return self
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        # print(f,f.name)
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    
    • exit()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
    
    
    try:
        with Open('a.txt') as f:
            print('=====>执行代码块')
            raise AttributeError('***着火啦,救火啊***')
    except Exception as e:
        print(e)
    

    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'>
    着火啦,救火啊
    <traceback object at 0x1065f1f88>
    着火啦,救火啊

    • 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
            return True
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        raise AttributeError('***着火啦,救火啊***')
    print('0' * 100)  #------------------------------->会执行
    

    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'>
    着火啦,救火啊
    <traceback object at 0x1062ab048>
    0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

  • 相关阅读:
    MySQL索引管理及执行计划
    MySQL客户端工具及SQL讲解
    mysql数据类型
    mysq日志管理
    mysql连接管理及实例初始化配置
    mysql用户权限管理
    msyql5.6与mysql5.7安装区别
    mysql简介
    ASP.NET使用ImageMap控件
    ASP.NET Calendar(日历控件)
  • 原文地址:https://www.cnblogs.com/zhuangyl23/p/11449534.html
Copyright © 2011-2022 走看看