反射的内置方法

内置方法

__str__

1.如果不重写__str__ return会打印出内存地址

2. print() 打印的时候, 会自动触发该函数的执行

如果重写了,会打印出你想要的

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

__repr____str__ 类似,但它是在交互式命令下直接写变量名,会执行__repr__ (了解)

image-20231020154647051

小结:

str函数或者print函数调用的是obj.__str__()

repr函数或者交互式解释器调用的是obj.repr__()

注意:

如果__str__没有被定义, 那么就会使用__repr__来代替输出

__str__和__repr__方法的返回值都都必须是字符串

重要( __setattr__ , __delattr__, __getattr__ : 对象加 (.)点 就会触发)

__getattr__ : 如果去对象中取属性,一但取不到,会进入__getattr__; 对象加 (.) 赋值或修改值会触发

__setattr__ : 如果去对象中赋值属性,一但取不到,会进入__setattr__ ; 对象加 (.) 获取值, 如果取不到, 会触发

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

# 点拦截方法
class Foo:
    def __init__(self, name):
        self.name = name

    def __getattr__(self, item):
        print('hhhh')
        return '你沙雕啊,没有这个字段'
   	
    def __setattr__(self, key, value):
        print('yyyy')
       
    def __delattr__(self, item):
        print('bbbb')


f = Foo('nick')
print(f.name)
print(f.age)
print(f.__dict__)
print(f.name)
f.sex='male'

def f.name
print(f.__dict__)		# 会发现没删掉

字典继承例子

# 原来的字典使用方法
di = dict(name='hys', age=17)
print(di)

# 写一个类继承字典, 可以让他(.)取值, 也可以括号取值
class Mydict(dict):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
       
    def __getattr__(self, item):
        print(item)
        return self[item]
    
    def __setattr__(self, key, value):
        self[key] = value
       
di = Mydict(name='hys', age=16)
# 取值的两种方法
print(di['name'])
print(di.age)
# 赋值的两种方法
di.like='milk'
print(di.like)
di['sex']='male'
print(di.sex)

例子总结:虽然他本质上也是,但是在这里我就能控制这些过程

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

class Foo:
    def __init__(self,name):
        self.name=name

    def __getitem__(self, item):
        # 一般用这种反射的方式, 但实际这两个意思是一样的
        name = getitem(self, item)
        return name
        # 一般不会用这种方式
        return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
         
f1=Foo('sb')
# 当我取值的时候, 会触发__getitem__方法
f1['age']=18
# 当我赋值时,会触发__setitem__方法
f1.age1=19
# 当我删除值的时候,会触发__delitem__方法
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)

__call__ 对象加括号 或 类加括号会调用它

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

__ enter__和__exit__

# 上下文管理器, 本质原理;  with 顶头写会自动调用__exit__方法
with open() as f:
    pass

递归问题

class Foo():
    def __init__(self, name):
        self.name = name
       
    def __setattr__(self, key, value):
        print('xxxx')
        # 这种方法有问题!	会到达递归的最大深度
        setattr(self, key, value)
       
    def __getattr__(self, item):
        return '没有值'		# 因为是取不到才跳到这里, 所以再写个反射还是取不到
   
f = Foo('nick')
posted @ 2023-10-30 11:36  hanyingshuo  阅读(19)  评论(0)    收藏  举报