反射函数与元类

一.反射函数

反射:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)

python面向对象中的反射:通过字符串的形式操作对象相关的属性。

 

四种内置方法:getattr   setattr  delattr  hassttr

getattr:从对象中取出属性,第三个值位默认值 当属性不存在是返回默认值

 

setattr:为对象添加新的属性

 

delattr:从对象中删除属性

 

hasattr:判断object中有没有一个name字符串对应的方法或属性

class Person:

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

    def Say_hi(self):
        print('you are handsome')


p = Person("dragon",58,'male')

setattr(p,'id','123')
print(p.id)
delattr(p,'id')
if hasattr(p,'id'):
    getattr(p,'Say_hi',None)()
View Code

 

反射函数的应用场景:实现可插拔机制与动态导入模块

可插拔机制

import plugin

def run(plugin):
    while True :
        cmd = input('请输入指令')

        if cmd == 'exit':
            break
        if hasattr(plugin,cmd):
            func = getattr(plugin,cmd)
            func()

        else:
            print('该指令不存在')

    print('see you')

wincmd = plugin.Wincmd()
linux  = plugin.Linuxcmd()

run(linux)
# from frame

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 列出所有文件....")
# from plugin
View Code

 

二.元类

python中一切皆为对象,类的本质也是一个对象。

元类:可以通过实例化产生类

 

python中内置的元类TYPE,可以通过继承TYPE来构建自定义元类

使用metaclass关键字参数可以为一个类指定元类

 

方法:

call方法:

当你调用类对象时会自动启动元类中的__call__方法 ,并将这个类本身作为第一个参数传入,以及后面的一堆参数

覆盖元类中的call之后,这个类就无法产生对象,必须调用super().__call__来完成对象的创建
并返回其返回值

 

使用场景:

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

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

#实现将对象的所有属性名称转为大写
lass MyType(type):
    def __call__(self, *args, **kwargs):
        new_args = []
        for a in args:
            new_args.append(a.upper())

        print(new_args)
        print(kwargs)
        return super().__call__(*new_args,**kwargs)


class Person(metaclass=MyType):
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender

p = Person(name="jack",gender="woman")
print(p.name)
print(p.gender)
View Code

 

new方法:

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

class Meta(type):

    def __new__(cls, *args, **kwargs):
        print(cls) # 元类自己
        print(args) # 创建类需要的几个参数  类名,基类,名称空间
        print(kwargs) #空的 
        print("new run")
        # return super().__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):
    pass
print(A)
View Code

 

三.单例

单例:指的是一个类产生一个对象

使用单例是为了节省 资源

class Singel(type) :

    def __call__(self, *args, **kwargs):

        if hasattr(self,'obj') :
            return getattr(self,'obj')

        obj = super().__call__(*args,**kwargs)
        print(obj)
        print('new')
        self.obj = obj
        return obj

class Student(metaclass=Singel):
    def __init__(self,name):
        self.name = name


stu = Student('jack')
print(stu)
stu = Student('jack')
print(stu)
stu = Student('jack')
print(stu)
View Code

 

posted @ 2019-07-30 22:27  Tri_stone  阅读(155)  评论(0编辑  收藏  举报