__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation.
__init__()Called after the instance has been created (by __new__()), but before it is returned to the caller.
__new__() and __init__() work together in constructing objects (__new__() to create it, and __init__() to customize it)
1、定制化tuple类型
必须重新定义new与init
class IntTuple(tuple):
#覆盖tuple的内置静态方法,不需要加装饰器
def __new__(cls,iterable):
g = (x for x in iterable if isinstance(x,int) and x > 0)
return super(IntTuple,cls).__new__(cls,g)
#参数iterable必须要有,这是数据入口,随后该数据会被传递给__new__
def __init__(self,iterable):
print(self)
#可选
super(IntTuple,self).__init__()
a = IntTuple([1,44,'2',(3,5)])
1、 定义类属性slots对实例属性的影响
import sys
class A():
def __init__(self,id,name):
self.id = id
self.name = name
class B():
__slots__ = ['id','name']
def __init__(self,id,name):
self.id = id
self.name = name
print(dir(A(1,'lisi')))
print(dir(B(2,'lisi')))
print(set(dir(A(2,'lisi'))) - set(dir(B(2,'lisi'))))
print(sys.getsizeof(A(1,'lisi')))
print(sys.getsizeof(A(1,'lisi').__dict__))
属性差异为红色标记的两个属性,weakref对于内存的消耗可不计
with obj as obj1: pass
,实际执行过程为obj调用enter方法,返回的新对象赋值给obj1,之后执行块内代码,最后obj1执行exit方法!1、实例
mydict = {}
class A():
def __init__(self,a,b):
self.a = a
self.b = b
def __enter__(self):
mydict['a'] = self.a
mydict['b'] = self.b
#后三个参数是固定的,异常类型,异常实例、异常traceback对象
def __exit__(self,exc_type,exc_val,exc_tb):
mydict.clear()
print(mydict)
with A(3,5) as Q:
print(mydict)
print(mydict)
2、异常捕获与压制
mydict = {}
class A():
def __init__(self,a,b):
self.a = a
self.b = b
def __enter__(self):
mydict['a'] = self.a
mydict['b'] = self.b
#后三个参数是固定的,异常类型,异常实例、异常traceback对象
def __exit__(self,exc_type,exc_val,exc_tb):
#对于with代码块中出现的异常,__exit__能捕获
print(exc_type,exc_val,exc_tb)
mydict.clear()
#返回True能成功压制异常!!!
return True
print(mydict)
with A(3,5) as Q:
raise Exception('myerror')
print(mydict)
print(mydict)
with代码块产生异常,但任然会执行exit方法,清空字典;这是上下文管理器的默认行为方式,即先执行exit后再抛出代码块内的异常,确保exit方法始终要执行
通过return True成功压制异常,即有异常发生也不抛出!
使用setx/getx方法来访问属性,相当于中间抽象出一层,进行一些逻辑处理,比较灵活,但每次调用起来比较费劲
解决方法:内置装饰器property
class circle():
def __init__(self,radius):
self.radius = radius
#get方法(取值器)使用装饰器property
@property
#函数名即为新的属性名
def radius(self):
#设置器、取值器内部均使用self.__原属性名
return self.__radius
#set方法(设置器)使用: 新属性名.setter
@radius.setter
def radius(self,value):
if not isinstance(value,(int,float)):
raise ValueError('wrong type')
self.__radius = value
c = circle(100)
print(c.radius)
c.radius = '1'