您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

Python反射介绍

时间:2022-03-07 13:42:04  来源:  作者:测试开发小记

反射机制是面向对象编程语言中比较重要的功能,可以动态获取对象信息以及动态调用对象,Python/ target=_blank class=infotextkey>Python作为一门动态编程语言,当然也有反射机制,本文介绍Python反射函数使用方法。

反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

在程序运行时可以获取对象类型定义信息,例如,Python中的type(obj)将返回obj对象的类型,这种获取对象的type、attribute或者method的能力称为反射。通过反射机制,可以用来检查对象里的某个方法,或某个变量是否存在。也就是可以通过字符串映射对象的方法或者属性

Python反射函数

Python反射常用的内置函数

  • type(obj):返回对象类型
  • isinstance(object, classinfo):判断一个对象是否是一个已知的类型,类似 type()
  • callable(obj):对象是否可以被调用
  • dir([obj]):返回obj属性列表
  • getattr(obj, attr):返回对象属性值
  • hasattr(obj, attr):判断某个函数或者变量是否存在
  • setattr(obj, attr, val):给模块添加属性(函数或者变量)
  • delattr(obj, attr):删除模块中某个变量或者函数

反射函数使用方法

先创建一个类:

class Person():
    def __init__(self, x, y):
        self.age = x
        self.height = y
        
    def __new__(cls, *args, **kwargs):
        print("begin!!!")
        return object.__new__(cls)
        
    def __call__(self, *args, **kwargs):
        print("hello!!!")

    def talk(self):
        print(f"My age is {self.age} and height is {self.height}")

dir()

利用反射的能力,我们可以通过属性字典__dict__来访问对象的属性:

p = Person(20, 180)
print(p)
p()
print(p.__dict__)
p.__dict__['age']=22
print(p.__dict__)
p.weight = 60
print(p.__dict__)
print(dir(p))

执行输出:

begin!!!
<__mAIn__.Person object at 0x000002484557BCC8>
hello!!!
{'age': 20, 'height': 180}
{'age': 22, 'height': 180}
{'age': 22, 'height': 180, 'weight': 60}
['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'height', 'talk', 'weight']

  • 在实例创建之前调用__new__方法,返回值(实例)将传递给__init__方法的第一个参数。__new__方法的详细介绍可参考:Python中的__new__和__init__
  • 实例化对象时会自动执行 __init__ 方法
  • 打印一个对象时,会自动执行__str__ 方法
  • 调用实例化对象时,会自动触发__call__ 方法
  • 通过dir()方法可以打印出了对象p的属性。

接下来测试一下其他反射函数:

callable()

if (callable(p)):
    print("p is callable")
else:
    print("p is not callable")

Out:

p is callable

isinstance()和type()

print(isinstance(p, Person))
print(type(p) == Person)
print(isinstance(p.age, int))
print(type(p.age) == int)

Out:

True
True
True
True

hasattr()

print(hasattr(p,"talk"))

print(hasattr(p.talk,"__call__"))

Out:

True
True

getattr()

print(getattr(p,"talk"))
print(getattr(p.talk, "__call__"))

if hasattr(p,'walk'):
    print(getattr(p,'walk'))
else:
    print("I can't walk")

print(getattr(p, "walk", None)) # 如果没有walk属性就返回None

Out:

<bound method Person.talk of <__main__.Person object at 0x000001FF52868288>>
<method-wrApper '__call__' of method object at 0x000001FF52155048>
I can't walk
None

setattr()

setattr(p,'walk','ON')
if hasattr(p,'walk'):
    print(getattr(p,'walk'))
else:
    print("I can't walk")
print(p.__dict__)

Out:

ON
{'age': 22, 'height': 180, 'weight': 60, 'walk': 'ON'}

delattr()

delattr(p,'walk')
if hasattr(p,'walk'):
    print(getattr(p,'walk'))
else:
    print("I can't walk")
print(p.__dict__)

Out:

I can't walk
{'age': 22, 'height': 180, 'weight': 60}

应用

下面介绍两种Python反射的应用场景。

动态调用

从前面举的例子中,我们了解到可以通过字符串来获取对象的属性(getattr()),这是非常有用的一个功能。比如,一个类中有很多方法,它们提供不同的服务,通过输入的参数来判断执行某个方法,一般的使用如下写法:

class MyService():
    def service1(self):
        print("service1")

    def service2(self):
        print("service2")

    def service3(self):
        print("service3")

if __name__ == '__main__':
    Ser = MyService()
    s = input("请输入您想要的服务: ").strip()
    if s == "service1":
        Ser.service1()
    elif s == "service2":
        Ser.service2()
    elif s == "service3":
        Ser.service3()
    else:
        print("error!")

如果函数比较少这样写没有太大问题,如果有很多,这样写就比较复杂了,需要写大量else语句,可以使用反射机制来写:

if __name__ == '__main__':
    Ser = MyService()
    s = input("请输入您想要的服务: ").strip()
    if hasattr(Ser, s):
        func = getattr(Ser, s)
        func()
    else:
        print("error!")

这样是不是简洁了很多,上面的例子中,通过反射,将字符串变成了函数,实现了对对象方法的动态调用。

动态属性设置

可以通过setattr()方法进行动态属性设置,在使用scapy库构造报文时,我们需要设置某些报文字段,然而网络协议的报文字段很多,在需要设置大量字段时,一个一个的赋值就很麻烦:

>>> ls(IP)
version    : BitField  (4 bits)                  = ('4')
ihl        : BitField  (4 bits)                  = ('None')
tos        : XByteField                          = ('0')
len        : ShortField                          = ('None')
id         : ShortField                          = ('1')
flags      : FlagsField                          = ('<Flag 0 ()>')
frag       : BitField  (13 bits)                 = ('0')
ttl        : ByteField                           = ('64')
proto      : ByteEnumField                       = ('0')
chksum     : XShortField                         = ('None')
src        : SourceIPField                       = ('None')
dst        : DestIPField                         = ('None')
options    : PacketListField                     = ('[]')

可以使用setattr()方法来赋值:

from scapy.all import *

fields = {"version":4, "src":"192.168.0.1","dst":"192.168.10.1"}
ip = IP()
for key, val in fields.items():
    setattr(ip, key, val)


Tags:Python反射   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Python反射介绍
反射机制是面向对象编程语言中比较重要的功能,可以动态获取对象信息以及动态调用对象,Python作为一门动态编程语言,当然也有反射机制,本文介绍Python反射函数使用方法。反射反射...【详细内容】
2022-03-07  Search: Python反射  点击:(345)  评论:(0)  加入收藏
▌简易百科推荐
一篇文章教会你使用Python中三种简单的函数
所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。一、函数简介所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。二、函数定义...【详细内容】
2024-04-11  Go语言进阶学习  微信公众号  Tags:Python   点击:(7)  评论:(0)  加入收藏
一篇文章带你了解Python的分布式进程接口
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。一、前言在Thread和Process中,应当优...【详细内容】
2024-04-11  Go语言进阶学习    Tags:Python   点击:(6)  评论:(0)  加入收藏
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(10)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(21)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(35)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(40)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(42)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(91)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(90)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(61)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条