zoukankan      html  css  js  c++  java
  • python中面向对象元类的自定义用法

    面向对象中的常用方法

    1.instance 和 issubclass

    instance :判断两个对象是不是一类

    issubclass :判断某个类是不是另一个类的子类

    #两个常用方法的使用
    class Person:
        passclass Student(Person):
        pass
    ​
    stu = Student()
    print(isinstance(stu, Student))
    print(issubclass(Student,Person))
    True
    True  ##输出的结果是布尔值。

    2.反射

    反射,其实就是反省。简单来讲就是对象要具备一种修正错误的能力。

    #四种方法:
    hasattr      #判断是否存在属性
    getattr      #获取某个属性的值
    setattr      #设置某个属性的值
    delattr      #删除某个属性
    #这四种方法的共同点,都是通过字符串来操作属性,通过字符串操作。
    #示例:反射属性
    class Student:
        def __init__(self, name, sex, age):
            self.name = name
            self.age = age
            self.sex = sex
        def study(self):
            print('student is studying')
    deng = Student('deng', 'male', 25)
    #当我们获取一个对象,但是不清楚对象内部细节,就需要用反射。
    def test(obj):
        if hasattr(obj, 'name'):
            print(getattr(obj, 'name', "no 'name' attribute"))
    ​
    test(deng)
    ​
    #示例:反射方法
    #通过反射方法的方式为对象增加一个方法,但是注意,这样增加的方法就是一个普通函数,不会自动传值。
    res = getattr(deng, 'study', None)
    print(res)
    res()
    def run(obj):
        print('student is running')
    ​
    setattr(deng,'run',None)
    res1 = getattr(deng, 'run',None)
    run(deng)
    ​
    #deng
    #<bound method Student.study of <__main__.Student object at 0x00000272D8DB8C50>>
    #student is studying
    #student is running

    3._ _str _ _内置方法

    当我们需要自定义显示内容时,就需要实现 _ _str _ _方法

    #该方法必须返回一个字符串,返回是什么,打印出来就是什么。
    class Test:
        def __init__(self,name):
            self.name = name
        def __str__(self):
            print('str run...')
            return self.name
    ​
    t = Test('ming')
    print(t)

    其实,在我们将一个对象转换为字符串时,本质就是在调用这个对象的_ str _ _方法。

     

    4.  _ _del _ _内置方法

    该方法在对象(程序,文件,等等)被从内存中删除时会自动执行该方法。

    class Student:
        def __del__(self):
            print('对象被删除。。。')
    ​
    stu = Student()  #创建stu对象
    #当该stu对象创建完成后该程序就运行结束,就会运行del方法。
    #触发__del__有两种:
        1.程序自动运行结束
        2.手动删除,会立即执行__del__
    #示例:
    class Student:
        def __del__(self):
            print('对象被删除。。。')
    ​
    stu = Student()
    del stu     #在这就会打印,但这是程序并未结束
    import time
    time.sleep(5) 
    什么时候使用它
    在python中 有自动内存管理机制 所以 python自己创建的数据 不需要我们做任何操作
    但是有一种情况 我们使用python打开了一个不属于python管理的数据
    比如打开了一个文件  这个文件一定是操作系统在打开 会占用系统内存  而python解释器无法操作系统内存的
    所以 当你的python解释器运行结束后  文件依然处于打开状态  这时候就需要使用__del__来关闭系统资源
    ​
    简单地说 当程序运行结束时 需要做一些清理操作 就使用__del__
    ​
    __del__也称之为 析构函数
    ​
    分析构造 并拆除这个对象

     

    5.exec方法

    该方法是解析执行python代码(字符串类型) 并且将得到的名称 存储到制定的名称空间  解释器内部也是调用它来执行代码。解释器内部也是将代码看做字符串。

    该方法有三个参数:

    参数一    需要一个字符串对象, 表示需要被执行的python语句

    参数二    是一个字典,表示全局名称空间

    参数三    是一个字典,表示局部名称空间

    #示例:
    globals_dic = {}
    locals_dic = {}
    exec('''
    a = 1  
    if a >1: 
        print('ming') 
    else:
        print('deng')''', globals_dic, locals_dic)

    #注意:

    1.如果同时制定了全局和局部的,则会将字符串中包含的名称解析后存到局部名称空间。

    2.如果只传了一个传参数 则 将字符串中包含名称 解析后存到全局中。

     

    6.元类

    • 使用class可以发现,类其实是type类型的实例(对象)。

    • 一切皆对象

    • 元类是指 用于产生类的类  type就是元类

    class Student:
        def study(self):
            print('studying')
    print(type(Student))

    总结:

    1.类由type实例化产生

    2.我们可以使用type产生一个类

    3.一个类由类名,类的父类,类的名称空间组成。

    type类实例化可以得到类,类实例化可以得到对象。

     

    7._ _ call _ _ 内置方法

    _ _ call _ _调用的意思,在对象被调用的时候执行该方法(执行该对象所属的类)

    #示例:
    class Person:
        def __call__(self, *args, **kwargs):
            print('call  running')
    p = Person()   #创建对象不会执行call内置方法
    p()   # call  running  对象被调用时会自动执行该方法。
    自定义元类 的目的

    1.可以通过call 来控制对象的创建过程
    2.可用控制类的创建过程

    自定义一个元类(元类也是一个类),但该类需继承元类type。

    #1.通过__call__来控制对象的创建过程
    #1.创建一个元类(需要继承type)
    #2.覆盖__call__方法,会将正在实例化对象的类转化为传入的参数
    #3.在新的__call__方法中,需要按下面编写,然后再加你需要的控制逻辑即可。
    class MyMeta(type):
        #self表示创建对象的那个类,*args, **kwargs参数
        def __call__(self, *args, **kwargs):
            print('MyMeta中的call')
            #下面三步是固定的
            #1.创建对象
            obj = object.__new__(self)
            #2.调用初始化方法
            self.__init__(obj,*args,**kwargs)
            #3.得到一个完整的对象
            return obj
    #先修改Person的元类为MyMeta
    class Person(metaclass=MyMeta):
        def __init__(self,name ,age):
            self.name = name
            self.age = age
        def __call__(self, *args, **kwargs):
            print('call is running...')
    deng = Person('deng', 26)
    print(deng)
    deng()
    ####
    MyMeta中的call
    <__main__.Person object at 0x00000251588D89B0>
    call is running...
    ​
    ​
    #2.通过元类控制类的创建过程:
    #1.创建一个元类(需要继承type)
    #2.覆盖__init__方法,该方法会新建类的对象,类名,父类名,名称空间,可以利用这些信息做处理
    #3.对于需要控制的类,需要指定metaclass为上面元类
    class MyMeta(type):
        def __init__(self, class_name, bases, namespace):
            print('=======')
            #控制类名必须大写
            if not class_name.istitle():
                print('类名必须大写开头。。。')
                #该代码主动抛出异常
                raise TypeError('类名,开头必须大写开头。。。')
            if not self.__doc__:
                raise TypeError
            pass
    class Student(metaclass=MyMeta):
        '''
        这是文档注释,可以通过__doc__获取
        '''
        #在类的__init__中可以控制该类对象的创建过程
        def __init__(self, name):
            print('+++++++++++++')
            print(self.__doc__)
            self.name = name
    print(Student.__doc__)

    8.单例模式

    单例   一种设计模式

    单个对象,一个类如果只有一个实例,那么该类称之为单例

    为什么需要单例?

    class MyMeta(type):
        obj = None
        def __call__(self, *args, **kwargs):
            if not MyMeta.obj:
                obj = object.__new__(self)
                self.__init__(obj, *args, **kwargs)
                MyMeta.obj = obj
            return MyMeta.obj
    class Printer(metaclass=MyMeta):
        '''
        这是一个单例类,请不要直接实例化,使用get方法获取实例
        '''
        obj = None
        def __init__(self, name, type):
            self.name = name
            self.type = type
        def printing(self, text):
            print('正在打印%s' % text)
        @classmethod
        def get_printer(cls):
            if not cls.obj:
                obj = cls('ec001', 'sharp')
                cls.obj = obj
                print('创建新对象')
            return cls.obj
    ​
    p = Printer.get_printer()
    print(p.name)
    print(p)
    p1 = Printer('ming','002')
    print(p1.name)
    print(p1)

     

    总结:

    单例的优点:就是可以优化内存,减少重复对象的产生占用内存。

  • 相关阅读:
    PL/SQL快捷键
    <c:if>条件判断 和 取值做乘法运算
    文档保存后找不到了误以为丢失,重做!
    Gson将参数放入实体类中进行包装之后再传递
    [leedcode 66] Plus One
    [leedcode 65] Valid Number
    [leedcode 64] Minimum Path Sum
    [leedcode 63] Unique Paths II
    [leedcode 62] Unique Paths
    [leedcode 61] Rotate List
  • 原文地址:https://www.cnblogs.com/5j421/p/10147109.html
Copyright © 2011-2022 走看看