#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/5/20 23:27
# @Author : chen
# @File : 反射.py
"""
# 反射: 通过字符串映射到对象的属性
"""
"""
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def talk(self):
print('%s is talking' % self.name)
obj = People('egon', 18)
print(obj.name) # .(点)后面是一个属性,不是字符串,
# 本质上是 obj.__dict__['name'] 是隐藏字典里key为'name'的值
print(obj.talk) # 点后面一定时一个属性,不是字符串
print(obj.talk())
# 接受用户的输入,使用input方法,接收内容都转化为字符串
# 需求,根据用户输入 返回对象的属性
# choice = input('>>: ')
# print(obj.choice) # 会直接报错(AttributeError:
# 'People' object has no attribute 'choice'),点后面应该是属性,而不是字符串
# 1.python 内置方法 hasattr,有两个参数,第一个是对象,第二个是实例的属性
# 只能返回True 和 False
print(hasattr(obj, 'name')) # 实际操作等于 obj.name 等同于 obj.__dict__['name']
print('attribute_talk', hasattr(obj, 'talk')) # obj.talk
print('attribute_talka', hasattr(obj, 'talka')) # obj.talk
# 2.getattr() 跟hasattr差不多,但不存在的属性可以加参数不报错
# 第一个,第二个参数跟hasattr一样,第三个指定返回的结果(字符串)
print(getattr(obj, 'talk', None)) # 当调用的是类的方法时,返回的结果是绑定类的方法的地址
# 如果是属性就直接返回结果
print(getattr(obj, 'namexxxx', None))
print(getattr(obj, 'namexxxx', 'Error'))
# 3.以字符串的形式 ,设置属性(新增)
setattr(obj, 'sex', 'male') # obj.sex = 'male'
print(obj.sex)
# 4. 以字符串形式 删除属性
delattr(obj, 'age') # obj.age
print(obj.__dict__)
"""
"""
class People:
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def talk(self):
print('%s is talking' % self.name)
obj = People('egon', 18)
# 5. 同时适用于类,判断类中有没有国籍这个属性
print(getattr(People, 'country')) # People.country
# 通过字符串,访问对象,类的属性
"""
# 反射的应用
# 接收用户输入,触发查询属性
class Service:
def run(self):
while True:
inp = input('>>: ').strip() # cmd = 'get a.txt'
cmds = inp.split() # cmds = ['get', 'a.txt']
if len(cmds) == 2: # 判断用户输入是否正确
if hasattr(self, cmds[0]):
# 这里要使用self,不能随便使用别的,我使用的Service,报错了,就是因为传参问题
func = getattr(self, cmds[0])
func(cmds[1])
else:
print('has no attribute')
else:
print('your cmds is wrong')
def get(self, cmds):
print('get......', cmds)
def put(self):
print('put......')
obj = Service()
obj.run()
getattr反射的使用
getattr(class,‘str’)
第一个参数填class,第二个使用的是字符串(函数名)
另外一种用法
getattr(class,‘str’),第一个参数是模块名称,第二个是类名
import sys
class Course:
def __init__(self, name, period, price):
self.name = name # 课程名
self.period = period # 课程周期
self.price = price # 课程价格
print('type类型:', type(sys.modules[__name__]), '值结果:', sys.modules[__name__])
s = getattr(sys.modules[__name__], 'Course')
print('s的type类型:', type(s))
a = s('egon', '6 months', 19800)
print('a的type类型:', type(a))
print('a的name属性:', a.name)
输出结果:
type类型: <class 'module'> 值结果: <module '__main__' from 'D:/python_product/select_homework/core/Teacher.py'>
s的type类型: <class 'type'>
a的type类型: <class '__main__.Course'>
a的name属性: egon
==================================================================
sys.modules[__name__]
# 表示当前模块的名称
虽然当前模块没有类,但是使用了import后,将会把导入模块的类放到当前模块的局部变量中
于是,再获取当前模块的类就会有了类名
使用反射就能获取到对应的类,加括号即可执行