欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python学习 day018打卡 反射

程序员文章站 2022-05-04 13:49:37
本节主要内容: 1.isinstance,type,issubclass 2.区分函数和方法 3.反射(重点) 一.isinstance,type,issubclass issubclass():判断xxx类是否是yyy类型的子类 type(obj):查看obj是由哪个类创建的. type()可以帮 ......

本节主要内容:

1.isinstance,type,issubclass

2.区分函数和方法

3.反射(重点)

 

一.isinstance,type,issubclass

issubclass():判断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)) # ture

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

class foo:
    pass

obj = foo()
print(type(obj))    # <class '__main__.foo'>

type()可以帮我们判断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(),boy(),girl(),boy(),girl(),boy())
print(ret)

 

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

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)) # ture

 

isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)

 

二,区分函数和方法

def func():
    pass

print(func) #<function func at 0x00000265b9e12e18>

class foo:
    def chi(self):
        print("我是吃")

foo = foo()
print(foo.chi)  # <bound method foo.chi of <__main__.foo object at 0x00000265ba00c908>>

  函数在打印的时候,很明显显示的是function.而方法在打印的时候很明显是method.但是在类里面就不一定了:

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 0x0000016b23aec978>>
print(foo.chi)  # <function foo.chi at 0x0000016b23acdf28>
print(foo.static_method)    # <function foo.static_method at 0x0000016b23af4048>
print(foo.class_method) # <bound method foo.class_method of <class '__main__.foo'>>
print(f.static_method)  # <function foo.static_method at 0x0000016b23af4048>
print(f.class_method)   # <bound method foo.class_method of <class '__main__.foo'>>

 

通过观察上面代码的结果,我们可以得出以下结论:

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

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

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

 

我们可以通过借助types模块来帮我们分辨到底谁是函数,谁方法

from types import functiontype, methodtype

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

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

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


# 实例方法:
#     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

# functiontype:函数
# methodtype: 方法

 

插入: 我们写的类也可以看做是对象,类的类型是type,即type(类) ==><class 'type'>

 

三.反射

反射:所谓反射就是通过字符串来动态访问模块中的功能.通过手动输入需要运行的功能,反着去模块里找,这个就叫反射

# master.py

def chi():
    print("大牛很能吃")

def he():
    print("大牛从来不喝")


def la():
    print("大牛就知道拉")

def sa():
    print("大牛说撒是什么")
import master

while true:
    s = input("请输入你要测试的功能:")

    if hasattr(master,s):
        func = getattr(master,s)
        func()
    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 方法

 总结,getattr()可以从模块中获取内容,也可以从类中获取内容,也可以从对象中获取内容.在python中一切皆为对象,那可以这样认为.getattr从对象中动态的获取成员

 

关于反射,一共有4个函数:

1.hasattr(obj,str)判断obj中是否包含str成员

2.getattr(obj,str)从obj中获取str成员

3.setattr(obj,str,value)吧obj中的str成员设置成value.注意,这里的value可以是值,也可以是函数或者方法.如果str不存在,就创建新的成员,把值赋值给新成员

4.delattr(obj,str)把obj中的str成员删除掉

 

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

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
print(f.chi) # 此时的chi既不是静态方法,也不是实例方法,更不是类方法.就相当于你在类中写了个self.chi = lambda 是一样的
print(f.__dict__)   # {'chi': <function <lambda> at 0x00000238e1392e18>}

delattr(f,"chi")
print(hasattr(f,"chi")) # false