Python学习 Day 019 - 反射

主要内容:

  • 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. 区分函数和方法

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

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

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>
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>

结论:

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

另外:用types中的FunctionType和MethodType可以区分, 当前内容是方法还是函数,

from types import MethodType,FunctionType
class Foo:
    @classmethod
    def func1(self):
        pass
    @staticmethod
    def func2(self):
        pass
    def func3(self):
        pass
    def func4(self):
        pass
    lst = [func1, func2, func3]
obj = Foo()
Foo.lst.append(obj.func4)
for item in Foo.lst:
    print(isinstance(item,MethodType))
    #  print(isinstance(item,FunctionType))

3.反射

一个需求, 说, 有个大牛, 写l一堆特别牛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("请输入你要测试的功能")
    if hasattr(master,val):
        attr = getattr(master,val)                # 从xxx对象或者模块中找xxxxx(字符串) 功能, 变量
        if callable(attr):                        #判断这个东西是否可以被调用
            attr()
        else:
            print(attr)
    else:
        print("没有这个功能")

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

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

在面向对象中:

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 方法
class Person:
    def __init__(self,name):
        self.name = name
        self .age = None
    def chi(self):
        print("%s喜欢吃东西" % self.name)
p = Person("张三")
# p.chi()
val = input("请输入你想让张三执行的动作:")
if hasattr(p,val):
    func = getattr(p,val)
    func()

另外:

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)

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

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

猜你喜欢

转载自www.cnblogs.com/wcx666/p/9719902.html