python之面向对象编程-自定义内置方法定制类的功能,元类

1.内置方法:

        __str__        打印自动触发

        __del__        删除对象之前自动触发

2.用于实例化产生类的类称之为元类

    __call__        调用对象时自动触发

    __new__        新建一个空对象

  __init__           调用类自动触发,初始化独有属性

1.__str__方法

    在对象被打印时,自动触发,应该在该方法内采集与对象slef有关的信息,然后拼成字符串返回

        def __str__(self):

               print('====>')

             return '<name:%s age:%s>' %(self.name,self.age)

    obj=People('egon',18)

    print(obj)

2.__del__析构方法

    __del__会在对象被删除之前自动触发

class People:                                                    

    def __init__(self,name,age):

        self.name=name

        self.age=age

        self.f=open('a.txt','r',encoding='utf-8')

    def __del__(self)                                                             #程序运行完毕,对象自动删除   

        print('==========>')                                           #对象被删除之前自动触发

       # self.f.close    #需要做回收操作系统资源相关的事情

obj=People('egon',18)

del obj

3.什么是元类

    在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象

    负责产生该对象的类称为之为元类,即元类可以简称为类的类

        class Foo:   #Foo=元类()            #把定义的类foo当初个对象来看

            pass

    元类是负责产生类的,所以我们学习元类或自定义元类的目的是为了控制类的产生过程(添加逻辑条件..)

    还可以控制对象的产生过程

1.储备知识:内置函数exec用法

    将字符串中的代码提取出来运行一次            

cmd="""

x=1 

y=2 

print('----->')"""

class_dic={}                          #相当于名称空间

exec(cmd,{},class_dic)        #将运行过程中执行的名字都丢在字典里了

print(class_dic)

exec用法:模拟类定义阶段造名称空间将类体代码执行过程中产生的名字丢进去

2.创建类的方法有两种

    大前提,如果说类也是对象,那么用class关键字创建类的过程也是一个实例化

    该实例化的目的是为了得到一个类,调用的就是元类

    方式1:用默认是元类 type

        

<strong># class People: #People=type(...)
#     country='China'
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#
#     def eat(self):
#         print('%s is eating' %self.name)

# print(type(People))            #把people看做对象的话,那么people的类是type type就是默认元类</strong>

  创建类的三个要素:类名,父类,类的 名称空间

    class 就是封装了一个功能

    class_name='People'

    class_bases=(object,)

    class_dic={}

    class_body="""

country='China'
def __init__(self,name,age):
    self.name=name
    self.age=age


def eat(self):
    print('%s is eating' %self.name)

"""

exec(class_body,{},class_dic)

创建类三要素:

class_name

class_bases

class_dic

People1=type(class_name,class_bases,class_dic)              #自己造出一个类

obj=people1(‘egon’,18)

obj.name

方式2:创建自定义的元类

<strong>class Mymeta(type):                      #只要继承了type类才能称之为元类,否者就是一个普通的自定义类

        def __init__(self,class_name,class_bases,class_dic)
            print(self) #现在是People
            print(class_name)
            print(class_bases)
            print(class_dic)
            super(Mymeta,slef),__init__(class_name,class_bases,class_dic) #重用父类的功能

        <span style="color:#ff0000">分析class运行原理</span>

       <span style="color:#ff0000"> 1.拿到一个字符串的类名 class_name='People'</span><span style="color:#ffcc00">
</span>
       <span style="color:#ff0000"> 2.拿到一个类的父类class_bases=(object,)</span>

        <span style="color:#ff0000">3.执行类体代码,拿到一个类的名称空间class_dic={.....}</span>

        <span style="color:#ff0000">4.调用People=type(class_name,class_bases,class_dic)</span>

class People(objeck,emtaclass=Mymate):           <span style="color:#ff0000">#把peopel当做个对象 peopel=Mymeta(类名,父类,类的名称空间)</span>

        country='China'
            def __init__(self,name,age):
                self.name=name
                self.age=age


            def eat(self):
                print('%s is eating' %self.name)


<span style="color:#ff0000"># 应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程</span></strong>

例:控制元类,添加逻辑条件

<strong>class Mymeta(type):                                         #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
    def __init__(self,class_name,class_bases,class_dic):
        if class_dic.get('__doc__') is None or len(class_dic.get('__doc__').strip()) == 0:
            raise TypeError('类中必须有文档注释,并且文档注释不能为空')
        if not class_name.istitle():
            raise TypeError('类名首字母必须大写')
        super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能

class People(object,metaclass=Mymeta): #People=Mymeta('People',(object,),{....})   #把people当做一个对象看待,元类设置有条件,对象必须遵循
    """这是People类"""
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def eat(self):
        print('%s is eating' %self.name)</strong>

__call__ 调用对象时自动触发

<strong>#3 储备知识:__call__         调用对象时自动触发
# class Foo:
#     def __call__(self, *args, **kwargs):
#         print(self)
#         print(args)
#         print(kwargs)
#
#
# obj=Foo()
#
# # 要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法
# # 该方法会在调用对象时自动触发
# obj(1,2,3,x=1,y=2)</strong>

# 4、自定义元类来控制类的调用的过程,即类的实例化过程

<strong>class Mymeta(type):

    def __call__(self, *args, **kwargs):
        # print(self) # self是People
        # print(args)
        # print(kwargs)
        # return 123

<span style="color:#ff0000">        # 1、先造出一个People的空对象</span>
        obj=self.__new__(self)
       <span style="color:#ff0000"> # 2、为该对空对象初始化独有的属性</span>
        # print(args,kwargs)
        self.__init__(obj,*args,**kwargs)

     <span style="color:#ff0000">   # 3、返回一个初始好的对象</span>
        return obj


class People(object,metaclass=Mymeta): #把peopel看做一个对象 上面描述的就是造出peopel的过程
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def eat(self):
        print('%s is eating' %self.name)

    def __new__(cls, *args, **kwargs):        
        print(cls)
        # cls.__new__(cls) # 错误
        obj=super(People,cls).__new__(cls)  #重用父类__init__方法 造出个对象obj
        return obj

# 分析:调用Pepole的目的
#1、先造出一个People的空对象
#2、为该对空对象初始化独有的属性
# obj1=People('egon1',age=18)
# obj2=People('egon2',age=18)
# print(obj1)
# print(obj2)

obj=People('egon',age=18)
print(obj.__dict__)
print(obj.name)
obj.eat()</strong>
原文地址:https://www.cnblogs.com/Marcki/p/10111939.html