zoukankan      html  css  js  c++  java
  • 方法&函数区别,反射

    主要内容:

    • 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成员删除掉           

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

  • 相关阅读:
    Java for LeetCode 229 Majority Element II
    Java for LeetCode 228 Summary Ranges
    Java for LeetCode 227 Basic Calculator II
    Java for LintCode 颜色分类
    Java for LintCode 链表插入排序
    Java for LintCode 颠倒整数
    Java for LintCode 验证二叉查找树
    Java for LeetCode 226 Invert Binary Tree
    Java for LeetCode 225 Implement Stack using Queues
    Java for LeetCode 224 Basic Calculator
  • 原文地址:https://www.cnblogs.com/wcx666/p/9719902.html
Copyright © 2011-2022 走看看