对象的另一面
Posted 我的人生只需要一次成功
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象的另一面相关的知识,希望对你有一定的参考价值。
当getattr与__getattribute__同时出现时:先找__getattribute__,如果抛出异常则执行getattribute
1 class Foo: 2 def __init__(self,x): 3 self.x=x 4 def __getattr__(self, item): 5 print("执行的是我") 6 def __getattribute__(self, item): 7 print("我是ibute") 8 raise AttributeError("哈哈") 9 10 f1=Foo(10) 11 f1.x
__str__,__repr__,__format__
class Foo: def __init__(self,name,age): self.name=name self.age=age def __repr__(self): return "这个是repr" def __str__(self): return "这个是str" f1=Foo("szw",18) print(f1) # str函数或者print函数--->obj.__str__() # repr或者交互式解释器--->obj.__repr__() # 如果__str__没有被定义,那么就会使用__repr__来代替输出 # 注意:这俩方法的返回值必须是字符串,否则抛出异常
format_dic={"ymd":"{0.year}{0.mon}{0.day}", "m-d-y":"{0.year}-{0.mon}-{0.day}", "y:m:d":"{0.year}:{0.mon}:{0.day}",} class Data: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day def __format__(self, format_spec): print("我执行了") print("---------->,format_spec") if not format_spec or format_spec not in format_dic: #如果没传格 式 或传进来的格式找不到 则默认使用“ymd”作为格式 format_spec="ymd" fm=format_dic[format_spec] return fm.format(self) d1=Data(2016,12,26) # print(format(d1)) # print(format(d1,"ymd")) print(format(d1,"m-d-y")) # print(format(d1,"y:m:d")) # print(format(d1,"lshgia"))
__slots__
\'\'\' 1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性) 2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的) 3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__ 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个 字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给 实例添加新的属性了,只能使用在__slots__中定义的那些属性名。 4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该 只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。 更多的是用来作为一个内存优化工具。 \'\'\' class Foo: __slots__="x" f1=Foo() f1.x=1 # f1.y=2#报错 print(f1.x) class Bar: __slots__=["x","y"] n=Bar() n.x,n.y=1,2 print(n.x,n.y)
__doc__
#该属性无法被继承 class Foo: "654131651" pass print(Foo.__doc__) class Bar(Foo): pass print(Bar.__doc__)#该属性无法继承给子类
__module__和__class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
from obj.s import Foo f1=Foo("szw") print(f1.name) print(f1.__module__)#查看在那个模块 print(f1.__class__)#查看在那个类
__del__
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
__del__:析构方法
垃圾回收时触发
class Foo: def __del__(self): print(\'执行我啦\') f1=Foo() del f1 print(\'------->\') #输出结果 执行我啦 -------> 简单示范
class Foo: def __del__(self): print(\'执行我啦\') f1=Foo() # del f1 print(\'------->\') #输出结果 -------> 执行我啦 #为何啊??? 挖坑埋了你
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print(\'__call__\') obj = Foo() # 执行 __init__ obj() # 执行 __call__
__next__和__iter__实现迭代器协议
class Foo: def __init__(self,n): self.n=n def __iter__(self): return self def __next__(self): if self.n==100: raise StopIteration("终止了") self.n+=1 return self.n f1=Foo(10) print(f1.__next__()) print(f1.__next__()) print(f1.__next__()) # for i in f1: # print(i)
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=\'\')
__enter__和__exit__
1 with open(\'a.txt\') as f: 2 \'代码块\'
\'\'\' with触发__enter__ with代码块结束后执行__exit__ \'\'\' class Open: def __init__(self,name): self.name=name def __enter__(self): print("with触发enter") return self def __exit__(self, exc_type, exc_val, exc_tb): print("exit") # return self with Open("a.txt")as f: print("--------------") print(f.name) print("000000000000")
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
class Open: def __init__(self,name): self.name=name def __enter__(self): print("with触发enter") return self def __exit__(self, exc_type, exc_val, exc_tb): #如果return返回的是True这异常被吞掉 print("exit") print(exc_type) print(exc_val) print(exc_tb) return True with Open("a.txt.txt")as f: print("--------------") print(lsfhoisgsofsaipghsoigh) print(f.name) print("000000000000")
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
单例模式:
class LoggerHelper(object): _i=None @classmethod def instance(cls): if cls._i: return cls._i else: cls._i=LoggerHelper() return cls._i obj1=LoggweHelper.instance() print(obj1) obj2=LoggweHelper.instance() print(obj2) obj3=LoggweHelper.instance() print(obj3)
以上是关于对象的另一面的主要内容,如果未能解决你的问题,请参考以下文章