首页 > 其他分享 >面向对象之反射

面向对象之反射

时间:2022-11-07 19:34:36浏览次数:44  
标签:obj1 __ obj name 反射 面向对象 print target

目录

一、面向对象之反射

0.反射的含义

反射:自省的一种方式,利用字符串操作对象的数据和方法

用户所传递的信息都是字符串类型,所以利用反射可以与用户进行交互

1. hasattr:判断一个方法是否存在与这个类中
2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行
3. setattr:通过setattr将外部的一个函数绑定到实例中
4. delattr:删除一个实例或者类中的方法

1.hasattr(object,name)

判断对象是否含有某个字符串对应的属性名或者方法名

2.getattr()

根据字符串获取对象对应的属性名(值)或方法名

如果没有名字则会报错,所以常常和hasattr搭配使用

(1)案例中体会反射在与用户交互中的便捷与突破性

class C1:
    name = 'duoduo'

    def choice_name(self):
        print('你是谁')

# 产生C1的对象
obj = C1()

1)判断某个名字是否可以被使用(存在)

# 当我们想判断对象obj中是否存在某个名字,却不想让其报错的时候可以考虑到用异常处理
try:
    obj.aaa
except AttributeError:
    print('不存在这个名字')

2)判断用户随意指定的名字对象是否可以使用(存在)

# 在异常处理的基础上,增加与用户交互的功能
target_name = input('请输入名字:').strip()
try:
    obj.target_name
except AttributeError:
    print('不存在这个名字')

3)反射的功能则可以用字符串来操作对象的数据和方法

# 反射:利用字符串操作对象的数据和方法
print(hasattr(obj, 'name'))  # True
print(getattr(obj, 'name'))  # duoduo
print(getattr(obj, 'choice_name'))  # <bound method C1.choice_name of <__main__.C1 object at 0x103191f10>>

4)综合起来利用反射来和用户进行交互

# 利用反射的方法,来动态获取想判断的名字
class C1:
    name = 'duoduo'

    def choice_name(self):
        print('你是谁')


obj = C1()
while True:
    target_name = input('请输入名字:').strip()
    if hasattr(obj,target_name):
        print('有名字')
        # 获取该名字对应的数据(值  函数地址)
        data_or_func = getattr(obj,target_name)
        if callable(data_or_func):
            print('这名字是某个方法')
        else:
            print('这名字对应的是值')
            print(data_or_func)
    else:
        print('没有该名字')v

3.setattr(object, name, value)

根据字符串给对象设置或者修改数据

obj1 = C1()
setattr(obj1, 'age', 18)
print(obj1.__dict__)  # {'age': 18}

4.delattr(object, name)

根据字符串删除对象里面的名字

class C1:
    name = 'duoduo'

    def choice_name(self):
        print('你是谁')

        
obj1 = C1()  # 类C1产生了一个对象obj1

1.hasattr()判断名字是否存在
res = hasattr(obj1, 'choice_name')
print(res)  # True

2.setattr()  为obj1添加属性或者方法
setattr(obj1, 'age', 18)  # 为obj1增加一个属性为 age = 18
print(obj1.__dict__)  # {'age': 18} 查看后在obj1中成功增加来 age = 18的属性
setattr(obj1, 'age', lambda a: a + 1)
print(obj1.__dict__)  # {'age': <function <lambda> at 0x10242a280>}

3.delattr() 删除属性或者方法
delattr(obj1, 'age')
print(obj1.__dict__)  # {} 空集合代表,该对象没有自己独有的功能或者属性

二、反射实战案例

1.使用反射的场景:

​ 只要需求中出现了关键字:对象...字符串...

2.案例

(1)模拟终端

class WinCmd:
    def tasklist(self):
        print("""
        1.学习编程
        2.学习python
        3.学习英语
        """)

    def ipconfig(self):
        print("""
        地址:127.0.0.1
        地址:上海浦东新区
        """)

    def get(self, target_file):
        print('获取文件', target_file)

    def put(self, target_file):
        print('上传文件', target_file)

    def server_run(self):
        print("欢迎进入简易版本cmd终端".center(50, '='))
        while True:
            target_cmd = input('请输入您的指令>>>:')
            res = target_cmd.split(' ')  # 因为在终端中输入命令常常有空格
            if len(res) == 1:
                if hasattr(self, res[0]):
                    getattr(self, res[0])()  # 存在该命令则执行
                else:
                    print(f'{res[0]}不是内部或者外部命令')  # 如果传入了参数,则执行该命令并传入参数
            elif len(res) == 2:
                if hasattr(self, res[0]):
                    getattr(self, res[0])(res[1])
                else:
                    print(f'{res[0]}不是内部或者外部命令')


obj = WinCmd()  # 产生类WinCmd的对象
obj.server_run()  # 调用obj的方法server_run

(2)一切皆对象

利用反射保留某个py文件中所有的大写变量名以及对应到数据值

  • settings.py文件中
NAME = 'duoduo'
AGE = 13
desc = '吃饭天'
info = '没到点'

def name():
    print('name')

class Person:
    name = 'duoduo'

执行文件中

查看文件中的名字也可以用dir()方法,列举对象可以使用的名字

查看文件中的名字也可以用 __dict__ 方法,print(settings.__dict__)

但是文件中的名字会有很多,所以如果class类更适合用__dict__方法

(1)传统方法

import settings

print(dir(settings))  # dir是列举对象可以使用的名字
# ['AGE', 'NAME', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'desc', 'info']

1.方式一:for循环 + 判断
# 构造一个空字典,用来存放我们想要的名字
useful_dict = {}
for name in dir(settings):
    if name.isupper():  # 保留大写
        useful_dict[name] = getattr(settings,name)
print(useful_dict)  # {'AGE': 13, 'NAME': 'duoduo'}


2.方式二:生成式
useful_dict = {name: getattr(settings, name) for name in dir(settings) if name.isupper()}

print(useful_dict)
# {'AGE': 13, 'NAME': 'duoduo'}

(2)利于反射动态获取

# 用反射判断settings.py文件中是否有某个名字

while True:
    target_name = input('请输入您想判断的某个名字:').strip()
    if hasattr(settings, target_name):

        print(getattr(settings, target_name))
        """ 
        如果存在该名字则返回值,
        是方法则返回方法的内存地址<function name at 0x1004a7d30>,
        如果是类名则返回类的名字<class 'settings.Person'>
        """

    else:
        print('该模块文件中没有该名字')

标签:obj1,__,obj,name,反射,面向对象,print,target
From: https://www.cnblogs.com/DuoDuosg/p/16867146.html

相关文章

  • 面向对象三大特性封装,多态,反射
    派生方法实战演练importjsonimportdatetimed={'ti':datetime.date.today()'t2':datetime.datetime.today()'t3':'jason'}res=json.dumps(d)pr......
  • 面向对象之封装、多态、反射
    面向对象之封装、多态、反射面向对象之封装封装:将数据和功能‘封装’起来隐藏:将数据和功能隐藏起来不让用户直接调用,并开发一些接口间接调用,而且可以在接口内添加一些......
  • xss反射型深入分析
    有任何问题都可以留言咨询。 定义再理解什么是xss反射型漏洞?这里有个核心思想,指的是用户输入了什么,那响应的内容肯定会包括什么。比如用户输入了"testxss",那响应的内......
  • Python基础之面向对象:5、三大特征-多态
    面对对象之多态目录面对对象之多态一、多态1、多态的概念2、多态的实际应用1、自我约束2、abc模块一、多态1、多态的概念​ 多态在实际应用时较为抽象,指事物的多种形态......
  • Python基础之面向对象:6、三大特征-封装
    面向对象之封装目录面向对象之封装一、封装1、封装的概念2、为什么要封装3、封装的两个层面二、隐藏与调用的方法1、隐藏的方法2、调用与修改的方法三、伪装1、伪装的概念......
  • Python基础之面向对象:7、反射
    面向对象之反射目录面向对象之反射一、反射1、反射的定义2、使用的场景3、常用方法1.hasattr()2.getattr()3.setattr()4.delattr()4、反射的实际应用一、反射1、反射的......
  • 11月7日内容总结——派生方法实例、面向对象三大特性之封装、多态和反射
    目录一、派生方法实战二、面向对象三大特性之封装隐藏属性如何调用隐藏属性隐藏属性的作用和使用方式三、伪装伪装的操作两个小功能:删除和修改四、面向对象三大特性之多态......
  • 面向对象三
    目录派生方法实战演练面向对象三大特性之封装伪装三大特性之多态面向对象之反射反射实战案例派生方法实战演练importjsonimportdatetimed={'t1':datetime.dat......
  • Python基础之面向对象:4、super方法实战
    派生方法实战​ 以上我们学习了通过super()的方法可以重写父类、额外添加父类中的数据,下面将通过实战案例来讲述super()方法来重写、添加父类中的功能代码需求:1、使用js......
  • 面向对象封装/多态/反射
    内容概要派生方法实战面向对象三大特性之封装三大特性之多态面向对象之反射反射实战案例练习题派生方法实战派生方法实战案例:importjsonimportdatetime#......