检测本文件中对象是否存在
# -*- coding: utf-8 -*- import sys x=10 obj1=sys.modules[__name__] print(hasattr(obj1,"x")) obj2=sys.modules[__name__] print(hasattr(obj2,"y"))
基于反射动态导入模块
isinstance检查对象是否是类产生的对象
# -*- coding: utf-8 -*- class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(class1,class2)检查class1是否是class2产生的派生类
# -*- coding: utf-8 -*- class Foo(object): pass class Bar(Foo): pass print(issubclass(Bar, Foo))
__getattribute__
当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError二者同时出现
# -*- coding: utf-8 -*- __author__ = 'Linhaifeng' class Foo: def __init__(self,x): self.x=x def __getattr__(self, item): print('执行的是我')
def __getattribute__(self, item): print('不管是否存在,我都会执行') raise AttributeError('哈哈') f1=Foo(10) f1.x
#有异常,但是程序没有立马崩溃 f1.xxxxxx
__getitem__,__setitem__,__delitem__
点的方式与attr写法(上面)相关,字典的方式与item(下面)写法相关。
# -*- coding: utf-8 -*- class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)
字符串相关内置函数改写
__str__,__repr__,__format__
# -*- coding: utf-8 -*- # 定义学校名,学校地址,学校类型的不同格式 format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 } class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type #找不到str就去找repr作为替代品 def __repr__(self): return 'School(%s,%s)' %(self.name,self.addr) def __str__(self): return '(%s,%s)' %(self.name,self.addr) def __format__(self, format_spec): # if format_spec if not format_spec or format_spec not in format_dict: format_spec='nat' fmt=format_dict[format_spec] return fmt.format(obj=self) s1=School('oldboy1','北京','私立') print('from repr: ',repr(s1)) print('from str: ',str(s1)) print(s1) ''' str函数或者print函数--->obj.__str__() repr或者交互式解释器--->obj.__repr__() 如果__str__没有被定义,那么就会使用__repr__来代替输出 注意:这俩方法的返回值必须是字符串,否则抛出异常 ''' print(format(s1,'nat')) print(format(s1,'tna')) print(format(s1,'tan')) print(format(s1,'asfdasdffd'))
__slots__
# -*- coding: utf-8 -*- ''' 1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性) 2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的) 3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__ 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给 实例添加新的属性了,只能使用在__slots__中定义的那些属性名。 4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该 只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。更多的是用来作为一个内存优化工具。 ''' class Foo: __slots__ = 'x' #key=x,value=none f1 = Foo() f1.x = 1 #f1.y = 2 # 报错 print(f1.__slots__) # print(f1.__dict__) f1不再有__dict__ class Bar: __slots__ = ['x', 'y'] #两个key属性的情况 n = Bar() n.x, n.y = 1, 2 #n.z = 3 # 报错,不再有__dict__
__doc__(描述信息属性,不定义默认指定)
# -*- coding: utf-8 -*- class Foo: '我是描述信息' pass class Bar(Foo): pass print(Foo.__doc__) print(Bar.__doc__) #该属性无法继承给子类
__module__ 从其他文件引入类时,查看使用的对象来自于哪一个文件
__class__ 从其他文件引入类时,查看使用的对象来自于哪一个文件的哪一个类
__del__析构方法(当对象在内存中被释放时,自动触发执行,python一般不用定义)__del__在实列被删除的情况下才会被触发
删除实列时触发
# -*- coding: utf-8 -*- class Foo: def __del__(self): print('执行我啦') f1=Foo() del f1 print('------->')
整个程序执行完毕释放内存
# -*- coding: utf-8 -*- class Foo: def __del__(self): print('执行我啦') f1=Foo() print('------->')
__call__ 对象加括号执行(前提是写有__call__)
# -*- coding: utf-8 -*- class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('执行__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
__next__,__iter__实现迭代器协议
例:实现斐波那契数列
# -*- coding: utf-8 -*- class Fib: def __init__(self): self._a=0 self._b=1 def __iter__(self): return self def __next__(self): self._a,self._b=self._b,self._a + self._b return self._a f1=Fib() print(f1.__next__()) print(next(f1)) print(next(f1)) for i in f1: if i > 100: break print('%s ' %i,end=' ')
描述符就是一个“绑定行为“的对象属性,在描述符协议中,它可以通过方法充写属性的访问。这些方法有get(),set(),delete().如果这些方法中任何一个被定义在一个对象中,这个对象就是一个描述符。(这几个方法是特殊方法,双下划线由于转换未显示)