类的反射介绍和应用

#!/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后,将会把导入模块的类放到当前模块的局部变量中
于是,再获取当前模块的类就会有了类名
使用反射就能获取到对应的类,加括号即可执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值