python学习第二十四天:反射内置方法元类

补充内置函数

isinstance(obj,Foo)   # 判断obj是不是foo的实例

issubclass()      # 判断一个类是不是另一个类的子类

反射

         什么是反射?

                  通过字符串来操作类或者对象的属性

         怎么用?

                  hasattr(adj,’xxx’) 判断adj有没有’xxx’属性

                  getattr(adj,’xxx’,None) adj有’xxx’就返回adj.xxx,没有则返回None,若不指定第三个                                 参数,没有则会报错

                  setattr(adj,’age’,18) adj.age = 18

                  delattr(adj,’age’) def adj.age

内置方法

       def __str__(self):在对象被打印时,自动触发,应该在该方法内采集与对象有关的信息并return,当print(adj)是会打印__str__(self)中的return值

         def __del__(self) 析构方法,对象被删之前自动触发

元类

         什么是元类?

                  python中一切皆对象,用class定义的类本身也是一个对象,负责产生该类对象的类称为元类

         为何用元类?

                  元类可以负责产生类,进而控制类的产生还可以控制对象的产生

         如何用元类?

                  ①储备知识:

                  exec()

                  参数一:字符串形式的命令

                  参数二:全局作用域(字典形式),如果不指定,默认为globals()

                  参数三:局部作用域(字典形式),如果不指定,默认为locals()

                           可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中

创建类的三个要素:类名,父类,类的名称空间
#类名
class_name='Chinese'
#类的父类
class_bases=(object,)
#类的名称空间
class_dic = {}
#类体
class_body="""
country='China'
def __init__(self,name,age):
    self.name=name
    self.age=age
def talk(self):
    print('%s is talking' %self.name)
"""
exec(class_body,{},class_dic)
People = type(class_name,class_bases,class_dic)  # 实例化类

class运行原理:

1.拿到一个字符串形式的类名

2.拿到类的基类们

3.执行类体代码,拿到类的名称空间

4.调用type()再赋值给变量名

 

应用:自定义元类控制类的产生过程,其实就是调用元类的过程 

#如果说People=type(类名,类的父类们,类的名称空间),那么我们定义元类如下,来控制类的创建
class Mymeta(type):  # 继承默认元类的一堆属性
    def __init__(self, class_name, class_bases, class_dic):
        if '__doc__' not in class_dic or not class_dic.get('__doc__').strip():
            raise TypeError('必须为类指定文档注释')

        if not class_name.istitle():
            raise TypeError('类名首字母必须大写')

        super(Mymeta, self).__init__(class_name, class_bases, class_dic)


class People(object, metaclass=Mymeta):
    country = 'China'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print('%s is talking' % self.name)


#自定义元类,控制类的调用(即实例化)的过程
class Mymeta(type): #继承默认元类的一堆属性
    def __init__(self,class_name,class_bases,class_dic):
        if not class_name.istitle():
            raise TypeError('类名首字母必须大写')

        super(Mymeta,self).__init__(class_name,class_bases,class_dic)

    def __call__(self, *args, **kwargs):
        #self=People
        print(self,args,kwargs) #<class '__main__.People'> ('egon', 18) {}

        #1、实例化People,产生空对象obj
        obj=object.__new__(self)

        #2、调用People下的函数__init__,初始化obj
        self.__init__(obj,*args,**kwargs)

        #3、返回初始化好了的obj
        return obj

class People(object,metaclass=Mymeta):
    country='China'

    def __init__(self,name,age):
        self.name=name
        self.age=age

    def talk(self):
        print('%s is talking' %self.name)

obj=People('egon',18)
print(obj.__dict__) #{'name': 'egon', 'age': 18}

猜你喜欢

转载自www.cnblogs.com/luck-L/p/9244953.html