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__)  # {}

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

上一篇:类与面对对象编程


下一篇:面向对象编程