面向对象高级A(反射,拦截方法)

一等公民:只要可以把一个东西赋值给一个变量,这个东西就叫一等公民

断点调试

在想要加断点的地方用鼠标点击一下,会看到一个红色圆圈

变红的地方,程序执行到,就会暂停

断点应该加在报错之前,在错误代码上放断点进行调试

向下绿色箭头是单步调试

右下角色绿色三角形是快速调到下一个断点执行

控制台报错,点击你能看懂的最后一行,光标会定位到错误代码

issubclass()

判断第一个类是不是第二个类的子类,返回true或者false

class Foo:
    pass

class Bar(Foo):
    pass

class Tt(Bar):
    pass

print(Tt.__bases__) #(<class '__main__.Bar'>,)
print(issubclass(Bar, Foo)) # True
print(issubclass(Tt, Foo)) # True

isinstance()

判断第一个参数是不是第二个参数的对象,返回True或者False

class Foo:
    pass
class Tt:
    pass
f = Foo()
print(isinstance(f, Foo)) # true
print(isinstance(f, Tt)) # false

反射

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

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

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

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

class Foo:
    def run(self):
        print('run')
    def speak(self):
        print('speak')
p = Foo()

cmd = input('请输入命令')

if hasattr(p, cmd):
    cmd1 = getattr(p, cmd)
    cmd1()
else:
    print('该命令不存在')
    
‘’‘
请输入命令:run
run

请输入命名:a
该命令不存在
’‘’

# 动态的加属性
class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person('nick', 19)
key=input('请输入key: ')
value=input('输入value: ')
setattr(p,key,value)
print(p.age)
print(p.__dict__)

'''
请输入key:nick
输入value:123
19
{'name': 'nick', 'age': 19, 'nick': '123'}
'''

# 动态的删属性
p.name = 'lqz'
p.age = 18
p.sex = 'male'
a = input('请输入要删除的属性: ')
print(p.__dict__)
delattr(p, a)
print(p.__dict__)
"""
请输入要删除的属性: sex
{'name': 'lqz', 'age': 18, 'sex': 'male'}
{'name': 'lqz', 'age': 18}
"""

# 动态的加方法
# 需要先写一个函数,然后通过setattr()往对象中加方法

def test(a):
    print(a)

print(p.__dict__)
setattr(p, 'test', test)
print(p.__dict__)
p.test(0) # 0

#模块也是对象,也可以用这四个方法

#内置模块
import os
print(hasattr(os, 'path1')) #False


#使用自己写的模块,通过反射来获取模块中是否有我要使用的属性或方法,如果有就执行,没有就报错

#这种方法可以用在:我想调用别人写的模块,但是我并不知道他写没写完,所以我需要用到hasattr先判断是否存在,存在的话用getattr拿到它,否则抛异常
'''
#别人写的,领导规定要写speak,run,eat方法
#这个人没写完
#utils.py

def speak():
    print('speak')


def run():
    print('run')
#这个人写完了
#def eat():
    print('eat')
    
#opera.py
import utils

if hasattr(utils, 'eat')
	eat = getattr(utils, 'eat')
	eat()
else:
	print('那个人还没写完呢')

# 那个人还没写完呢
'''


内置方法

__str__


class Foo:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return '['+self.name+']'

f = Foo('nick')
print(f) #print会按照__str__里面重写的格式进行打印
# print(f.__str__()) # 打印结果同上:  [nick]

l = [1, 2, 3]
print(l) # [1, 2, 3]本质也是调用list的__str__方法

点拦截方法

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

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

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

class Foo:
    def __init__(self, name):
        self.name = name # name没拿到值,要进入到__setarr__中,
        #  找到后打印出来name的值 'nick'
        print(name)
    def __getattr__(self, item):
        return '没有这个字段'
    def __setattr__(self, key, value):# key值是参数name,
        # value是值'nick'
        print(key)
        print(value)
    def __delattr__(self, item):
        print('zzzz')

f = Foo('nick') # 生成对象调用__init__方法,
print(f.name) #重写了__setattr__, 所以找不到name,这样就会进入__getattr__中



#######
#小例子#
#######

# 写一个类继承字典, 让他可以.取值,也可以中括号取值
class Mydict(dict):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
    def __getattr__(self, item):
        # pass
        return self[item]

di = Mydict(name = 'lqz', age = 18)
print(di['age'])
print(di.name) #点取值找不到,
# 会触发__getattr__,继承了字典,直接利用key返回value

[]中括号拦截

__item__系列, 对象通过[]中括号取值,赋值删除值的时候会调用

#实现机理和.拦截一样,只不过是对象
# 用中括号调用时会触发
class Foo:
    def __init__(self, name):
        self.name = name
    def __getitem__(self, item):
        name = getattr(self, item) # 通过反射
        # 拿到nick,并返回,这句话之后可
        # 以使用中括号进行取值
        return name
    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')
f['name'] = 'ljy'
del f['name']
# print(f.name)
print(f['name'])

()对象加小括号拦截

_call_

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

# xxxx
原文地址:https://www.cnblogs.com/michealjy/p/11454082.html