zoukankan      html  css  js  c++  java
  • day24 Pyhton学习 反射

    一.isinstance,type,issubclass

    issubclass() 这个内置函数可以帮我们判断x类是否是y类的子类

    issubclass(x,y)

    class Base:
     pass
    class Foo(Base):
     pass
    class Bar(Foo):
     pass
    print(issubclass(Bar, Foo)) # True
    print(issubclass(Foo, Bar)) # False
    print(issubclass(Bar, Base)) # True

    type(obj)表示查看obj是由哪个类创建的

    class Foo:
     pass
    obj = Foo()
    print(obj, type(obj)) # 查看obj的类 <class '__main__.Foo'>
    可以帮我们判断xxx是否是xxx数据类型的
    class Boy:
     pass
    class Girl:
     pass
    # 统计传进来的男生和女生分别有多少
    def func(*args):
     b = 0
     g = 0
     for obj in args:
        if type(obj) == Boy:
             b += 1
        elif type(obj) == Girl:
             g += 1
     return b, g
    ret = func(Boy(), Girl(), Girl(), Girl(), Boy(), Boy(), Girl())
    print(ret)
    isinstance也可以判断xxx是yyy类型的数据. 但是isinstance没有type那么精准.
    class Base:
     pass
    class Foo(Base):
     pass
    class Bar(Foo):
     pass
    print(isinstance(Foo(), Foo)) # True
    print(isinstance(Foo(), Base)) # True
    print(isinstance(Foo(), Bar)) # False
     isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)

    二.区分函数和方法

    我们之前讲过函数和方法. 这两样东西如何进行区分呢? 其实很简单. 我们只需要打印一
    下就能看到区别的.
    class Foo:
     def chi(self):
     print("我是吃")
     @staticmethod
     def static_method():
     pass
     @classmethod
     def class_method(cls):
     pass
    f = Foo()
    print(f.chi) # <bound method Foo.chi of <__main__.Foo object at
    0x10f688550>>
    print(Foo.chi) # <function Foo.chi at 0x10e24a488>
    print(Foo.static_method) # <function Foo.static_method at 0x10b5fe620>
    print(Foo.class_method) # bound method Foo.class_method of <class
    '__main__.Foo'>>
    print(f.static_method) # <function Foo.static_method at 0x10e1c0620>
    print(f.class_method) #<bound method Foo.class_method of <class
    '__main__.Foo'>>
    仔细观察, 我们能得到以下结论:
    1. 类方法. 不论任何情况, 都是方法.
    2. 静态方法, 不论任何情况. 都是函数
    3. 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数. 

    三.反射

    getattr(对象, 字符串): 从对象中获取到xxx功能. 此时xxx是一个字符串. get表示找, attr表示属性(功能). 但是这里有个问题. 用户如果手一抖, 输入错了. 在大牛的代码里没有你要找的内容. 那这个时候就会报错. 所以. 我们在获取attr之前. 要先判断一下. 有没有这个attr. 
    import master
    from types import FunctionType
    while 1:
       print("""作为大牛, 我帮你写了:
       chi
       he
       la
       shui
      等功能. 自己看看吧""")
     gn = input("请输乳你要测试的功能:")
     # niuB版
     if hasattr(master, gn): # 如果master里面有你要的功能
      # 获取这个功能, 并执行
       attr = getattr(master, gn)
       # 判断是否是函数. 只有函数才可以被调用
       if isinstance(attr, FunctionType):
             attr()
       else:
           # 如果不是函数, 就打印
           print(attr)
    class Person:
         country = "大清"
         def chi(self):
             pass
    # 类中的内容可以这样动态的进行获取
    print(getattr(Person, "country"))
    print(getattr(Person, "chi")) # 相当于Foo.func 函数
    # 对象一样可以
    obj = Person()
    print(getattr(obj, "country"))
    print(getattr(obj, "chi")) # 相当于obj.func 方法
    总结, getattr可以从模块中获取内容, 也可以从类中获取内容, 也可以从对象中获取内容. 在python中一切皆为对象. 那可以这样认为. getattr从对象中动态的获取成员    
    class Person:
         def chi(self):
             print("")
         def he(self):
             print("")
         def la(self):
             print("")
         def sa(self):
             print("")
         def shui(self):
             print("")
         def run(self):
             lst = ['chi', 'he', 'la', 'sa', 'shui']
             num = int(input("""本系统有以下功能
                 1. 吃
                 2. 喝
                 3. 拉
                 4. 撒
                 5. 睡
    请选择你要执行的功能:"""))
     
            # 通过类名也可以使用
             # func = getattr(Person, lst[num - 1])
             # func(self)
             # 通过对象来访问更加合理
             # method = getattr(self, lst[num-1])
             # method()
    p = Person()
    p.run()        
    补充:
     关于反射, 其实一共有4个函数:
        1. hasattr(obj, str) 判断obj中是否包含str成员
        2. getattr(obj,str) 从obj中获取str成员
        3. setattr(obj, str, value) 把obj中的str成员设置成value. 注意. 这李的value可以是值, 也可以是函数或者⽅法
        4. delattr(obj, str) 把obj中的str成员删除掉
    class Foo:
         pass
    f = Foo()
    print(hasattr(f, "chi")) # False
    setattr(f, "chi", "123")
    print(f.chi) # 被添加了一个属性信息
    setattr(f, "chi", lambda x: x + 1)
    print(f.chi(3)) # 4
    print(f.chi) # 此时的chi既不是静态方法, 也不是实例方法, 更不是类方法. 就相当于你在类中写了个self.chi = lambda 是一样的
    print(f.__dict__) # {'chi': <function <lambda> at 0x107f28e18>}
    delattr(f, "chi")
    print(hasattr(f, "chi")) # False
  • 相关阅读:
    Java(15) _Runtime类 内存方法
    Mysql(1)_ 基本sql语句
    Java(13)_ 用IO流复制文件
    Java(12)_switch语句
    Java(10) _无参构造方法调用问题
    Java(9) _强制类型转换
    Java(8)_符串常量赋值
    Java(7)_file类的常用方法
    Java(6)_ Runtime类调用exe程序
    Java(5) _类的定义
  • 原文地址:https://www.cnblogs.com/pythonz/p/9972715.html
Copyright © 2011-2022 走看看