~~面向对象进阶(三):反射~~

进击のpython


神奇的反射


定义:通过字符串的形式操作对象相关的属性

由于python一切皆对象

所以,都可以使用反射!

什么意思呢?,我现在,写一个类

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

    pass

我现在想要知道我的类,有没有一个属性叫做name2

可以吧,这也是一个请求

那怎么做呢?

p = Person()

if p.name2:
    print("我在类的属性里")

这么写吗?

不对吧,当你这么写的时候,p.name2也实际上就是在调用是吧

那我没有是不是肯定要报错啊

AttributeError: 'Person' object has no attribute 'name2'

结果也确实是如我们所分析的那样

那这种时候,就用到反射了!

那我们就要学习反射的第一个方法

  • hasattr

    他是来查询你的类里面有没有一个属性的方法的

    示例如下

    if hasattr(p, "name2"):
        print("我在类的属性里")

    其中传的参数先后是(类的实例,你要查询的属性)

    看好奥,查询的属性要用字符串的形式

    这是不是就是通过字符串来操作对象的相关属性

    执行一下发现什么都没有

    将name2⇨name

    发现下面的话成功打印了

    能理解吧(因为name2不在里面,返回的是False)


其实反射就像我们所学习到的数据类型一样,也是存在增删改查的

getattr()获取

hassttr()检查

setattr()赋值

deattr()删除

因为传入的是字符串形式,所以也就可以认为是通过字符串的形式

来操作对象的相关属性


  • getattr

    a = getattr(p, "name")
    print(a)

    获取p实例里面name属性的值

    能理解吧(打印结果为None,因为上述代码属性就是None)

    你看,你是不是通过字符串的模式,就获取到a了

    但是有什么用呢?

    这可是太有用了!

    你想想熬,你这个Person里面多了一些方法,比如walk speak等等

    那用户在进行操作程序的时候

    键入命令是不是都是字符串形式的!

    懂我意思了吧

    当用户的键入信息在类里有,我们就执行,否则就不执行

    user_input = input("请输入指令:")
    if hasattr(p, user_input):
        a = getattr(p, user_input)
        a()
    请输入指令:walk
    没病走两步

    对吧!

    当我输入指令的时候,我就键入“walk”这个指令

    判断一下是不是在实例的方法里啊

    在是吧!

    然后获取到这个方法(函数)

    最后再将函数调用

    这就是简单的反射应用场景


  • setattr

    setattr(p, "sex", "Female")
    print(p.sex)

    赋值,给你的p实例新增加了一个叫sex的属性

    同时将它赋值为Female

    这样我在下面打印的时候就打印出来不会报错

    (原实例里没有这个属性,如果不写setattr是会报错的)

    这种属性,是静态的

    那我们怎么样可以设置一个方法呢?

    首先,因为我知道我的这个方法是要传进类里的

    所以在类外面定义的时候

    我先在括号里填上实例对象self

    def talk(self):
        print(f"{self.sex}逼逼叨!")

    然后再在外面设置setattr方法

    setattr(p, "sex", "Female")
    
    setattr(p, "talk", talk)

    (实例对象,方法名(自定义),函数名)

    最后调用的时候,要把实例传进去!

    p.talk(p)

    方法名那里多说一下

    并不需要和函数名起名一致

    setattr(p, "shuohua", talk)
    p.shuohua(p)

    因为他是函数的调用名,所以你怎么叫,他就怎么调用

    同时还要注意,最后一个参数放的是函数名!没有()

    而且啊,不要思维定势

    不光可以给实例加方法

    你也可以给类加方法啊

    setattr(Person, "shuohua", talk)
    p.shuohua()

    对吧!

    所以你就可以看出来

    其实最好的绑定方法是要给类绑定

    因为要是给实力绑定,还要自己传实例


  • delattr

    print(p.age)
    delattr(p, "age")
    print(p.age)

    执行结果可以看到

    None
    AttributeError: 'Person' object has no attribute 'age'

    第一行打印属性

    第二行将这个属性删除

    第三行再想打印就找不到了

    就报错了

    但是其实你会发现一个问题

    就是这个方法其实和 del 差不多

    del p.age

    也是可以的


那说了这么多,反射可以怎么做呢?

一个简单的例子就可以知道了

现在让我们打开购物车,访问一个菜单,你单击登录就跳转到登录界面,你单击注册就跳转到注册界面,等等

其实你单击的其实是一个个的链接,每一个链接都会有一个函数或者方法来处理。

没学反射之前的解决方式

class User:
    def login(self):
        print('欢迎来到登录页面')

    def register(self):
        print('欢迎来到注册页面')

    def save(self):
        print('欢迎来到存储页面')


while 1:
    choose = input('>>>').strip()
    if choose == 'login':
        obj = User()
        obj.login()
    elif choose == 'register':
        obj = User()
        obj.register()
    elif choose == 'save':
        obj = User()
        obj.save()

对吧

一点一点的写

那要是学完反射

我们就可以这么写了!

class User:
    def login(self):
        print('欢迎来到登录页面')

    def register(self):
        print('欢迎来到注册页面')

    def save(self):
        print('欢迎来到存储页面')


user = User()
while 1:
    choose = input('>>>').strip()
    if hasattr(user, choose):
        func = getattr(user, choose)
        func()
    else:
        print('输入错误。。。。')

这样就可以明确的感觉到反射的好处


*这个很有用*
*不学就吃亏*
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jevious

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值