python学习笔记 day27 反射(二)

1. isinstance(obj,cls)  ----查看obj是否为cls的对象;

    issubclass(sub,super)------查看sub是否为super的子类

class A():
    pass
a=A()
print(isinstance(a,A))  # instance(obj,cls)查看obj是否为cls的对象
class B(A):
    pass
print(issubclass(B,A)) # issubclass(sub,super)查看sub是否为super的子类

 

 反射----根据变量的字符串形式获得变量的值;

1.反射对象的属性  VS  反射对象的方法

class Student():
    def __init__(self,name):
        self.name=name  # 对象属性
    def get_name(self):
        return self.name
student=Student("璇璇")
if hasattr(student,'name'):  # 查看对象student是否含有name属性(只是这里是name属性的字符串形式)
    ret=getattr(student,'name')
    print('使用反射获得对象的属性',ret)
if hasattr(student,'get_name'):
    ret=getattr(student,'get_name')  # ret其实就是student.get_name 反射对象的方法,从对象方法的字符串形式获得该对对象的方法
    print("使用反射调用对象的方法:",ret())

 

运行结果:

2. 反射类中的属性和方法;

class Person():
    country='China'  # 类属性,又叫静态属性
    @classmethod  # 定义类方法
    def func(cls):
        print("这是类方法,类属性的值为:",cls.country)
    @staticmethod
    def func2():
        print("这是静态方法,里面不需要传self,cls等就是放在类中的普通函数")
if hasattr(Person,'country'):  # 查看类中是否有country静态属性
    ret=getattr(Person,'country')
    print("使用反射根据类中静态属性的字符串形式获得静态属性的值:",ret)
if hasattr(Person,'func'):
    ret=getattr(Person,'func') # 使用反射根据类方法的字符串形式获得类方法ret ,ret相当于Person.func
    ret()
if hasattr(Person,'func2'):  #反射类的静态方法
    ret=getattr(Person,'func2')
    ret()

 

运行结果:

 

 3. 反射模块中的属性和方法:

首先需要导入的模块 test.py中:

# 这个模块需要被test1.py导入的,测试模块中的反射
name='xuanxuan'
def func():
    print("我是被导入模块test.py中的方法")

 

import test # 导入test模块
if hasattr(test,'name'): # 查看被导入的模块是否含有name属性,这里是name的字符串形式,
    ret=getattr(test,'name')  # 可以使用getattr对象属性的字符串形式获得对象的属性
    print("使用反射获得模块中属性的值:",ret)
if hasattr(test,'func'):  # 查看模块test是否含有func方法
    ret=getattr(test,'func')
    ret()

 

运行结果:

 

 4. 内置模块也可以使用反射

比如用户输入time模块的一个方法名,需要用户输出time模块中该方法,但是我们不能直接使用,因为用户输入获得的是一个字符串形式的函数名,我们需要使用getattr(模块名,字符串形式的方法名)获得该模块的该方法

import time
func_name=input(">>>")
if hasattr(time,func_name):  # 查看time模块是否含有func_name,只不过这里收到的是字符串形式
    func=getattr(time,func_name)  # 比如输入localtime, func就相当于time.localtime
    print(func())  # 输入localtime func()相当于time.localtime()

运行结果:

 

 5. 反射自己模块中的属性和方法

这里需要注意,当前py文件获得当前py文件(模块名)可以使用sys.modules字典中 __name__键对应的值,也即使用sys.modules[__name__]就可以获得当前的模块名(其实就是当前py文件的文件名);

import sys
name='xuanxuan'
def func():
    return "我是当前文件中的方法"
# 我们可以直接使用name,或者直接调用func()函数
print(name)
print(func())

# 当然也可以使用这种方式来获得当前模块(当前py文件)的属性和方法:
print(sys.modules[__name__])  # 可以打印当前模块名
print("使用sys.modules[__name__]获得当前模块名,使用这种方式调用当前模块中的属性:",sys.modules[__name__].name)  # 这样也可以获得当前模块中的name变量,但是我们通常不去这样做,因为在自己的模块中就直接可以使用属性和方法
print("使用sys.modules[__name__]来获得当前模块名,然后使用模块名.方法获得当前模块中的方法:",sys.modules[__name__].func())

print("*******************接下来使用反射获得当前模块中的属性和方法,比如你在当前模块拿到的是'name'或者'func'这种字符串形式的")
if hasattr(sys.modules[__name__],'name'):  # 查看当前模块sys.modules[__name__]是否含有name属性
    ret=getattr(sys.modules[__name__],'name')
    print("使用反射获得当前模块的name属性的值:",ret)
if hasattr(sys.modules[__name__],'func'):  # 查看当前模块是否含有方法名func
    ret=getattr(sys.modules[__name__],'func')
    print('使用反射获得当前模块的方法func:',ret())

 

 运行结果:

 

 6. 一个模块中的类也可以使用反射获得:

被导入模块test.py中的内容:

# 这个模块需要被test1.py导入的,测试模块中的反射
class A():
    def func(self):
        print("我是被导入的模块中的类 中的方法")

 

import test
if hasattr(test,'A'): # 查看导入的模块test中是否含有类A,但是有可能我们拿到的是字符串形式的'A'
    cls=getattr(test,'A')   # cls相当于test.A其实就是类A
    obj=cls()   # obj 其实相当于导入模块test中类A的对象
    obj.func()  # 可以使用类A的对象obj调用在类A中定义的方法func

运行结果:

 

 总结:

只要是可以用 什么.什么 的形式来调用的都可以使用反射来完成通过拿到的字符串形式,获得本来的值;

setter ----设置修改属性 ;  delattr----删除属性

class A():
    def func(self):
        print("类A中的方法")
setattr(A,'name','名字') # 设置类A的类属性,静态属性,这个属性依然是字符串类型的,但是实际上操作的确是不带引号的
print("类A中的name属性值:",A.name)  # 类属性
a=A()
setattr(a,'name','璇璇')  # 设置对象的name属性
print("对象a中的name属性值:",a.name)

运行结果:

但是如果delattr删掉对象a中的name属性呢?

class A():
    def func(self):
        print("类A中的方法")
setattr(A,'name','名字') # 设置类A的类属性,静态属性,这个属性依然是字符串类型的,但是实际上操作的确是不带引号的
print("类A中的name属性值:",A.name)  # 类属性
a=A()
setattr(a,'name','璇璇')  # 设置对象的name属性
print("对象a中的name属性值:",a.name)
delattr(a,'name')  # 反射中的一些方法,,操作的对象都素hi字符串类型的,我们就是想通过这些字符串类型的属性或者方法,来获得实际不带引号的属性和放啊
print("删掉对象a中的name属性之后,对象的属性没有了,但是a.name时 由对象指针会去类中去找对应的属性:",a.name)

运行结果:

 

posted @ 2018-09-22 16:05  写的BUG代码少  阅读(179)  评论(0编辑  收藏  举报