博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python中面向对象元类的自定义用法
阅读量:4995 次
发布时间:2019-06-12

本文共 5147 字,大约阅读时间需要 17 分钟。

面向对象中的常用方法

1.instance 和 issubclass

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

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

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

 

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#
>#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 timetime.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的元类为MyMetaclass 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        passclass Student(metaclass=MyMeta):    '''    这是文档注释,可以通过__doc__获取    '''    #在类的__init__中可以控制该类对象的创建过程    def __init__(self, name):        print('+++++++++++++')        print(self.__doc__)        self.name = nameprint(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.objclass 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)

 

 

总结:

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

转载于:https://www.cnblogs.com/5j421/p/10147109.html

你可能感兴趣的文章
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
查看>>
电话录音系统说明书
查看>>
JVM(1)——IDEA启动分配内存大小及GC日志打印
查看>>
oracle 批量更新之update case when then
查看>>
text3
查看>>
自己写的连击文字特效
查看>>
【Android】eclipse打不开的解决办法和“Jar mismatch! Fix your dependencies”的解决
查看>>
Mysql查询某字段值重复的数据
查看>>
Java 自学笔记-基本语法3setOut()方法设置新的输出流
查看>>
cocos2d-JS 模块 anysdk 概述
查看>>
docker镜像mac下保存路径
查看>>
docker使用 命令
查看>>
关于C#操作INI文件的总结
查看>>
ZeptoLab Code Rush 2015 B. Om Nom and Dark Park
查看>>
ctci1.2
查看>>
[译]RabbitMQ教程C#版 - 路由
查看>>
升级项目到.NET Core 2.0,在Linux上安装Docker,并成功部署
查看>>
调用API函数减少c#内存占用(20+m减至1m以下)
查看>>
Android:onNewIntent()触发机制及注意事项
查看>>
珠宝公司之感想
查看>>