zoukankan      html  css  js  c++  java
  • day 017面向对象-反射

     主要内容:

    •  isinstance, type, issubclass( 内置函数)
    • 区分函数和方法
    • 反射

    一    ( isinstance, type, issubclass)

    1.    isinstance()  :可以帮我们判断xx类是否是xx类的子类.       
    class Basse:
        pass
    class Foo:
        pass
    lass Bar(Foo): pass print(issubclass(Bar,Foo)) #true print(issubclass(Foo,Bar)) #false print(issubclass(Bar,Basse)) # False

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

    class Foo:
        pass
    obj = Foo()
    print( obj,type(obj)) # 查看obj的类 <__main__.Foo object at 0x0000019D93228198> <class '__main__.Foo'>
    判断好要计算的数据类型必须是int或者float

    def add(a, b):
    if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float): return a + b else: print("我要报错")

          3. isinstance() : 也可以判断xxx是YY类型的数据.但是它没有type那么精准.

    lass Animal:
        pass
    
    class Cat(Animal):
        pass
    
    class BoSiCat(Cat):
        pass
    
    # a = Animal()
    # print(isinstance(a, Animal)) # 自己类可以判断
    # print(isinstance(a, Cat))   # 子类不能判断
    
    c = BoSiCat()
    print(isinstance(c, Animal)) # True  子类的对象可以当成父类的类型来看.

    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 0x0000023453028588>>
     print(Foo.chi)  #<function Foo.chi at 0x000001AFE215A950
    print(f.static_method) #  拿对象来访问function Foo.static_method at 0x0000022A951AA9D8>
    print(Foo.static_method) #   拿类来访问<function Foo.static_method at 0x0000014459E4A9D8>
    print(f.class_method)  #<bound method Foo.class_method of <class '__main__.Foo'>>
    print(Foo.class_method)  #那类来访问 <bound method Foo.class_method of <class '__main__.Foo'>>

    结论:  类方法: 无论任何情况都是方法

              静态方法:无论任何情况都是函数

              实例方法: 如果是实力访问就是方法,如果是类名访问就是函数

     那如何用程序来帮我们分辨到底是函数换是方法呢? 

    例子:

    首先我们要借助typrs模块

    # 所有的方法都是Method的实例
    #所有的函数都是functiontypes的实例
    
    from types import MethodType,FunctionType  #引入模块
    def func():
        pass
    print(isinstance(func,FunctionType)) #true
    print(isinstance(func,MethodType)) # false
    class Foo:
        def chi(self):
            print("我是吃")
        @staticmethod
        def static_method():
            pass
        @classmethod
        def class_method(cls):
            pass
    obj=Foo()
    print()
    print(type(obj.chi)) # method
    print(type(Foo.chi)) # function
    
    # print(isinstance(obj.chi, MethodType)) # True
    # print(isinstance(Foo.chi, FunctionType)) # True
    #
    # print(isinstance(Foo.static_method, FunctionType)) # True
    # print(isinstance(Foo.static_method, MethodType)) # False
    #
    # print(isinstance(Foo.class_method, FunctionType)) # False
    # print(isinstance(Foo.class_method, MethodType)) #true

    三 反射 

    import fanshe  # 引入模块
    from types import FunctionType
    
    # while 1:
    #     print('''大牛写的功能
    #     chi
    #     he
    #     la
    #     shui
    #     调试哪个''')
    #     ts=input("请输入你要调试的功能")
    #     if ts=='chi':
    #          fanshe.chi()
    #     elif ts=="he":
    #         fanshe.he()
    #     elif ts=="la":
    #         fanshe.la()
    #     elif ts=='shui':
    #         fanshe.shui()
    #     else:
    #         print("大牛没有这个功能")
    #写是写完了. 但是.....如果大牛现在写了了100个功能呢? 你的判断要判断100次么?
    # 我们可以使用反射来完成这样的功能. 非常的简单. 想想. 这里我们是不是让用户输入要执行的功能了. 那这个功能就是对应
    # 模块里的功能. 那也就是说. 如果能通过字符串来动态访问模块中的功能就能解决这个问题
    
    #例子2
    # while 1:
    #     print('''大牛写的功能
    #     chi
    #     he
    #     la
    #     shui
    #     调试哪个''')
    #     ts=input("请输入你要调试的功能")
    #     func=getattr(fanshe,ts)  # geattr (对象,字符串)从对象中获取到xxx功能,此时xxx表示一个字符串,get
    #                                 #表示找,attr表示属性功能
    #     func()
    
     ## 写完了 但是这样有个问题在大牛的代码里没有你要找的内容,这时侯就会报错,所以在获取attr之前,要先判断下
     #有没有这个功能
     # 看下完整代码:
    # while 1:
    #     print('''大牛写的功能
    #       chi
    #       he
    #       la
    #       shui
    #       调试哪个''')
    #     ts = input("请输入你要调试的功能")
    #     if getattr(fanshe, ts):  #如果fanshe里有你要的功能
    #           # 获取这个功能,并执行
    #         attr=getattr(fanshe,ts)
    #         if isinstance(attr,FunctionType): #判断是否是函数,只有函数才可以被调用
    #             attr()
    #         else:     #如果不是就打印
    #             print(attr)
    
    #  两个函数 getattr():来获取信息 从对象中获取xxx功能
    #             hasattr()用来判断xxx中是否包含了xxx功能
    # class person:
    #     cuontry="daqing"
    #     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 cih(self):
            print("")
        def he(self):
            print("")
        def la(self):
            print("")
        def sa(self):
            print("sa")
        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成员删除掉
    # 注意, 以上操作都是在内存中进行的. 并不会影响你的源代码
    
    
    
    #setarrt 例子1
    # 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
    
    ## setarrt 例子2
    
    class Person:
        def __init__(self, name):
            self.name = name
            self.age = None
    
        def chi(self):
            print("人喜欢吃东西%s" % self.name)
    
    p = Person("刘伟")
    setattr(p, "name", "大阳哥") # 动态的给对象设置属性和值
    setattr(p, "age", 18) # 很少用. 慎用
    
    print(p.age)
    delattr(p, "age")
    print(p.age)
    
    # p.chi()
    
    # val = input("请输入你想让刘伟执行的动作:")
    # if hasattr(p, val):
    #     getattr(p, "name")
    #     func = getattr(p, val)
    #     func()
  • 相关阅读:
    VirtualBox安装
    记一次修改fstab挂载参数
    Debian其实有提供附带了各种桌面的安装镜像
    记一次使用unzip命令
    记一次给iPhone 6越狱
    浅谈.Net中内置的一种特殊的引用类型 -- String类型
    .Net中的静态类和非静态类、静态成员和非静态成员
    .Net子窗体给父窗体传值的几种方法
    int、float、double In .Net之相互转换
    车厢重组
  • 原文地址:https://www.cnblogs.com/systemsystem/p/9720425.html
Copyright © 2011-2022 走看看