首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >进阶的运维开发(三)- 反射

进阶的运维开发(三)- 反射

原创
作者头像
奔跑的骆驼
修改2020-02-28 09:57:48
3200
修改2020-02-28 09:57:48
举报
文章被收录于专栏:运维杂记运维杂记

反射

反射就是通过字符串的形式,导入模块,通过字符串的形式,去模块寻找制定函数并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动。

关键字

  • getattr
  • setattr
  • hasattr
  • delattr

例子:

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def show(self):
        return self.x + self.y

p = Point(2, 3)
p.__dict__
{'x': 2, 'y': 3}
# 实例化运用方法
p.show()
5
# 反射 获取类的信息
getattr(p, 'show')()
5

# 发射 添加类的信息
setattr(p, "language", "python")

p.__dict__
{'language': 'python', 'x': 2, 'y': 3}

p.language
python

# 反射 判断是否有该类的信息
hasattr(p, "language")
True

# 反射  删除类的信息
delattr(p, "language")

p.__dict__
{'x': 2, 'y': 3}

setattr的对象是实例,给函数动态增加方法需要将函数转化为方法,转化方法types.MethodType

def lst(self):
    print(self.x, self.y)

import types
setattr(p, "lst", types.MethodType(lst, p))

p.lst()
2 3

通过getattr来执行本身函数执行

class Command:
    def cmd1(self):
        print("cmd1")
    def cmd2(self):
        print("cmd2")
    def run(self):
        while True:
            cmd = input(">>>")
            if cmd == "quit"
                return 
            getattr(self, cmd, lambda : print("not found cmd {}".format(cmd)))()

cmd = Command()
cmd.run()
>>>cmd1
cmd1
>>>cmd2
cmd2
>>>cmd3
not found cmd cmd3
>>>quit

类方法

  • __getattr__
  • __setattr__
  • __delattr__

当一个类定义了__getattr__方法时,如果访问不存在的成员,会调用__getattr__方法

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __getattr__(self, name):
        return "can not found {} property".format(name)
    def show(self):
        return self.x + self.y

p = Point(1, 2)
p.x
1
p.z
'can not found z property'

属性查找优先级 __dict__ > __class__.__dict__ > __getattr__

p.__dict__
{'x': 1, 'y': 2}

p.__class__.__dict__
mappingproxy({'__dict__': <attribute '__dict__' of 'Point' objects>,
              '__doc__': None,
              '__getattr__': <function __main__.Point.__getattr__>,
              '__init__': <function __main__.Point.__init__>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Point' objects>,
              'show': <function __main__.Point.show>})

当一个类实现__setattr__时,任何地方对这个类的对象增加属性,或者对现有属性赋值,都会调用__setattr__

class Point:
        def __init__(self, x, y):
            self.x = x
            self.y = y 
        def __setattr__(self, name, value):
            print('set {} to {}'.format(name, value))
            self.__dict__[name] = value

p = Point(1, 2)
set x to 1
set y to 2

p.__dict__
{'x': 1, 'y': 2}

当需要对实例属性修改,做一些额外操作的时候,可以使用__setattr__

当一个类实现__delattr__时,任何地方对这个类的对象删除属性,都会调用__delattr__

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __delattr__(self, name):
        print('remove property {}'.format(name))
        self.__dict__.pop(name)

p = Point(1, 2)
p.__dict__
{'x': 1, 'y': 2}

del p.x
remove property x

p.__dict__
{'y': 2}
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __getattribute__(self, name):
        return "overwrite __dict__"

p = Point(1, 2)
p.x
'overwrite __dict__'

p.y
'overwrite __dict__'

从上述可得知属性优先级:

__getattribute__ > __dict__ > __class__.__dict__ > __getattr__

以梦为马 不负韶华 归来仍是少年

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 反射
    • 关键字
      • 类方法
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档