首页 > 编程语言 >【8.0】Python面向对象之反射

【8.0】Python面向对象之反射

时间:2023-11-30 14:39:45浏览次数:47  
标签:__ 8.0 run name Python res age 面向对象 print

【一】反射

【1】什么是反射

  • 反射是一种程序可以访问、检测和修改其本身状态或行为的能力。
  • 在 Python 中,反射主要指通过字符串的形式操作对象的属性。

【2】Python中的反射

  • 通过字符串的形式操作对象相关的属性。
  • python中的一切事物都是对象(都可以使用反射)

【二】反射方法

【1】反射方法介绍

  • getattr(object, name[, default])
    • 获取对象的属性值,如果属性不存在,可提供默认值。
  • hasattr(object, name)
    • 判断对象是否具有指定属性
  • setattr(object, name, value)
    • 设置对象的属性值
  • delattr(object, name)
    • 删除对象的属性

【2】反射方法使用

(1)引入

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("人能跑 ...")


person = Person('dream', 18)

# 直接通过对象获取属性对应的值
print(person.name)
# dream

# 可以查看类的属性,不能查看方法
print(person.__dict__)
# {'name': 'dream', 'age': 18}

# 根据字典取值:拿到字典中对应的值
print(person.__dict__['name'])
# dream

# 查看对象中的所有方法
print(person.__dir__())

# 查看 对象中 的所有方法
print(dir(person))
# ['__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', 'name', 'run']

(2)getattr

  • getattr(object, name[, default])
    • 获取对象的属性值,如果属性不存在,可提供默认值。
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("人能跑 ...")


person = Person('dream', 18)

# getattr 方法 : 如果存在这个方法或者属性,就返回属性值或者方法的内存地址;如果不存在,报错
res_name = getattr(person, 'name')
print(f"res_name :>>>> {res_name}")
# res_name :>>>> dream

res_age = getattr(person, 'age')
print(f"res_age :>>>> {res_age}")
# res_age :>>>> 18

res_run = getattr(person, 'run')
print(f"res_run :>>>> {res_run}")
# res_run :>>>> <bound method Person.run of <__main__.Person object at 0x000002405665B9A0>>

res_smile = getattr(person, 'smile')
print(f"res_smile :>>>> {res_smile}")
r'''
Traceback (most recent call last):
  File "E:\PythonProjects\000.py", line 72, in <module>
    res_smile = getattr(person, 'smile')
AttributeError: 'Person' object has no attribute 'smile'
'''

(3)hasattr

  • hasattr(object, name)
    • 判断对象是否具有指定属性
# 常用
# hasattr  判断对象是否存在某属性或方法
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("人能跑 ...")


person = Person('dream', 18)

# getattr 方法 : 如果存在这个方法或者属性,就返回属性值或者方法的内存地址;如果不存在,报错
res_name = hasattr(person, 'name')
print(f"res_name :>>>> {res_name}")
# res_name :>>>> True

res_age = hasattr(person, 'age')
print(f"res_age :>>>> {res_age}")
# res_age :>>>> True

res_run = hasattr(person, 'run')
print(f"res_run :>>>> {res_run}")
# res_run :>>>> True

res_smile = hasattr(person, 'smile')
print(f"res_smile :>>>> {res_smile}")
# res_smile :>>>> False

(4)setattr

  • setattr(object, name, value)
    • 设置对象的属性值
# 常用
# setattr  给对象设置方法或属性
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("人能跑 ...")


person = Person('dream', 18)

# getattr 方法 : 如果存在这个方法或者属性,就返回属性值或者方法的内存地址;如果不存在,报错
res_name = hasattr(person, 'name')
print(f"res_name :>>>> {res_name}")
# res_name :>>>> True

res_age = hasattr(person, 'age')
print(f"res_age :>>>> {res_age}")
# res_age :>>>> True

res_run = hasattr(person, 'run')
print(f"res_run :>>>> {res_run}")
# res_run :>>>> True

# 没有 height 属性 ----> 社会属性 值
setattr(person, 'height', 180)

print(getattr(person, 'height'))
# 180


def smile():
    print("可以笑")

# 设置方法
setattr(person, 'smile', smile)
# 获取方法
print(getattr(person, 'smile'))
# 使用方法
person.smile()

(5)delattr

  • delattr(object, name)
    • 删除对象的属性
# 常用
# setattr  给对象设置方法或属性
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("人能跑 ...")


person = Person('dream', 18)

res_name = delattr(person, 'name')
print(f"res_name :>>>> {res_name}")
# res_name :>>>> True

res_name = getattr(person, 'name')
print(res_name)

【3】拓展

(1)类也是对象

  • 在Python中一切皆对象,所以我们也可以将类作为反射方法的第一个参数,反射其属性
# hasattr  判断对象是否存在某属性或方法
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("人能跑 ...")


# getattr 方法 : 如果存在这个方法或者属性,就返回属性值或者方法的内存地址;如果不存在,报错
res_name = hasattr(Person, 'name')
print(f"res_name :>>>> {res_name}")
# res_name :>>>> False

res_age = hasattr(Person, 'age')
print(f"res_age :>>>> {res_age}")
# res_age :>>>> False

res_run = hasattr(Person, 'run')
print(f"res_run :>>>> {res_run}")
# res_run :>>>> True

res_smile = hasattr(Person, 'smile')
print(f"res_smile :>>>> {res_smile}")
# res_smile :>>>> False

(2)反射当前模块成员

import sys


def s1():
    print('s1')


def s2():
    print('s2')


this_module = sys.modules[__name__]

res_s1 = hasattr(this_module, 's1')
print(res_s1)
# True

res_s2 = getattr(this_module, 's2')
print(res_s2)
# <function s2 at 0x000002C2425E35B0>

【三】反射的好处

【1】实现可插拔机制

  • 反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,意味着可以在程序运行过程中动态地绑定接口的实现。
  • 这种灵活性使得程序更容易扩展和维护。
class PluginInterface:
    def execute(self):
        pass


class PluginA(PluginInterface):
    def execute(self):
        print("插件A被启动")


class PluginB(PluginInterface):
    def execute(self):
        print("插件B被启动")


def run_plugin(plugin):
    plugin.execute()


# 使用反射调用插件
plugin_name = input("请输入插件名字(PluginA or PluginB)  :>>>> ")
# 从全局名称空间中获取到 插件名字对应的类
plugin_class = globals().get(plugin_name)

# 判断一下当前类是否存在 并且 判断当前类是否 有 PluginInterface 接口
if plugin_class and issubclass(plugin_class, PluginInterface):
    # 如果都成立会触发相应的方法
    run_plugin(plugin_class())
else:
    # 不存在则抛出异常
    print("Invalid plugin name")

【2】动态导入模块(基于反射当前模块成员)

  • 动态导入模块是指在程序运行时根据字符串的形式导入模块。
  • 通过反射,可以动态导入模块的成员,实现更灵活的代码组织和管理。
import importlib

module_name = input("请输入模块名 :>>>> ")
method_name = input("请输入方法名 :>>>> ")

try:
    # 动态导入模块
    module = importlib.import_module(module_name)
    # 反射是否存在当前方法
    method = getattr(module, method_name)
    # 如果存在则执行当前方法
    method()
except ImportError:
    print("Module not found")
except AttributeError:
    print("Method not found")

标签:__,8.0,run,name,Python,res,age,面向对象,print
From: https://www.cnblogs.com/dream-ze/p/17867257.html

相关文章

  • 【7.0】Python面向对象之绑定方法与非绑定方法
    【一】绑定方法与非绑定方法介绍【1】绑定方法绑定给谁,谁来调用就自动将它本身当作第一个参数传入(1)绑定到类的方法用classmethod装饰器装饰的方法。为类量身定制类.boud_method(),自动将类当作第一个参数传入(其实对象也可调用,但仍将类当作第一个参数传入)(2)绑定......
  • 【补】面向对象软件开发
    【一】对象导向编程(OOP)对象导向编程(ObjectOrientedProgramming,OOP)是一种程序设计思想,它将现实世界中的实体抽象为一个个“对象”,并将对象间的交互规则封装到对象内部,通过调用对象的公共接口来实现各种功能。然而,当我们学习完Python的class机制后,可能会遇到这样一个......
  • 【补】Python中关于OOP的常用术语
    【一】抽象与实现【1】抽象抽象是一种概念或思维工具,用于简化复杂的问题并将其分解为易于管理的部分。抽象可以帮助我们理解事物的本质和行为,同时也可以帮助我们在设计软件时更好地组织代码和数据结构。【2】实现实现则是对抽象的一种具体表达。它是对抽象的概念或模型进......
  • MySQL8.0存储引擎对比
    MySQL8.0存储引擎对比MySQL8默认支持的存储引擎有MEMORY,PERFORMANCE_SCHEMA,MyISAM,MRG_MYISAM,BLACKHOLE,CSV,ARCHIVE和InnoDB共8种存储引擎。其中InnoDB为MySQL8的默认存储引擎。存储引擎信息在数据库中的存储位置为:INFORMATION_SCHEMA下的ENGINES表。ENGINESUPPORTCOMMENT......
  • MIT18.06Linear Algebra 第13讲 复习一
    转载于:超详细MIT线性代数公开课笔记......
  • MIT18.06Linear Algebra 第14讲 正交向量与正交子空间
    转载于:超详细MIT线性代数公开课笔记......
  • [python] 基于Tablib库处理表格数据
    Tablib是一个用于处理电子表格(如Excel,CSV,JSON)的Python库。它提供了一种简单而强大的方式来操作和处理数据。利用Tablib,我们可以轻松地读取、写入、过滤和转换各种类型的电子表格数据。Tablib具有一致且易于使用的API,以在不同的数据格式之间进行无缝转换。比如,Tablib可以将数据......
  • Python爬取某电商平台商品数据及评论!
    前言随着互联网的发展,电商平台的出现让我们的消费更加便利,消费者可以在家里轻松地购买到各种商品。但有时候我们需要大量的商品数据进行分析,或者需要了解其他消费者的评价,这时候我们可以通过爬虫来获取数据。本文将介绍如何使用Python爬取某电商平台的商品数据及评论,并且用到代理ip......
  • Python学习之十二_tkinter的学习与使用
    Python学习之十二_tkinter的学习与使用摘要本来想说会用QT5进行界面编程但是发现比较繁琐还是先学习使用tkinter的方式进行界面化的编写和学习了基础知识tkinter是一个源码开放的图形用户接口开发工具,具备跨平台的特性Python默认的GUI开发模块是tkinter(在Python3以前的版本中......
  • Python中导入包和模块
    一、模块含义在前面的几个章节中我们基本上是用python解释器来编程,如果你从Python解释器退出再进入,那么你定义的所有的方法和变量就都消失了。为此Python提供了一个办法,把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件被称为模块。模块是一个包含所......