反射机制

反射机制

image

1、python动态语言,何为动态

x = 10

  在python里,定义变量时,可以不用直接声明数据类型,而在后面用到时,可以直接识别到当前数据的数据类型,
也就是说,在我用到这个变量的时候才获取到了数据的当前数据类型,这也就是动态语言的由来,
  所谓的静态语言,就是我在定义变量的时候就声明了变量的数据类型,例如说数据库里的char和varchar是在定义时就指明了数据的数据类型,在以后用到时候不再是临时获取到数据的数据类型,
  而之所以可以在用到的时候可以获取到,这其实就是反射机制所做的事

image

2、什么是反射机制

所以什么是反射机制:
	即在程序运行的时候'动态'获取对象(python里一切皆对象)的信息(数据属性和方法属性)

3、为什么要用反射机制

利用反射机制可以实现在需要用到某个对象时,获取到该对象的一些信息,而不是再利用一些复杂的逻辑来实现

image

4、如何实现反射机制

其实在python里实现反射机制很简单
1、先通过python内置的dir方法获取到当前对象所具备的一些属性
2、利用反射机制反射出对象的属性,从而获取到对应的属性值
# 示例:
# 这里先创建一个类
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 实例化一个对象
stu1 = Student('jason', 18)
# 1、通过dir方法获取对象所具备的属性
print(
    dir(stu1))  # ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
'''得到的是一个关于当前对象所具有的属性的列表,且列表里的每一个属性都是字符串,
那么问题来了,我们想要通过对象属性获取对象的属性值的时候,实际上应该是通过字符串来
操作获取的,但是我们会发现,我们在获取对象属性的时候,是通过对象点属性的方式,而不是
对象点字符串来获取的,那这两者是不是冲突了:我可以通过对象点属性的方式获取对象属性值,但是对象的属性又是
字符串的形式,而我还不能通过对象点字符串来获取。
事实上,有一种方式可以通过字符串的方式获取到对象的属性值
'''
1、先利用列表索引取值的方式取出来stu1的name属性
2、再通过对象__dict__方法获取
print(stu1.__dict__[dir(stu1)[-1]])  # jason
'''从上面的例子里可以看出来,其实我们可以通过dict内置方法来获取到对象的属性值,但是有一点要注意,
并不是所有的对象都具有dict方法的,以下面的实例为例'''
name = 'jason'
# print(name.__dict__)
'''上面的结果会报错,报错的原因是:字符串没有dict这个方法,那么问题来了,
既想通过字符串的方式来获取属性值,又不能用dict方法,那怎么办
其实python作为一中动态语言,在设计之初就已经对这种情况做出了应对机制,
下面就是我们要说的内置方法四兄弟'''
hasattr()  # 查看属性是否在其相对应的对象属性列表里
getattr()  # 获取对象的属性值
setattr()  # 赋值操作
delattr()  # 删除操作

image

5、反射方法

# 反射方法
# 什么是反射方法:通过字符串操作属性或者方法
# 1、getattr
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def read(self):
        print('%s' % self.name)


# 实例化对象
stu1 = Student('jason', 20)
# 利用点的方式查看对象的属性
print(stu1.name)
# 如何通过字符换来操作
# 方法一:
print(stu1.__dict__['name'])
# # 方法二:
print(getattr(stu1, 'name'))
'''
以上的几种方法好像都可以实现查看对象的值,但是有一点要注意,
正常点的方式和用dict方法取值的方式,当对象的属性不存在时会直接报错,
但是getattr方法不一样,getattr方法可以传入第三个参数,
在我们访问的属性不存在时,不会报错,会返回第三个参数,不传参数则报错
'''

# 示例:
print(getattr(stu1, 'name1', '不存在'))  # 不存在
# 2、setattr
# 示例:
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def read(self):
        print('%s' % self.name)


# 实例化对象
stu1 = Student('jason', 20)
# 正常点的方式修改属性数据
stu1.name = 'jasonNB'
print(stu1.name)  # jasonNB
# 通过字符串的方式修改
# 方式一:
stu1.__dict__['name'] = 'jasonNB'
print(stu1.name)  # jasonNB
# # 方式二:
setattr(stu1, 'name', 'jasonNB')
print(stu1.name)  # jasonNB
# 3、delattr
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def read(self):
        print('%s' % self.name)


# 实例化对象
stu1 = Student('jason', 20)
# 正常点的方式删除属性数据
del stu1.name
print(stu1.__dict__)  # {'age': 20}
# 通过字符串的方式修改
# 方式一:
del stu1.__dict__['name']
print(stu1.__dict__)  # {'age': 20}
# 方式二:
delattr(stu1, 'name')
print(stu1.__dict__)  # {'age': 20}
# 4、hasattr
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def read(self):
        print('%s' % self.name)


# 实例化对象
stu1 = Student('jason', 20)
# 查看对象是否具有某个属性
print(hasattr(stu1, 'name'))  # True
print(hasattr(stu1, 'name1'))  # False
'''
其实对于getattr、delattr、hasattr方法,不仅可以对对象里的属性和方法进行操作,
也可以对类里的属性和方法进行操作
'''
# getattr

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def read(self):
        print('%s:%s' % (self.name, self.age))


# # 实例化对象
stu1 = Student('jason', 20)
# 获取对象里的方法并调用
getattr(stu1, 'read')()  # jason:20
# 获取类里的方法并调用
getattr(Student, 'read')(stu1)  # jason:20
'''
其实对于我们平时所导入的模块来说,一样可以用getattr方法操作
'''
import time
# 获取时间戳
# 正常获取
print(time.time())  # 1638879367.0702362
# getattr方法获取
print(getattr(time, 'time')())  # 1638879367.0702362
'''
其实对于导入模块来说,我们平常用的都是import 模块名或者from...import...句式导入,
此外我们也可以用字符串的方式导入模块
'''


time = __import__('time')  # 了解即可
print(time.time())  # 1638879518.6852396
hasattr
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def read(self):
        print('%s:%s' % (self.name, self.age))


# 实例化对象
stu1 = Student('jason', 20)
# 查看类是不是拥有某个属性或者方法
print(hasattr(Student, 'name'))  # False
print(hasattr(Student, 'read'))  # True

image

posted @ 2021-12-08 23:59  PyLy  阅读(173)  评论(0)    收藏  举报

念两句诗

入我相思门,知我相思苦,长相思兮长相忆,短相思兮无穷极。
【唐代】李白