类的内置方法:__getattr__,__setattr__,__delattr__
# __getattr__为内置方法,当使用点号[获取实例属性时],如果属性不存在就自动调用__getattr__方法,如类Foo()的对象f.name
# __setattr__当[设置类实例属性时]自动调用,如f.name=5 就会调用__setattr__方法 self.[name]=5
# 这个类是从dict继承来的,是dict的超类
class Foo:
def __init__(self,name):
self.name=name
def hello(self):
print("hello")
#获取实例属性时,属性不存在的情况自动调用
def __getattr__(self, item):
# 打印属性不存在时的属性和类型
print("%s %s"%(item,type(item)))
# 当[设置类实例属性时]自动调用
def __setattr__(self, key, value):
print(self,key,value)
if not isinstance(value,str):
raise TypeError("must be str")
else:
self.__dict__[key]=value
def __delattr__(self, item):
self.__dict__.pop()
f=Foo("adamanter")
f.hello()
f.name #类有这个属性,不会调用__getattr__
f.food #类没有这个属性,会调用__getattr__,显示food <class 'str'>,属性是food,类型是str
f.eat #类没有这个属性,会调用__getattr__,显示eat <class 'str'>,属性是eat,类型是str
f.name = "antonio" #设置调用__setter__,打印本身<__main__.Foo object at 0x1011bff28> name antonio,也放入了f字典
#f.age =18 #报错,因为不符合设置属性时候,我们判断的是必须是字符串,因此抛出:must be str
print(Foo.__dict__) #里面有hello函数
print(f.__dict__) #里面有{'name': 'adamanter'}
# {'__setattr__': <function Foo.__setattr__ at 0x10842fbf8>, '__init__': <function Foo.__init__ at 0x10842fae8>,
# '__getattr__': <function Foo.__getattr__ at 0x10842fb70>, '__dict__': <attribute '__dict__' of 'Foo' objects>,
# '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__delattr__': <function Foo.__delattr__ at 0x10842fc80>,
# '__doc__': None, 'hello': <function Foo.hello at 0x10842fa60>, '__module__': '__main__'}
# {'name': 'adamanter'}
python面向对象中的反射:hasattr,getattr,setattr,delattr
# python面向对象中的反射:通过字符串的形式操作对象相关的属性。
# python中的一切事物都是对象(都可以使用反射)
# 四个可以实现自省的函数
# 下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
# 基于类的反射
class People:
country="china"
def __init__(self,name):
self.name=name
def walk(self):
print("%s walk",self.name)
h=People("ada")
# 利用布尔值返回类或对象有没有这个属性,hasattr返回布尔值
print(hasattr(People,"country"))
print(hasattr(h,"country"))
print(hasattr(h,"walk"))
# True
# True
# True
#获取类或对象的某个属性,getattr回值就是获取的属性值或绑定的方法
res1=getattr(People,"country")
print(res1)
res2=getattr(h,"country")
print(res2)
res3=getattr(h,"walk")
print(res3)
# china
# china
# <bound method People.walk of <__main__.People object at 0x10f7e75f8>>
#设置类或对象的某个属性并查看,setattr返回None,但是属性已经添加
sss = setattr(h,"age",18)
print(sss)
print(h.__dict__)
# None
# {'name': 'ada', 'age': 18}
#删除类或对象的某个属性并查看,delattr返回None,但是属性已经删除
ddd = delattr(h,"age")
print(ddd)
print(h.__dict__)
# None
# {'name': 'ada'} 因为没有age属性,不可修改属性
基于模块的反射
# 反射当前模块的属性
import sys
x=1111
class Foo:
pass
def s1():
print('s1')
def s2():
print('s2')
this_module=sys.modules[__name__]
print(this_module)
# <module '__main__' from '/Users/Alex/PycharmProjects/hellotest/python/反射.py'>
#这句话所做的操作:遍历s1在不在this_module 的字典__dict__中
print(hasattr(this_module,'s1'))
print(getattr(this_module,'s2'))
print(this_module.s1)
print(this_module.s2)
# True
# <function s2 at 0x101678f28>
# <function s1 at 0x1014a0f28>
# <function s2 at 0x101678f28>
# import importlib
# t=importlib.import_module("time")
# print(t.time())
#导入当前路径下包impag下的hello.py
# x=importlib.import_module("impag.hello")
# 字符串导入模块,官方不推荐
# m=input("please input your module:")
# m1=__import__(m)
# print(m1)
# print(m1.time())
重写自定制列表的append和insert方法
class List(list):
def append(self,object:str):
if not isinstance(object,int):
raise TypeError("must int")
super().append(object)
def insert(self, index: int, object):
if not isinstance(object,int):
raise TypeError("must int")
super().insert(index,object)
l=List([1,2,3])
print(l)
# [1, 2, 3]
l.append(4) #会调用类本身的append方法
print(l)
# [1, 2, 3, 4]
# l.append("hello") 我们重写了append方法,要求他只能接受int
# raise TypeError("must int")
l.insert(0,-1) #第一个0是索引,必需是int,第二个规定是int
# l.insert(0,"hello") #报错,因为我们重写了增加和插入方法,非int类型插入报错,必须是int类型
print(l)
# [-1, 1, 2, 3, 4]