反射,__setattr__,__getattr__,__delattr__
1.isinstance用法
isinstance(x,y):用于判断x是不是y类型的数据,返回布尔值
判断x对象是不是由y这个类实例化的
a="egon" class People: def walk(self): print("walking") p=People() isinstance(a,str) res=isinstance(p,People) print(res)
2.issubclass用法
issubclass(x,y):用于判断x是不是y的子类,返回布尔值
class Anmail: def __init__(self,an_type): self.name=an_type def walk(self): print("walking") class People(Anmail): def __init__(self,name): self.name=name print(issubclass(People,Anmail))
3反射(hasattr,setattr,getattr,delattr)用法
hasattr(x,“name”)判断x中是否含有字符串name属性或者方法
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
需要注意的是name要用括号括起来
x:可以是类,可以是对象
y:属性的变量名
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon","20","男") print(hasattr(p,"name")) #True print(hasattr(p,"walk")) #True
setattr(x,"name",value)把x对象中字符串name(属性)的值修改为value
给对象的属性赋值,若属性不存在,先创建再赋值。
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon","20","男") print(setattr(p,"name","alex")) #p.name=alex print(setattr(p,"walk","zou")) #{'sex': '男', 'name': 'alex', 'walk': 'zou', 'age': '20'}
getattr(x,"name",None)
获取到x中name的属性,如果name是数据属性则返回的是一个值,如果name是一个方法则返回一个内存name的内存地址
多加参数None表示,如果x中没有name属性,不会报错,会返回一个None值
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon","20","男") print(getattr(p,"name")) #egon print(getattr(p,"walk")) #<bound method People.walk of <__main__.People object at 0x000001FCE4FFFBA8>> getattr(p,"walk")() #======>walking
delattr(x,"name")
删除x中name的数据属性,不能删name的方法
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon","20","男") delattr(p,"name") print(p.__dict__) #{'sex': '男', 'age': '20'}
4__setattr__,__getattr__,__delattr__的用法
__setattr__
`__setattr__`函数是用来设置对象的属性,通过object中的__setattr__函数来设置属性:
class People: def __init__(self,name,age,sex): self.name=name #走到self.name的时候就会先执行__setattr__,self.name表示self.__dict__[name] self.age=age self.sex=sex def __setattr__(self, key, value): if not isinstance(value,str): #可实现在实例化的时候定制一套规则,必须是什么样的数据类型 raise TypeError("参数必须是字符串") self.__dict__[key]=value #往字典__dict__中加入属性key=value def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon",20,"男") #报错 p=People("egon","20","男") #正常
__getattr__
从对象中读取某个属性时,首先需要从self.__dicts__中搜索该属性,再从__getattr__中查找,如果类中没有对象调用的属性时,就会执行__getatter__这个函数
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __getattr__(self, item): #如果类中没有对象调用的属性时,就会执行这个函数 print("没有这个属性") def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon","20","男") p.drink #没有这个属性
__delattr__
`__delattr__`函数式用来删除对象的属性:
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __delattr__(self, item): #找到self.__dict__[item],删除 #self.__dict__.pop(item) del self.__dict__[item] def walk(self): print("======>walking") def eat(self): print("======>eatting") p=People("egon","20","男") del p.name print(p.__dict__) #{'sex': '男', 'age': '20'}
5 定制自己的数据类型:
1.继承的方式
#用继承的方式定制一个新list的方法 class List(list): def append(self, object): #派生出自己新的append功能,可以添加一个验证追加元素的必须是字符串 if not isinstance(object,str): raise TypeError("追加的必须是字符串") super().append(object) #super()只能使用到该类的上一级 l=List([7,8,9]) l.append("s") #正常 # l.append(5) #报错 l.insert(0,4) #由于是继承的关系,可继续使用list的所有功能
2.授权的方式
#用授权的方式来自制一个日志的记录文件 """ 思路:日志文件必须包括日期,使用者全部记录到一个文件中 方法:先获取到文件的句柄,把句柄当做一个对象来操作 """ import time class Open: def __init__(self,name,mode="r",encoding="utf-8"): self.name=name self.mode=mode self.encoding=encoding self.x=open(name, mode=mode, encoding=encoding) def write(self,line): t=time.strftime("%Y-%m-%d %x") self.x.write("%s %s"%(t,line)) self.x.flush() def __getattr__(self,item): print("zhao budao gongnege") if not hasattr(self.x,item): print("没有%s功能"%item) else: print(item) return getattr(self.x,item) f=Open("log.log","w",encoding="utf_8") f.write("22222222")
6 通过字符串导入模块
通过__import__导入(官方不推荐使用)
#输入time m=input("请输入需要导入的模块:") model=__import__(m) print(model.time())
推荐使用
import importlib t=importlib.import_module("time") print(t.time())
7 练习
# 基于授权定制自己的列表类型,要求定制的自己的__init__方法, class List: def __init__(self,*args): self.x=list(*args) def __str__(self): return str(self.x) # 定制自己的append:只能向列表加入字符串类型的值 def append(self, object): if not isinstance(object, str): raise TypeError("必须追加字符串类型的数据") return self.x.append(object) # 定制显示列表中间那个值的属性(提示:property) @property def middle(self): n=int(len(self.x)/2) return self.x[n] # 其余方法都使用list默认的(提示:__getattr__加反射) def __getattr__(self, item): if not hasattr(self.x,item): print("没有%s方法"%(item)) else: return getattr(self.x,item) l=List((1,2,4,5)) l.append("2") print(l) res=l.middle print(res)