Python内建函数七
北京扁平疣好的医院 http://baijiahao.baidu.com/s?id=1688833387258790876&wfr=spider&for=pc 本篇文章将继续介绍Python的内建函数。 Pprint()最常用的打印函数,可以传入多个参数一并打印。print包含多个关键字参数:sep,end,file和flush。通过关键字参数sep可以设置间隔字符以及end设置结束字符,file用于指定打印到的目标位置,可以是文件,也可以是IO流对象,默认是sys.stdout,即标准输出。flush用于强制清空缓冲区。 a=1b="hello"classC:passc=C()print(a,b,c,sep=" ",end="END")#1 hello __main__.Cobjectat0x7fecb8f6cENDd={"key":"value","layer1":{"key":[1,2,3],"layer2":{"layer3":{"layer4":{"key":"value",}},},}}print(d){key:value,layer1:{key:[1,2,3],layer2:{layer3:{layer4:{key:value}}}}} 可以看到,嵌套很深、内容很多的字典项通过print后均被压缩到一行内进行打印,层级不明显。Python提供了一个pprint标准库,用以实现友好打印的功能: importpprintpprint.pprint(d){key:value,layer1:{key:[1,2,3],layer2:{layer3:{layer4:{key:value}}}}} pprint函数会将字典项进行自动分层次打印。 a=[1,2,3,4]a.insert(0,a)print(a)#[[...],1,2,3,4]pprint.pprint(a)#[Recursiononlistwithid=,1,2,3,4]Pproperty() 生成一个特性(property)对象。property对象是定义数据描述符(DataDescriptor)的一种简洁的方式(啥是描述符?参见这个系列)。普通的描述符需要单独定义一个类,并给出__get__,__set__和__delete__的定义,最后再在目标类中指定描述符所控制的属性: classOneOf:def__init__(self,*options):self.options=set(options)defvalidate(self,value):ifvaluenotinself.options:raiseValueError(f"Expected{value!r}tobeoneof{self.options!r}")def__set_name__(self,owner,name):self.name="_"+namedef__get__(self,obj,objtyp=None):returngetattr(obj,self.name)def__set__(self,obj,value):self.validate(value)setattr(obj,self.name,value) 上例定义了一个描述符,其中__set_name__特殊方法用于获取目标属性的名字,即name参数。该描述符的作用在于判断类属性是否是给定的options的其中之一,下面看一下其用法: classSchool:course=OneOf("math","Chinese","English")score=OneOf("A","B","C")def__init__(self):self.course="English"s1=School()print(s1.course)#Englishs1.score="D"#ValueError:ExpectedDtobeoneof{B,C,A} 如果采用property,那么可以不用额外定义类OneOf,直接在目标类School中实现: classSchool:def__init__(self):self.course_range={"math","Chinese","English"}defcourse_get(self):returnself._coursedefcourse_set(self,value):ifvaluenotinself.course_range:raiseValueError(f"Expected{value}tobeoneof{self.course_range}")self._course=valuecourse=property(fget=course_get,fset=course_set)s=School()s.course="English"print(s.course)#Englishs.course="Programming"#ValueError:ExpectedProgrammingtobeoneof{English,math,Chinese} 当然,可以采用最简洁的装饰器形式定义property: classSchool:def__init__(self):self.course_range={"math","Chinese","English"} propertydefcourse(self):returnself._coursecourse.setterdefcourse(self,value):ifvaluenotinself.course_range:raiseValueError(f"Expected{value}tobeoneof{self.course_range}")self._course=values=School()s.course="Programming"#ValueError:ExpectedProgrammingtobeoneof{Chinese,English,math}另一个例子如下: classCube:def__init__(self,length=0,width=0,height=0):self._length=lengthself._width=widthself._height=heightdefget_volume(self):"""Returnthevolumeofthecube"""returnself._length*self._width*self._heightvolume=property(fget=get_volume) propertydeflength(self):returnself._lengthlength.setterdeflength(self,value):assertvalue=0self._length=valuelength.deleterdeflength(self):self._length=0c=Cube(width=5,height=3)c.length=-2#AssertionErrorc.length=4print(c.volume)#60delc.lengthprint(c.volume)#0Rrange()在Python中,range实际上是一种不可变的序列类型: fromcollections.abcimportSequencea=range(10)print(isinstance(a,Sequence))#True 因为是序列类型,所以序列的基本操作,range都是支持的: a=range(0,10,1)#Start,Stop,Stepprint(a[1])#1print(a[:5])#range(0,5)print(len(a))#10print(3ina)#True 那么,为什么不直接用list呢?因为range是固定的模式,即,从start开始,以step为步长,直到stop的序列,所以range所占用的内存空间永远是固定的,它只需存储三个变量: importsysa=range(int(10e6))b=list(a)print(sys.getsizeof(a),sys.getsizeof(b))# 最后,range对象相等性在于range中元素是否完全相等,而不取决于start,step和stop是否相等: a=range(4,8,2)b=range(4,7,2)print(list(a),list(b))#[4,6][4,6]print(a==b)#TrueRrepr() 返回一个对象的可打印的表示字符串,即(printablerepresentation)。repr的目的在于生成的字符串尽可能能够通过eval得到原对象,即s=eval(repr(s)): a=range(10)print(repr(a))#range(0,10)print(eval(repr(a))==a)#True 需要同str区分开来。str通常返回对用户友好的字符串,str的结果不能用eval复原为原对象: a="python"print(repr(a),str(a))#pythonpythonprint(eval(repr(a))==a)#Trueprint(eval(str(a))==a)#NameError:namepythonisnotdefined 对于自定义类型,可以通过__repr__特殊方法控制repr得到的结果: classPoint:def__init__(self,x,y):self.x=xself.y=ydef__repr__(self):returnf"Point(x={self.x},y={self.y})"def__eq__(self,other):ifself.x==other.xandself.y==other.y:returnTrueelse:returnFalsep=Point(1,2)print(p)#Point(x=1,y=2)print(p==eval(repr(p))#TrueRreversed() 返回一个目标对象反序的迭代器: a=[1,2,3,4]print(list(reversed(a)))#[4,3,2,1] 对于自定义类型,可以通过特殊方法__reversed__来自定义反序操作: classSentence:def__init__(self,words):self.words=wordsself.s=.join(self.words)def__str__(self):returnself.sdef__reversed__(self):forwinself.words[::-1]:yieldws1=Sentence(["It","is","not","only","Python"])print(s1)#ItisnotonlyPythons2=Sentence(reversed(s1))print(s2)#PythononlynotisItRround() 取整函数: print(round(0.4),round(0.6))#01 需要特别注意的是,round使用的取整算法称作bankerrounding,而非四舍五入,区别在于bankerrounding将所有的半数(0.5,1.5,2.5...)向最靠近的偶数取整(可以称作四舍六入五留双): print(round(0.5),round(1.5),round(2.5))# 为什么有这样反直觉(实际反的是我们四舍五入的直觉)的规则呢?给出如下一系列数字,我们来看看不同的取整方法得到的平均数是多少: l=10a=[x+0.5forxinrange(l)]print(a,sum(a)/l)#[0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5]5.0#四舍五入fromdecimalimportDecimalb=[Decimal(x).quantize(Decimal(1),rounding=decimal.ROUND_HALF_UP)forxina]print(sum(b)/l)#5.5#roundprint(sum([round(x)forxina])/l)#5.0 可以看到,对平均数的计算,round要更准确。四舍五入的方法,对于大量的数字统计而言,会产生巨大的偏差。 往期文章: Python内建函数(六) Python内建函数(五) Python内建函数(四) Python内建函数(三) Python内建函数(二) Github看全文 |
转载请注明地址:http://www.tanhuaa.com/thzp/10923.html
- 上一篇文章: Kubernetes映射外部服务到集群
- 下一篇文章: tasksel安装工具