zoukankan      html  css  js  c++  java
  • python学习12-反射 判断函数与方法(转载)

    一、三个内置函数

    1、issubclass(a, b)  判断a类是否是b类的子类

    class Foo:
    pass

    class Zi(Foo):
    pass

    class Sun(Zi):
    pass
    print(issubclass(Zi,Foo)) #True
    print(issubclass(Zi,Sun)) # False

    issubclass

    复制代码
     1 class Foo:
     2     pass
     3 
     4 class Zi(Foo):
     5     pass
     6 
     7 class Sun(Zi):
     8     pass
     9 print(issubclass(Zi,Foo))  #True
    10 print(issubclass(Zi,Sun))  # False
    复制代码

    2、type(对象)   返回该对象的数据类型,精确识别(即不向上兼容)  

    class Animal:
    pass

    class Cat(Animal):
    pass

    class BosiCat(Cat):
    pass

    c = Cat()
    b = BosiCat()
    print(type(c)) #<class '__main__.Cat'> 会准确说出c是一种Cat,不会说c是一种Animal

    type

    复制代码
     1 class Animal:
     2     pass
     3 
     4 class Cat(Animal):
     5     pass
     6 
     7 class BosiCat(Cat):
     8     pass
     9 
    10 c = Cat()    
    11 b = BosiCat()
    12 print(type(c))   #<class '__main__.Cat'>  会准确说出c是一种Cat,不会说c是一种Animal
    复制代码

    3、isinstance(对象,类)   判断xx对象是否是xxx类 (向上兼容)

    class Animal:
    pass

    class Cat(Animal):
    pass

    class BosiCat(Cat):
    pass

    c = Cat()
    b = BosiCat()

    print(isinstance(c , Cat)) #判断c 是否是一种Cat
    print(isinstance(c,Animal)) #判断c 是否是一种Animal
    print(isinstance(c,BosiCat))

    结果:
    True
    True
    False

    isinstace

    复制代码
    class Animal:
        pass
    
    class Cat(Animal):
        pass
    
    class BosiCat(Cat):
        pass
    
    c = Cat()
    b = BosiCat()
    
    print(isinstance(c , Cat))     #判断c 是否是一种Cat
    print(isinstance(c,Animal))    #判断c 是否是一种Animal
    print(isinstance(c,BosiCat))
     
    结果:
    True
    True
    False
    复制代码

    二、判断函数与方法

    python官方定义:

    函数function —— A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of the body.

    方法method —— A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self).

    从定义看,函数就相当于一个数学公式,它不与其他东西相互关联,传递相应的参数就能用。而方法是,定义在类内部的函数,并且这个函数和类或类的实例对象有某种关联,访问时会自动传递一个参数作为第一参数。

    简单来说:

    函数没和类或对象进行绑定;

    方法和类或对象有绑定

    # 区分函数和方法:

    def func():
    pass
    print(func) # <function func at 0x10646ee18> 函数
    class Foo:

    def chi(self):
    print("我是吃")
    f = Foo()
    print(f.chi) # <bound method Foo.chi of <__main__.Foo object at
    0x10f688550>> 方法

    函数和方法

    复制代码
     1 def func():
     2  pass
     3 print(func) # <function func at 0x10646ee18>  函数
     4 class Foo:
     5 
     6  def chi(self):
     7  print("我是吃")
     8 f = Foo()
     9 print(f.chi) # <bound method Foo.chi of <__main__.Foo object at
    10 0x10f688550>>    方法
    复制代码

    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 class Foo:
     2      def chi(self):
     3          print("我是吃")
     4      @staticmethod
     5      def static_method():
     6          pass
     7      @classmethod
     8      def class_method(cls):
     9          pass
    10 
    11 f = Foo()
    12 
    13 print(f.chi) # <bound method Foo.chi of <__main__.Foo object at
    14 0x10f688550>>
    15 
    16 print(Foo.chi) # <function Foo.chi at 0x10e24a488>
    17 print(Foo.static_method) # <function Foo.static_method at 0x10b5fe620>
    18 print(Foo.class_method) # bound method Foo.class_method of <class
    19 '__main__.Foo'>>
    20 
    21 print(f.static_method) # <function Foo.static_method at 0x10e1c0620>
    22 print(f.class_method) #<bound method Foo.class_method of <class
    23 '__main__.Foo'>>            
    复制代码

    结论:

    1. 类方法. 不论任何情况, 都是方法.

    2. 静态方法, 不论任何情况. 都是函数

    3. 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数.

    #官方判断方法:

    通过types模块引入MethodType  FunctionType 来判断

    from types import FunctionType, MethodType

    class Car:
    def run(self): # 实例方法
    print("我是车, 我会跑")

    @staticmethod
    def cul():
    print("我会计算")

    @classmethod
    def jump(cls):
    print("我会jump")

    c = Car()

    实例方法:
    # 1. 用对象.方法 方法
    # 2. 类名.方法 函数
    c = Car()
    print(isinstance(c.run, FunctionType)) # False
    print(isinstance(Car.run, FunctionType)) # True
    print(isinstance(c.run, MethodType)) # True
    print(isinstance(Car.run, MethodType)) # False

    # 静态方法 都是函数
    print(isinstance(c.cul, FunctionType)) # True
    print(isinstance(Car.cul, FunctionType)) # True
    print(isinstance(c.cul, MethodType)) # False
    print(isinstance(Car.cul, MethodType)) # False

    # 类方法都是方法
    print(isinstance(c.jump, FunctionType)) # False
    print(isinstance(Car.jump, FunctionType)) # False
    print(isinstance(c.jump, MethodType)) # True
    print(isinstance(Car.jump, MethodType)) # True

    判断

    复制代码
     1 from types import FunctionType, MethodType
     2 
     3 class Car:
     4     def run(self): # 实例方法
     5         print("我是车, 我会跑")
     6 
     7     @staticmethod
     8     def cul():
     9         print("我会计算")
    10 
    11     @classmethod
    12     def jump(cls):
    13         print("我会jump")
    14 
    15 c = Car()
    16 
    17 实例方法:
    18 #     1. 用对象.方法   方法
    19 #     2. 类名.方法     函数
    20 c = Car()
    21  print(isinstance(c.run, FunctionType)) # False
    22  print(isinstance(Car.run, FunctionType)) # True
    23  print(isinstance(c.run, MethodType)) # True
    24  print(isinstance(Car.run, MethodType)) # False
    25 
    26 # 静态方法 都是函数
    27  print(isinstance(c.cul, FunctionType)) # True
    28  print(isinstance(Car.cul, FunctionType)) # True
    29  print(isinstance(c.cul, MethodType)) # False
    30  print(isinstance(Car.cul, MethodType)) # False
    31 
    32 # 类方法都是方法
    33 print(isinstance(c.jump, FunctionType)) # False
    34 print(isinstance(Car.jump, FunctionType)) # False
    35 print(isinstance(c.jump, MethodType)) # True
    36 print(isinstance(Car.jump, MethodType)) # True
    复制代码

    三、反射(重点)

    关于反射, 其实一共有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成员删除掉

    注意:

    obj可以是模块,类,实例对象

    以上操作都是在内存中进行的, 并不会影响你的源代码,但是在同一个py文件中,你通过反射修改了类,是会影响到其他对象的。

    复制代码
     1 #反射用到的四个函数,常用的是hasattr 和getattr
     2 # setattr(a,b,c)  a是要操作的对象,b是操作对象中的成员字符串形式,c是修改的值
     3 # getattr(a,b)     有返回值,返回值形式a.b    a是要操作的对象,b是操作对象中的成员字符串形式
     4 #delattr(a,b)      a是要操作的对象,b是操作对象中的成员字符串形式
     5 #hasatter(a,b)     a是要操作的对象,b是操作对象中的成员字符串形式
     6 
     7 class Car:
     8 
     9     def __init__(self,color,pai,price):
    10         self.color = color
    11         self.pai = pai
    12         self.price= price
    13 
    14     def fly(self):
    15         print('我的车会飞')
    16 
    17 c = Car('blue','丰田','18888')
    18 f = getattr(Car,"fly")    #操作对象是类,返回值相当于Car.fly
    19 print(f)      #<function Car.fly at 0x0000000001EA9D08> 这里是函数,没有和类绑定,所以需要下面手动传值
    20 f(c)       # f是函数,没有和类绑定,所以需要手动传值Car.fly(c) ,它是等价于c.fly()的
    21 
    22 #delattr(Car,"fly")    #操作的是类,把类中fly方法删除了
    23 #c.fly()     #报错,没有fly
    24 
    25 c2 =Car("yellow","bmw",20000)
    26 
    27 def fly():
    28     print("通过对象c修改fly方法")
    29     
    30 setattr(c,"fly",fly)         #并没有改变类中的内容,相当于在当前对象中创建了一个fly方法,一个对象是不可能有修改类的权限的
    31 c.fly()       #通过对象c修改fly方法
    32 c2.fly()     #我的车会飞
    33 c3 = Car("blue","奔驰",88888)
    34 c3.fly()      #我的车会飞
    35 setattr(Car,'fly',lambda self:print('通过类名,修改fly方法')) #通过类名修改fly方法
    36 c.fly()     #通过对象c修改fly方法
    37 c2.fly()   #通过类名,修改fly方法
    38 c3.fly()  #通过类名,修改fly方法
    39 c4 = Car("red","悍马",66666)
    40 c4.fly()     #通过类名,修改fly方法
    复制代码
     
  • 相关阅读:
    Elasticsearch系列(4):基本搜索
    Elasticsearch系列(3):Elasticsearch操作入门
    Elasticsearch系列(2):安装Elasticsearch(Linux环境)
    禅道之需求追踪和多角色协作流程
    Linux下Redis服务器搭建
    Sql Server 2008日志满的解决办法
    sql server2008数据库迁移的两种方案
    Linux下Jenkins服务器搭建
    Linux下RabbitMQ服务器搭建
    Linux下GitLab服务器搭建
  • 原文地址:https://www.cnblogs.com/wuyufeng-9-14/p/10336885.html
Copyright © 2011-2022 走看看