菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
357
0

反射

原创
05/13 14:22
阅读数 7761
'''
什么是反射:
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)
'''

# isinstance(obj, cls)检查obj是否是类cls的对象
class Foo:
pass

obj = Foo()
print(isinstance(obj, Foo)) # True

# issubclass(sub, super)检查sub类是否是super类的派生类
class A:
pass

class B(A):
pass

print(issubclass(B, A)) # True


'''四个可以实现自省的函数,下列方法适用于类和对象'''
class Black_Medium:
feture = 'Ugly'
def __init__(self, name, addr):
self.name = name
self.addr = addr

def sell_hourse(self):
print('%s正在卖房子' % self.name)

def rent_hourse(self):
print('%s正在出租房子' % self.name)

b1 = Black_Medium('乐有家', '深圳湾')

# ①hasattr(object, name)判断object中有没有一个name字符串对应的方法或属性
print(hasattr(b1, 'name')) # True;b1.name--->b1.__dict__['name']
print(hasattr(b1, 'sell_hourse')) # True,其实也相当于检测b1能否调用所对应的数据属性和函数属性

# ②getattr(object, name, default=None)
print(getattr(b1, 'name')) # '乐有家'
print(getattr(b1, 'sell_hourse')) # <bound method Black_Medium.sell_hourse of <__main__.Black_Medium object at 0x000001BC3D4C0160>>
print(getattr(b1, 'name1', '没找到')) # 当寻找的方法或属性不存在时,打印第三个参数;如果不存在且不传入第三个参数,那么会报错

# ③setattr(x, y, v)添加修改属性
setattr(b1, 'sb', 18) # 相当于b1.sb=18
setattr(b1, 'name', 'SB')
setattr(b1, 'func', lambda x: x+1) # 添加函数属性
print(b1.func(2))
setattr(b1, 'rent_hourse', lambda x: x**2) # 修改函数属性
print(b1.rent_hourse(3))
print(b1.__dict__) # {'name': 'SB', 'addr': '深圳湾', 'sb': 18}

# ④delattr(x, y)删除属性
delattr(b1, 'sb') # 相当于del b1.sb
# delattr(b1, 'aaa') # 不存在则报错
print(b1.__dict__) # {'name': 'SB', 'addr': '深圳湾'}


'''反射的好处'''

# 实现可插拔机制(可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能)
class FtpClient:
'''ftp客户端,但是还没有实现具体的功能'''
def __init__(self, addr):
self.addr = addr
print('正在连接服务器%s' % self.addr)

def get(self):
'''后续又实现了该功能'''
print('正在获取文件信息...')

# 另一个模块代码
# from day51 import FtpClient
#
# f1 = FtpClient('198.1.1.1')
# if hasattr(f1, 'get'):
# func_get = getattr(f1, 'get')
# func_get()
# else:
# print('方法未实现')


# 模块信息为字符串形式的第一种导入方法
# m = __import__('my_module.web.web1.web2.cal')
# print(m) # <module 'my_module' from 'C:\\Users\\XHP\\PycharmProjects\\python_quanzhan\\s1\\my_module\\__init__.py'>显示最顶级文件目录的信息
# print(m.web.web1.web2.cal.add(3, 4))

# 模块信息为字符串形式的第二种导入方法(最好是用这种)
# import importlib
# n = importlib.import_module('my_module.web.web1.web2.cal')
# print(n) # <module 'my_module.web.web1.web2.cal' from 'C:\\Users\\XHP\\PycharmProjects\\python_quanzhan\\s1\\my_module\\web\\web1\\web2\\cal.py'>显示所导入模块的信息
# print(n.add(3, 4))


# 当所导入模块有私有方法时该如何导入
# from my_module.web.web1.web2.cal import add,_add1 # 当import*的时候,_add1()会报错(就唯独不能*导入)
# print(add(3, 3))
# print(_add1(3, 3))

发表评论

0/200
357 点赞
0 评论
收藏