- 泛化:所有子类和父类有一样的特点。特化:描述子类与父类的不同
-
反射/自省
-
class BlackMedium:
feture='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('[%s]正在卖房子,傻逼才买呢'%self.name)
def rent_hourse(self):
print('[%s]正在租房子,傻逼才租呢'%self.name)
b1=BlackMedium('万成置地','天露园')#生成实例
print(hasattr(b1,'name'))#检测实例b1能否调用name的数据属性
print(getattr(b1,'name'))#获取实例b1中的name属性的value
func=getattr(b1,'rent_hourse')#获取实例b1中的函数的地址,等价于b1.rent_hourse
func()#执行上述函数
print(getattr(b1,'rent_hoursesdfsdaf','没有这个属性'))#匹配不到,则返回后边的值
setattr(b1,'sb',True)#给实例b1的字典加个值,key和value
print(b1.__dict__)
setattr(b1,'name','SB')
setattr(b1,'func',lambda x:x+1)#可以实例加函数属性
print(b1.__dict__)
print(b1.func(10))
delattr(b1,'sb')
print(b1.__dict__)
- 反射就是自己找自己,应用场景:适用于团队合作,彼此分工,一人休假,不影响其他人的代码工作。可插拔程序。
-
动态导入模块
- 动态导入的底层就是基于反射做的
- 一切皆对象,模块也是对象
-
m=__import__('dic')#以字符串的形式导入模块。无论dic.套多少层,m只拿到dic
print(m)
m.t.test()#执行m下边t模块的test函数
#m1.t中_test2()函数,在此种*的情况下,不能被导入。
from m1.t import *
from m1.t import test1,_test2#如此方可导入
test1()
test2()
#import importlib
m=importlib.import_module('m1.t')
print(m)
m.test1()#也是以字符串的形式导入上述内容
-
类的内置attr属性
- 类本质上也是一个对象,上述的反射方法同样适用于类
- 双下划线开头的attr方法
-
class Foo:
x=1
def __init__(self,y):
self.y=y
#这三个方法是给实例用的,类不能调用
#以下三个方法系统都有内置,如果用户不定义,则在适当条件下触发系统内置的
def __getattr__(self, item):
print('执行_getattr_')
#__getattr__是python给类的内置方法,如果用户不定义,则执行系统默认的,就是报错。
#如果用户定义,则不报错,执行自定义的函数
#以下两种操作很多余,系统默认__delattr和__setattr_就是在执行这种操作
def __delattr__(self, item):
print('删除操作_delattr_')
#del self.item#无限递归了
self.__dict__pop(item):#操作底层字典进行删除
def __setattr__(self, key, value):#可以加上if判断,实现符合某种条件再设置
print('_setatter_执行')
# self.key=value#这种操作属于设置操作,就会触发_setattr_操作,陷入递归
self.__dict__[key]=value#操作底层字典进行设置
f1=Foo(10)
print(f1.y)
print(getattr(f1,'y'))
f1.ssssss#调用f1没有的属性,则执行getattr函数
del f1.y#删除操作时,会触发__delattr_操作
-
二次加工标准类型的两种方式
-
继承+派生
- str,list,tuple都是类
- class List(list),List继承list类
-
class List(list):
def append(self, p_object):
if type(p_object) is str:
# self.append(p_object) #如此调用,又陷入递归陷阱
# list.append(self,p_object) #调用父类append本身的,建议用super的方法
super().append(p_object)
else:
print('只能添加字符串类型')
def show_midlle(self): # 继承列表的类,并进一步加工,取得字符串得中值
mid_index = int(len(self) / 2)
return self[mid_index]
l1 = List('helloworld')
# print(l1.show_midlle())
l1.append('SB')
print(l1)
l1.append(1212)
-
组合的方式完成授权,效果等价于继承加工
- 授权:授权是包装的一个特性,包装一个类型通常是对已经存在的类型的一些定制,这种做法可以新建,修改或者删除原有产品的功能。其他的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。实现授权的关键点就是覆盖__getattr__方法
- 授权的步骤