反射

1.反射

反射指的是一个对象应该具备可以检测,修改,增加自身属性的能力。反射可以通过字符串操作属性,共涉及到四个属性,这四个函数就是普通的内置函数,没有双下划线,与print等等没有区别。

# hasattr  getattr  setattr  delattr的用法
class Person:
    def __init__(self,name,age,gender):
        self.name =name
        self.age = age
        self.gender = gender

p = Person('li',18,',man')
# print(p.age)      # >>>:18
# print(hasattr(p,'name'))    # >>>:True 判断某个对象是否存在某个属性
if hasattr(p,'name'):
    print(getattr(p,'name',None))
#从对象中取出属性,第三个值为默认位,当属性不存在时就返回出默认值

#为对象添加新的属性
setattr(p,"id",'91')
print(p.id)

# 从对象里面删除属性
delattr(p,"id")
delattr(p,'age')
print(p.__dict__)#里面中的id,age属性被删除了
# >>>:{'name': 'li', 'gender': ',man'}

  使用场景:反射其实就是对属性的增删改查,如果直接使用__dict__来操作,语句繁琐,不好理解。另外一个最主要的问题是,如果对象不是自己写的,而是第三方提供的,我就必须判断这个对象是否满足我需要的属性和方法。

2.元类 metaclass

元类是用来创建类的类,把要创建的类看成是元类的对象。对象是通过是通过实例化产生的,如果类也是对象的话,必然类对象也是由另一个类实例化产生的。默认情况下所有类的元类都是type。

只要继承了type,那么这个类就变成了一个元类。

#自己直接定义的一个元类
class
MyType(type): def __init__(self,class_name,bases,dict): super().__init__(class_name,bases,dict) print(class_name,bases,dict) if not class_name.istitle(): raise Exception("类名格式不对") class Duck(metaclass=MyType): # 为duck类指定了元类为MyType pass
>>>:Duck () {'__module__': '__main__', '__qualname__': 'Duck'}

3.元类中的call方法

  当你调用累对象时会自动调用元类中的__call__方法,并将这个类本身作为第一个参数传入,以及后面的一堆差数。当覆盖元类中的call之后,这个类就无法产生对象,必须调用super().__call__来完成对象的创建。

  使用场景:当你想要控制对象的创建过程时,就覆盖call方法;当你想要控制类的创建过程时,就覆盖init方法。

# 实现将对象的所有属性名称转大写
class MyType(type):
    def __call__(self, *args, **kwargs):
        new_args = []
        for a in args:
            new_args.append(a.upper())

        print(new_args)
        print(kwargs)
        return super().__call__(*new_args,**kwargs)


class Person(metaclass=MyType):
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender

p = Person("jack""woman")
print(p.name)#>>>:JACK
print(p.gender)#>>>:WOMAN
注意:一旦覆盖了call必须要调用父类的call方法来产生对象并返回这个对象。
原文地址:https://www.cnblogs.com/blue-tea/p/11272230.html