zoukankan      html  css  js  c++  java
  • ~~面向对象进阶(三):反射~~

    进击の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('输入错误。。。。')
    

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


    *这个很有用*
    *不学就吃亏*
  • 相关阅读:
    0MQ手册(给力!)
    Beansdb动态关注
    要成功?每天记得这几点(成功手抄本)
    使用Entity Framework和WCF Ria Services开发SilverLight之7:多个Domain Service间共享Poco实体
    使用Entity Framework和WCF Ria Services开发SilverLight之4:Map之主外键映射
    SilverLight Tip 1 : Validation
    使用Entity Framework和WCF Ria Services开发SilverLight之6:查找指定字段
    SilverLight单元测试1:框架
    MVVM模式之:ViewModel Factory与注入
    MVC TIP5:JQuery AJAX错误捕获
  • 原文地址:https://www.cnblogs.com/jevious/p/11260256.html
Copyright © 2011-2022 走看看