反射
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。这个机制被称为反射(反过来让对象或者模块告诉我们他是什么),括号里是我瞎编的
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象、模块(一切皆对象,类本身也是一个对象)
#!/usr/bin/env python # -*- coding:utf-8 -*- import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2') 反射当前模块成员
hasattr(obj, name, /) Return whether the object has an attribute with the given name. This is done by calling getattr(obj, name) and catching AttributeError. getattr(...) getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. setattr(obj, name, value, /) Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v'' delattr(obj, name, /) Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y''
sys.builtin_module_names 可以使用sys里的builtin_module_names来查看内置模块
item系列
__getitem__\__setitem__\__delitem__
class Foo: def __int__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __getitem__(self,item): if hasattr(self,item): return self.__dict___[item] def __setitem__(self,key,value): self.__dict__[key] = value def __delitem__(self,key): self.__dict__[key] f = Foo('egon',38,'男') print(f['name']) f['hobby'] = '男' print(f.hobby,f['hobby']) del f.hobby # object类原生支持的 print(f.__dict__) # 证明已经删除 hobby属性 del f['hobby'] # 通过自己实现的 def __delattr__ print(f.__dict__) # 证明已经删除 hobby属性
__new__
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A, *args, **kwargs) a = A() print(a.x)
class Singleton: def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): cls._instance = object.__new__(cls, *args, **kw) return cls._instance one = Singleton() two = Singleton() two.a = 3 print(one.a) # 3 # one和two完全相同,可以用id(), ==, is检测 print(id(one)) # 29097904 print(id(two)) # 29097904 print(one == two) # True print(one is two)
当你之后再来实例化的时候,用之前创建的对象
问:去除对象中名字相同,年龄相同的对象 class A: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): if self.name == other.name and self.age == other.age: return True return False def __hash__(self): return hash(self.name+self.age) a = A('egg', 'male') b = A('egg', 'male') print(set((a, b))) # set 依赖对象的 hash eq 方法
__setattr__,__delattr__,__getattr__
class Foo: x=1 def __init__(self,y): self.y=y def __getattr__(self, item): print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value): print('----> from setattr') # self.key=value #这就无限递归了,你好好想想 # self.__dict__[key]=value #应该使用它 def __delattr__(self, item): print('----> from delattr') # del self.item #无限递归了 self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行 f1=Foo(10) print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值 f1.z=3 print(f1.__dict__) #__delattr__删除属性的时候会触发 f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作 del f1.a print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发 f1.xxxxxx 三者的用法演示