反射 元类

1.反射 reflect

反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力

反射就是通过字符串操作属性

涉及四个普通的内置函数,没有双下划线,

hasattr    getattr     setattr      delattr

class Person:
    def __init__(self,name,age,male):
        self.name = name
        self.age = age
        self.male = male
p = Person(‘jack‘,18,‘man‘)
if hasattr(p,"name"):     # 判断某个对象是否存在某个属性
    print(getattr(p,‘name‘,None))    # jack  # 从对象中取出属性,第三个值位默认值 当属性不存在是返回默认值
setattr(p,‘id‘,‘123‘)
print(p.id)          #123
delattr(p,‘id‘)
print(p.id)

使用场景:

反射其实就是对属性的增删改查,但是如果直接使用内置的dict来操作,语法繁琐,不好理解

另外一个最主要的问题是,如果对象不是我自己写的是另一方提供的,我就必须判断这个对象是否满足的要求,也就是是否我需要的属性和方法

框架代码:

反射被称为框架的基石,为什么
因为框架的设计者,不可能提前知道你的对象到底是怎么设计的
所以你提供给框架的对象 必须通过判断验证之后才能正常使用
判断验证就是反射要做的事情,
当然通过__dict__也是可以实现的, 其实这些方法也就是对__dict__的操作进行了封装
需求:要实现一个用于处理用户的终端指令的小框架
框架就是已经实现了最基础的构架,就是所有项目都一样的部分

import importlib
import settings
def run(plugin):
    while True:
        cmd = input(‘请输入指令‘).strip()
        if cmd == ‘exit‘:
            break
        if hasattr(plugin,cmd):  # 取出对应方法
            func = getattr(plugin,cmd)
            func()
        else:
            print(‘该指令不支持‘)
    print(‘see you la la‘)
path = settings.CLASS_PATH
module_path,class_name = path.rsplit(‘.‘,1)  # 从配置中单独拿出来 模块路径和 类名称
mk = importlib.import_module(module_path)   #拿到模块
cls = getattr(mk,class_name)  # 拿到类
obj = cls()  # 实例化对象
run(obj)   #调用框架

settings 文件里的代码为    CLASS_PATH = ‘plugins.LinuxCMD‘
plugins 文件里的代码class WinCMD:    def cd(self):        print(‘wincmd 切换目录‘)    def delete(self):        print(‘wincmd 删文件‘)    def dir(self):        print(‘wincmd 列出文件‘)class LinuxCMD:    def cd(self):        print(‘Linuxcmd 切换目录‘)    def rm(self):        print(‘Linuxcmd 删文件‘)    def ls(self):        print(‘Linuxcmd 列出文件‘)
class Person(object):
    name = ‘123‘
p = Person()
print(type(p))    # <class ‘__main__.Person‘>
print(type(Person))   <class ‘type‘>

直接调用type类来产生类对象

一个类的三个基本组成部分

1.类的名字  2.类的父类们   3.类的名称空间

cls_obj = type(‘dog‘,(),{})print(cls_obj)   #    <class ‘__main__.dog‘>

元类 metaclass

用于创建类的类, 对象是通过类实例化产生的,如果类也是对象的话,必然类对象也是有另一个类实例化产生的

默认情况下所有类的元类都是type

学习元类的目的:

高度的自定义一个类,例如控制类的名字必须以大驼峰的方式来书写

类也是对象,也有自己的类,

我们的需求是创建类对象做一些限制

想到了初始化方法 我们只要找到类对象的类(元类),覆盖其中 init方法就能实现需求

当然我们不能修改源代码,所以应该继承type来编写自己的元类,同时覆盖init来完成需求

class MyType(type):    # 定义了一个元类
    def __init__(self,clss_name,bases,dict):
        super().__init__(clss_name,bases,dict)
        if not clss_name.istitle():
            raise Exception(‘类名有误‘)
class Pig(metaclass = MyType):    # 为pig类指定了元类为MyType
    pass
class MyType(type):
    def __call__(self, *args, **kwargs):
        new_args = []
        for a in args:
            new_args.append(a.upper())
        print(new_args)   # [‘HAHA‘]
        print(kwargs)    # {‘name‘: ‘jack‘, ‘gender‘: ‘woman‘}
        return super().__call__(*new_args,**kwargs)
class Person(metaclass=MyType):
    def __init__(self,*args,name,gender):
        self.name = name
        self.gender = gender
p = Person(‘haha‘,name="jack",gender="woman")
print(p.name)   #jack
print(p.gender)   #woman
要求创建对象时,必须以关键字参数形式传参覆盖元类的__call__判断你有没有传非关键字参数 == 不能有位置参数, 有就炸class Mate(type):
    def __call__(self, *args, **kwargs):
        if args:
            raise Exception(‘不允许使用位置参数‘)
        return super().__call__(*args,**kwargs)
class A(metaclass=Mate):
    def __init__(self,name):
        self.name = name
a = A(name=‘jack‘)
print(a.name)   # jack

元类中call方法

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

使用场景:

当你想要控制对象的创建过程时,就覆盖call方法

当你想要控制类的创建过程时,就覆盖init方法

补充new方法

当你要创建类对象时,会首先执行元类中的__new__方法,拿到一个空对象,然后会自动调用__init__来对这个类进行初始化操作  
注意:,如果你覆盖了该方法则必须保证,new方法必须有返回值且必须是,对应的类对象

class Meta(type):
    def __new__(cls, *args,**kwargs):
        obj = type.__new__(cls,*args,**kwargs)
        return obj
    def __init__(self,a,b,c):
        super().__init__(a,b,c)
        print(‘init run‘)
class A(metaclass=Meta):    # init run
    pass
print(A)    #  <class ‘__main__.A‘>
class Single(type):
    def __call__(self, *args, **kwargs):
        if hasattr(self,‘obj‘):    #判断是否存在已经有的对象
            return getattr(self,‘obj‘)
        obj = super().__call__(*args,*kwargs)  # 没有则创建
        print(‘new 了‘)
        self.obj = obj   # 并存入类中
        return obj
class Studenet(metaclass= Single):
    def __init__(self,name):
        self.name = name
class Person(metaclass=Single):
    pass
Person()
Person()

单例设计模式: 指的是一个类产生一个对象

为什么要使用单例:单例是为了节省 资源,当一个类的所有对象属性全部相同时,则没有必要创建多个对象

原文地址:https://www.cnblogs.com/zrh-960906/p/11272786.html

时间: 2024-11-08 14:05:37

反射 元类的相关文章

Python第二十一课(反射/元类)

Python第二十一课(反射/元类)    >>>思维导图>>>中二青年 反射reflect 什么是反射, 其实是反省,自省的意思 反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力 反射就是通过字符串操作属性 涉及的四个函数,这四个函数就是普通的内置函数 没有双下划綫,与print等等没有区别 hasattr getattr setattr delattr p = Person("jack",18,"man") #

7.28 多态 反射 元类

多态 1.什么是多态 多态指的是一类事物有多种形态 例如: 动物有多种形态: 人,狗,猪 在程序中多态指的是,不同对象可以响应相同方法,并可以有自己不同的实现方式 2.为什么需要多态 案例分析: import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): prin

OOP 反射&amp;元类

面向对象 反射:reflect,可以理解为自省的意思 反射是指一个对象应该具有自我检测.修改.增加自身属性的能力 反射就是通过字符串操作属性 涉及到的函数:hasattr & getattr & setattr & delattr hasattr(对象,'属性名'):判断某个对象是否存在某个属性 getattr(对象,'属性名',None):从对象中取出属性     第三个值位默认值,当属性不存在是返回默认值 setattr(对象,'属性名','属性对应的值'):为对象设置添加新的

QObject提供了QMetaObject元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化

元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化其中元类又提供了:classInfo,className,构造函数,多重祖先元类,method, property, Enumerator, Signal, Slot等等 http://doc.qt.io/qt-5/qobject.html http://doc.qt.io/qt-5/qmetaobject.html 我感觉Qt的出现,除了提供GUI以外,主要就是提

Python基础- 类和对象(使用、继承、派生、组合、接口、多态、封装、property、staticmethod、classmethod、反射、slots、上下文管理协议、元类)

标签: python对象 2017-07-01 16:28 79人阅读 评论(0) 收藏 举报  分类: python(11)  版权声明:本文为广大朋友交流学习,如有纰漏望不吝赐教,若存在版权侵犯请及时与我联系 目录(?)[+] 一.初识类和对象 在python3中类型就是类 先定义类在产生相对应的对象,也就是现有了概念再有了实体 class Garen: camp = 'Demacia' def attack(self): print('attack') 1.如何使用类 在python3:

反射与元类

1.isinstance与issubclass 在介绍反射之前,先来介绍两个关于类的内置方法,第一个是用来判断对象是否是某一类的对象(以前常说的判断是否是某一类型,类与类型其实是一个概念),第二个则是用来判断某一类是否是继承了另一个类 l=list([1,2,3]) print(isinstance(l,list)) #True class People: def __init__(self): pass class Chinese(People): def __init__(self): pa

python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法

一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstance(obj, Foo)) #结果为True 2.issubclass(sub, super)检查sub类是否是 super 类的派生类 class Foo(object): pass class Bar(Foo): pass print(issubclass(Bar, Foo)) #结果为True

python面向对象高级:反射、魔法方法、元类

自省/反射什么是反射?自省也称作反射,这个性质展示了某对象是如何在运行期取得自身信息的.并且在python里,反射可以使得程序运行时对象拥有增删改查它本身属性或行为的一种能力如果Python不支持某种形式的自省功能,dir和type内建函数,将很难正常工作.还有那些特殊属性,像__dict__,__name__及__doc__反射的使用场景? 即插即用,即可以事先定义好接口,接口只有在被完成后才会真正执行 比如:如果和别人共同合作开发项目,但是需要用到对方的类的方法,对方还没完成 f1=FtpC

反射,元类

内置函数 # class Foo: # pass # obj=Foo # print(isinstance(obj,Foo)) #在python3中统一类与类型的概念 #d={"x":1}#d=dict({"x":1}) #print(type(d) is dict) # print(isinstance(d,dict)) isinstance(对象名,类名) 判断是否是实列 # issubclass(子类,父类) 判断一个类是不是另一个类的子类 # class P