• 方法&函数区别,反射


    主要内容:

    • 1. isinstance, type, issubclass
    • 2. 方法和函数的区别
    • 3. 反射(重点)

    1. isinstance, type, issubclass

    (1) issubclass(xxx,yyy) 这个内置函数可以帮我们判断xxx类是否是yyy类型的子类.

    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

    (2) type

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

    class Foo:
        pass
    obj = Foo()
    print(obj, type(obj))   # 查看obj的类

          判断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)                    # (3, 4)

    在进行计算的时,先判断好要计算的数据类型必须是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,yyy):  判断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家族体系中的(只能往上判断)

    2. 方法和函数的区别

    2.1 在类外边定义的函数一定是函数

    def func():
        print("你猜猜看")
    print(func)                     #<function func at 0x000002819F1B6048>

    2.2 写在类中的函数

    class Foo:
        # 实例方法: 对象.方法  方法    类名.方法  函数
        def func(self):
            print("这里是什么呢!")
    obj = Foo()
    print(obj.func)                   #绑定的方法<bound method Foo.func of <__main__.Foo object at 0x00000217422E7978>>
    
    Foo.func(obj) print(Foo.func) #类名直接调用就是方法 <function Foo.func at 0x000002BCB0528A60>

    注: 如果通过对象方法,那么self 它会自动帮你传递, 如果使用类名来调用,self就不会帮你传递

    2.3 类中的类方法,静态方法

    class Foo:
        @staticmethod
        def static_method():
            pass
    
        @classmethod  # 都是方法
        def class_method(cls):  # 类对象的内容
            pass
    
        @property  # 神马都不是. 变量
        def age(self):
            return 10
    f = Foo()
    # print(f.static_method)               #<function Foo.static_method at 0x000001ACF90D8A60>
    # print(Foo.static_method)             #<function Foo.static_method at 0x0000012304688A60>
    
    # 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'>>
    
    print(f.age)                             #10
    print (Foo.age)                          #   <property object at 0x000002B3197FB7C8>

    2.4 通过 types中的FunctionType和MethodType可以区分当前内容是方法还是函数,

    注: 判断是方法还是函数

    from types import MethodType,FunctionType
    def check(arg):
        '''
        判断arg是函数则打印1,arg是方法则打印2
        :param arg
        '''
        if isinstance(arg,MethodType):
            print(2)
        elif isinstance(arg,FunctionType):
            print(1)
        else:
            print('不认识')
            
    def func():
        pass
    class Foo(object):
        def display(self):
            pass
    check(func)                            #1
    check(Foo.display)                     #1
    check(Foo().display)                   #2

    2.5 练习

    class RoleConfig(object):
        def f1(self,arg):
            print('f1',arg)
        def f2(self,arg):
            print('f2',arg)
        list_display =[f1,f2]
    
    # obj = RoleConfig()
    for item in RoleConfig.list_display:
        item(RoleConfig()
    class RoleConfig(object):
    
        def f1(self, arg):
            print('f1', arg)
    
        def f2(self, arg):
            print('f2', arg)
    
        def f3(self, arg):
            print('f3', arg)

    #静态字段 list_display
    = [f1, f2] def get_list_display(self): self.list_display.insert(0, RoleConfig.f3) return self.list_display obj1 = RoleConfig() for item in obj1.get_list_display(): item(obj1, 2) obj2 = RoleConfig() for item in obj2.get_list_display(): item(obj2, 6)
    class RoleConfig(object):
    
        def f1(self, arg):
            print('f1', arg)
    
        def f2(self, arg):
            print('f2', arg)
    
        def f3(self, arg):
            print('f3', arg)
    
        list_display = [f1, f2]
    
        def get_list_display(self):
            v = []
            v.extend(self.list_display)
            v.insert(0, RoleConfig.f3)
            return v
    
    obj1 = RoleConfig()
    for item in obj1.get_list_display():
        item(obj1, 2)
    
    obj2 = RoleConfig()
    for item in obj2.get_list_display():
        item(obj2, 6)

    小结:

    •  类方法. 不论任何情况, 都是方法.
    •  静态方法, 不论任何情况. 都是函数
    •  实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数. 

    3.反射

    3.1 引入

    一个需求, 说, 有个大牛, 写一堆特别牛B的代码. 然后放在一个py文件里(模块),这时, 你想用这个大牛写的东西,但是呢. 你首先得知道大牛写的这些代码都是干什么用的. 那就需要你把大牛写的每一个函数跑一下. 摘⼀摘自己想用的内容. 来咱们模拟 这样的需求,首先, 大牛给出一个模块. 

    def chi():
        print ("大牛一次吃一桶")
    def he():
        print ("大牛一顿喝100杯水")
    def la():
        print ("大牛不用拉")
    def sleep():
        print("大牛一睡睡一年")
    name = "大牛"
    import master
    while 1 :
        print('''大牛写了很多东西
        chi
        he
        la
        sleep
    ''')
        val = input("请输入你要测试的功能")
    #判读 master这个py 文件中是否有你想要的的功能
    if hasattr(master,val):
         #获取这个功能 (从xxx对象中或者模块中找到xxx(字符串)功能,变量) attr
    = getattr(master,val)
    #判断这个东西是否可以被调用 if callable(attr): attr() else: print(attr) else: print("没有这个功能")

    上面有两个函数:一个是getattr(),hasattr()

    • getattr()用来获取信息.
    • hasattr()用来判断xxx中是否包含了xxx功能,. 

    3.2 反射的概述

    (1)反射的定义(什么是反射机制):

    • 反射就是通过字符串的形式,导入模块;
    • 通过字符串的形式,去模块寻找指定函数,并执行。
    • 利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动

    3.3 反射的使用

    3.3.1面向对象中的反射

    (1)hasattr (xxx, ooo)  (判断xxx中是含有ooo)

    class Movie(object):
        def __init__(self,name):
            self.name  = name
    
        def release(self):
            print('%s正在放映'%self.name)
    
    movie =Movie('大话西游')
    #hasattr 返回的是True / False
    print(hasattr(movie,'name')) #True 存在name这个属性 print(hasattr(movie,'release')) #True 存在release这个方法 print(hasattr(movie,'place')) #False 不存在产地place这个属性

    (2)getattr

    class Movie(object):
        language = '国语'
        def __init__(self,name):
            self.name  = name
    
        def release(self):
            print('%s正在放映'%self.name)
    
    movie =Movie('大话西游')
    
    #从类中获取属性
    attr = getattr(Movie,'language')
    print(attr)     #国语
    #获取对象的属性
    attr1 = getattr(movie,'name')
    print(attr1)    #大话西游(获取到的是name的内存地址)
    
    #获取对象可执行的方法
    attr2 = getattr(movie,'release')
    attr2()         # 大话西游正在放映
    print(attr2)    #<bound method Movie.release of <__main__.Movie object at 0x00000215EDF585F8>>

     注;

    关于 getattr(object,'xxxx' 'not find')  第三个参数意思是当从object对象中获取不到xxx时候返回  第三个参数

    (3)setattr()

    class Movie(object):
        language = '国语'
        def __init__(self,name):
            self.name  = name
    
        def release(self):
            print('%s正在放映'%self.name)
    
    movie =Movie('大话西游')
    setattr(movie,'name','少林足球')   #可以动态的给对象设置属性
    print(movie.name)                 #少林足球
    setattr(movie,'place','内地')     #可以给对象设置属性和值
    print(movie.place)                # 内地

    (4)delattr()

    class Movie(object):
        language = '国语'
        def __init__(self,name):
            self.name  = name
    
        def release(self):
            print('%s正在放映'%self.name)
    
    movie =Movie('大话西游')
                     #少林足球
    setattr(movie,'place','内地')     #可以给对象设置属性和值
    print(movie.place)                # 内地
    
    delattr(movie,'place')
    print(movie.place)                #已删除

    反射共有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成员删除掉           

    注意, 以上操作都是在内存中进行的. 并不会影响你的源代码

  • 相关阅读:
    Markdown的简介(转)
    写在二月的尾巴上
    The Pragmatic Programmer 读书笔记
    C/C++语言的一些精简归纳
    一般常用设计模式及原则的思想小结
    常用UML模型简要小结
    LeetCode 101. Symmetric Tree
    LeetCode 100. Same Tree
    LeetCode 99. Recover Binary Search Tree
    线索二叉树的建立与遍历
  • 原文地址:https://www.cnblogs.com/wcx666/p/9719902.html
Copyright © 2020-2023  润新知