版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Python进阶学习笔记第1章课程介绍Python入门中我们学习了:如何安装Python环境变量和数据类型:Python内置的基本类型List列表和Tuple元组:顺序的集合类型条件判断和循环:控制程序流程函数:定义和调用函数切片:如何对list进行切片迭代:如何用for循环迭代集合类型列表生成式:如何快速生成列表Python进阶课程我们讲要学习:函数式编程:不是函数编程哦,是函数式编程模块:如何使用模块面向对象编程:面向对象的概念、属性、方法定制类:利用Python的特殊方法定制类第2章函数式编程函数:function函数式:functional,一种编程范式函数式编程特点:把计算视为函数而非指令,贴近计算支持告诫函数,代码简洁Python不是纯函数式编程:允许有变量支持高阶函数:函数也可以作为变量传入支持闭包:有了闭包就能返回函数有限度的支持匿名函数高阶函数变量可以指向函数,函数名其实就是指向函数的变量,而高阶函数其实就是可以接收函数做参数的函数。Len([1,2,3])=3Demo:接收abs函数函数。defadd(x,y,f)returnf(x)+f(y)把函数作为参数传入另一个函数创建实例属性Personxiaoming、xiaohongxiaomingxiaohong要依靠他们各自的名字、性别、生日等属性。Pythonxiaomingnamegenderbirth属性:xiaoming=Person()='XiaoMing'xiaoming.gender='Male'xiaoming.birth='1990-1-1'给xiaohong加上的属性不一定要和xiaoming相同:xiaohong=Person()='XiaoHong'xiaohong.school='No.1HighSchool'xiaohong.grade=2实例的属性可以像普通变量一样进行操作:xiaohong.grade=xiaohong.grade+1任务请创建包含两个Person类的实例的list,并给两个实例的name赋值,然后按照name进行排序。sorted()是高阶函数,接受一个比较函数。参考代码:classPerson(object):passp1=Person()='Bart'p2=Person()='Adam'p3=Person()=L1=[p1,p2,p3]L2=sorted(L1,lambdap1,p2:cmp(,))printL2[0].nameprintL2[1].nameprintL2[2].name初始化实例属性son类ngenderbirthPersonPersoninit(),init()classPerson(object):definit(self,name,gender,birth):=nameself.gender=genderself.birth=birthinit()法,后续参数则可以自由指定,和定义函数没有任何区别。相应地,创建实例时,就必须要提供除self以外的参数:xiaoming=Person('XiaoMing','Male','1991-1-1')xiaohong=Person('XiaoHong','Female','1992-2-2')有了init()Personnamegenderbirth这3个属性,并且,被赋予不同的属性值,访问属性使用.操作符:print#输出'XiaoMing'printxiaohong.birth#输出'1992-2-2'要特别注意的是,初学者定义init()self参数:>>>classPerson(object):... definit(name,birth):... pass...>>>xiaoming=Person('XiaoMing','Male','1990-1-1')Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:init()takesexactly3arguments(4given)这会导致创建失败或运行不正常,因为第一个参数name被Python解释器传入了实例的引用,从而导致整个方法的调用参数位置全部没有对上。任务Person类的initnamegenderbirth要定义关键字参数,使用**kw;除了可以直接使用='xxx'设置一个属性外,还可以通过setattr(self,'name','xxx')设置属性。参考代码:classPerson(object):definit(self,name,gender,birth,**kw):=nameself.gender=genderself.birth=birthfork,vinkw.iteritems():setattr(self,k,v)xiaoming=Person('XiaoMing','Male','1990-1-1',job='Student')printprintxiaoming.job访问限制Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(),该属性就无法被外部访问。看例子:classPerson(object):definit(self,name):=nameself._title='Mr'job='Student'p=Person('Bob')print#=>Bobprintp._title#=>Mrprintp.job#=>Error(mostrecentcalllast):File"<stdin>",line1,in<module>AttributeError:'Person'objecthasnoattribute'job'可见,只有以双下划线开头的"job"不能直接被外部访问。但是,如果一个属性以"xxx"的形式定义,那它又可以被外部访问了,以"xxx"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"xxx"定义。以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。任务Person类的initnamescorescore绑定到score属性上,看看外部是否能访问到。以双下划线开头的属性无法被外部访问,"xxx"除外。参考代码:classPerson(object):definit(self,name,score):=namescore=scorep=Person('Bob',59)printprintp.score输出结果:BobTraceback(mostrecentcalllast):File"./6172/58Wr/index.py",line9,inprintp.scoreAttributeError:'Person'objecthasnoattribute'score'创建类属性类是模板,而实例则是根据类创建的对象。绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果性有且只有一份。定义类属性可以直接在class中定义:classPerson(object):address='Earth'definit(self,name):=name接访问:printPerson.address#=>Earth属性:p1=Person('Bob')p2=Person('Alice')printp1.address#=>Earthprintp2.address#=>Earth由于Python是动态语言,类属性也是可以动态添加和修改的:Person.address='China'printp1.address#=>'China'print#=>'China'Personaddress类属性都改变了。任务PersonPerson?不会了怎么办由于创建实例必定会调用init()方法,所以在这里修改类属性count很合适。参考代码:classPerson(object):count=0definitname):Person.count=Person.count+1=namep1=Person('Bob')printPerson.count#=>1p2=Person('Alice')printPerson.count#=>2p3=Person('Tim')printPerson.count#=>3#输出结果:123类属性和实例属性名字冲突怎么办量上修改类属性会发生什么问题呢?classPerson(object):address='Earth'definit(self,name):=namep1=Person('Bob')p2=Person('Alice')print'Person.address='+Person.addressp1.address='China'print'p1.address='+p1.addressprint'Person.address='+Person.addressprint'p2.address='+p2.address结果如下:Person.address=Earthp1.address=ChinaPerson.address=Earthp2.address=Earthp1.address'China'address'China',但是,Person.addressp2.address仍然是'Earch',怎么回事?原因是p1.address='China'并没有改变Person的address,而是给p1这个实例绑定了实例属性ds1而它所属的类Person也有一个类属性address,所以:访问p1.address时,优先查找实例属性,返回'China'。
'hina'访问p2.address时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。访问。当我们把p1的address实例属性删除后,访问p1.address就又返回类属性的值'Earth'了:delp1.addressprintp1.address#=>Earth绑定了一个实例属性。任务Personcount改为count改为私有countcount参考代码:classPerson(object):count=0definit(self,name):Person.count=Person.count+1=nameprintPerson.countp1=Person('Bob')p2=Person('Alice')printPerson.count#输出结果:不可以定义实例方法一个实例的私有属性就是以什么用?实例的属性外,还可以定义实例的方法。实例的方法就是在类中定义的函数,它的第一个参数永远是self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:classPerson(object):definitname):name=defget_name(self):returnnameget_name(self)self。init,name)其实也可看做是一个特殊的实例方法。调用实例方法必须在实例上调用:p1=Person('Bob')printp1.get_name() self不需要显式传入#=>Bob任务Person类增加一个私有属性score,表示分数,再增加一个实例方get_grade(),能根据scoreA-优秀B-及格C-不及格三档。?不会了怎么办get_grade()self参考代码:classPerson(object):definitname,score):name=nameself.score=scoredefget_grade(self):ifscore>=80:return'A'ifscore>=60:return'B'return'C'p1=Person('Bob',90)p2=Person('Alice',65)p3=Person('Tim',48)printp1.get_grade()printp2.get_grade()printp3.get_grade()#输出结果:ABC方法也是属性我们在class中定义的实例方法其实也是属性,它实际上是一个函数对象:classPerson(object):definit(self,name,score):=nameself.score=scoredefget_grade(self):return'A'p1=Person('Bob',90)printp1.get_grade#=><boundmethodPerson.get_gradeof<main.Personobjectat0x109e58510>>printp1.get_grade()#=>A也就是说,p1.get_grade返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.get_grade()才是方法调用。因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用types.MethodType把一个函数变为一个方法:importtypesdeffn_get_grade(self):ifself.score>=80:return'A'if>=60:return'B'return'C'classPerson(object):definit(self,name,score):=nameself.score=scorep1=Person('Bob',90)p1.get_grade=types.MethodType(fn_get_grade,p1,Person)printp1.get_grade()#=>Ap2=Person('Alice',65)printp2.get_grade()#ERROR:AttributeError:'Person'objecthasnoattribute'get_grade'#因为p2实例并没有绑定get_grade给一个实例动态添加方法并不常见,直接在class中定义要更直观。任务由于属性可以是普通的值对象,如str,int等,也可以是方法,还可以是函数,p1.get_gradeclassPerson(object):definit(self,name,score):=nameself.score=scoreself.get_grade=lambda:'A'p1=Person('Bob',90)printp1.get_gradeprintp1.get_grade()lambdaself.get_gradeselfself。#输出结果:at0x12f7e7d0>A定义类方法和属性类似,方法也分实例方法和类方法。classselfclass中定义类方法,需要这么写:classPerson(object):count=0@classmethoddefhow_many(cls):returncls.countdefinit(self,name):=namePerson.count=Person.count+1printPerson.how_many()p1=Person('Bob')printPerson.how_many()通过标记一个@classmethodPerson类上,而非类的实例。类clscls.count实Person.count。获得类的引用。任务count改为私有属性count,则外部无法读取score,但可以通过一个类方法获取,请编写类方法获得count值。?不会了怎么办注意类方法需要添加@classmethod参考代码:classPerson(object):count=0@classmethoddefhow_many(cls):returncls.countdefinit(self,name):=namePerson.count=Person.count+1printPerson.how_many()p1=Person('Bob')printPerson.how_many()#输出结果:01第3章类的继承什么是类的继承:genderschoolscore,是否需要重新编写呢?但是我们知道已有的Person类:classPerson(object):definit(self,name,gender):=nameself.gender=gender里面存在已有属性:name,gender我们可以这样:classStudent(Person):definit(self,name,gender,school,score):super(Student,self).init(name,gender)self.school=school=score缺少的功能只需要编写即可继承的好处:复用已有代码,自动拥有现有类的所有功能,只需要编写缺少的功能父类与子类派生类,继承类继承的特点:(1).子类和父类是is关系:classStudent(Person):passp=Person()s=Student()“p”是一个Person类,而不是一个Student类;s是一个Student类,也是一个Person类(2).错误的继承:Student类和Book类是has关系classStudent(Person):definit(self,bookName):=Book(bookName)(3).Python的继承特点:总是从某个类继承,如果没有合适的类,就从object类继承:classMyClass(object):passsuper().init(self,args):super(SubClass,self).init(args)pass如果没有使用,那么父类的属性很有可能就没有初始化。继承一个类如果已经定义了Person类,需要定义新的Student和Teacher类时,可以直接从Person类继承:classPerson(object):definit(self,name,gender):=nameself.gender=genderStudentscore:classStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=score一定要用super(Student,self).init(name,gender)去初始化父类,否则,继承自Person的Student将没有name和gender。super(Student,self)Personinit()selfsuper()init()(也不能写任务请参考Student类,编写一个Teacher类,也继承自Person。super()的init参考代码:classPerson(object):definitname,gender):=nameself.gender=genderclassTeacher(Person):definit(self,name,gender,course):super(Teacher,self).init(name,gender)self.course=courset=Teacher('Alice','Female','English')printprintt.course#输出结果:AliceEnglish判断类型函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。假设有如下的Person、Student和Teacher的定义及继承关系如下:classPerson(object):definit(self,name,gender):=nameself.gender=genderclassStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=scoreclassTeacher(Person):definit(self,name,gender,course):super(Teacher,self).init(name,gender)self.course=coursep=Person('Tim','Male')s=Student('Bob','Male',88)t=Teacher('Alice','Female','English')当我们拿到变量p、s、t时,可以使用isinstance判断类型:>>>isinstance(p,Person)p是Person类型>>>isinstance(p,Student)False pStudent>>>isinstance(p,Teacher)False #p类型属性和方法。我们再考察s:>>>isinstance(s,Person)sPerson类型>>>isinstance(s,Student)sStudent>>>isinstance(s,Teacher)False #s类型sStudentPerson类型,tuetnens看成Person的实例也是可以的。类型。任务t类isinstance()判断来验证您的答案。注意t是Teacher的实例,继承链是:object<-Person<-Teacher参考代码:classPerson(object):definit(self,name,gender):=nameself.gender=genderclassStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=scoreclassTeacher(Person):definit(self,name,gender,course):super(Teacher,self).init(name,gender)self.course=courset=Teacher('Alice','Female','English')printisinstance(t,Person)printisinstance(t,Student)printisinstance(t,printisinstance(t,object)#输出结果:TrueTrueFalseTrue多态类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们PersonStudentwhoAmI()classPerson(object):definit(self,name,gender):=nameself.gender=genderdefwhoAmI(self):return'IamaPerson,mynameis%s'%classStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=scoredefwhoAmI(self):return'IamaStudent,mynameis%s'%classTeacher(Person):definit(self,name,gender,course):super(Teacher,self).init(name,gender)self.course=coursedefwhoAmI(self):return'IamaTeacher,mynameis%s'%在一个函数中,如果我们接收一个变量x,则无论该x是Person、Student还是Teacher,都可以正确打印出结果:defwho_am_i(x):printx.whoAmI()p=Person('Tim','Male')s=Student('Bob','Male',88)t=Teacher('Alice','Female','English')who_am_i(p)who_am_i(s)who_am_i(t)运行结果:IamaPerson,mynameisTimIamaStudent,nameisBobIamanameisAlicexsStudentwhoAmI()PersonwhoAmI方法,s.whoAmI()由于Python是动态语言,所以,传递给函数who_am_i(x)的参数x不一定是Person或Person的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可:classBook(object):defwhoAmI(self):return'Iamabook'(Ja不检查类型,只要方法存在,参数正确,就可以调用。任务Pythonopen()FileFile对象有一read()方法可以读取文件内容:例如,从文件读取内容并解析为JSON结果:importjsonf=open('/path/to/file.json','r')printjson.load(f)Pythonjson.load()Fileread()File-likeObjectjson.load()。请尝试编写一个File-likeObject,把一个字符串r'["Tim","Bob","Alice"]'包装成File-likeObject并由json.load()解析。?不会了怎么办Studentsread()File-likeObject。参考代码:importjsonclassStudents(object):defread(self):returnr'["Tim","Bob","Alice"]'s=Students()printjson.load(s)#输出结果:[u'Tim',u'Bob',u'Alice']多重继承除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。多重继承的继承链就不是一棵树了,它像这样:classA(object):definit(self,a):print'initA...'self.a=aclassB(A):definit(self,a):super(B,self).init(a)print'initB...'classC(A):definit(self,a):super(C,self).init(a)print'initC...'classD(B,C):definit(self,a):super(D,self).init(a)print'initD...'看下图:BDABCsupr(调用iitAnit()只调用一次:>>>d=D('d')initA...initC...initB...initD...多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。举个例子,Python的网络服务器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服务器运行模式有多进程ForkingMixin和多线程ThreadingMixin两种。要创建多进程模式的TCPServer:classMyTCPServer(TCPServer,ForkingMixin)pass要创建多线程模式的UDPServer:classMyUDPServer(UDPServer,ThreadingMixin):pass如果没有多重继承,要实现上述所有可能的组合需要4x2=8个子类。任务+-Person+-Student+-是一类继承树;+-SkillMixin+-BasketballMixin+-FootballMixin是一类继承树。通过多重继承,请定义“会打篮球的学生”和“会踢足球的老师”。多重继承需要从两个或更多的类派生。参考代码:classPerson(object):passclassStudent(Person):passclasspassclassSkillMixin(object):passclassBasketballMixin(SkillMixin):defskill(self):return'basketball'classFootballMixin(SkillMixin):defskill(self):return'football'classBStudent(Student,BasketballMixin):passclassFootballMixin):passs=prints.skill()t=printt.skill()#输出结果:basketballfootball获取对象信息isinstance(例如,已有定义:classPerson(object):definit(self,name,gender):=nameself.gender=genderclassStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=scoredefwhoAmI(self):return'IamaStudent,mynameis%s'%首先可以用type()函数获取变量的类型,它返回一个Type对象:>>>type(123)<type'int'>>>>s=Student('Bob','Male',88)>>>type(s)<class'main.Student'>其次,可以用dir()函数获取变量的所有属性:>>>dir(123) #...['abs','add','and','class','cmp',...]>>>dir(s)['class',delattr','dict','doc','format','getattribute','hash','init',module','new','reduce','reduce_ex','repr','setattr','sizeof','str',subclasshook','weakref','gender','name','score','whoAmI']`class`s的一个属性。如何去掉`xxx`这类的特殊属性,只保留我们自己定义的属性?回顾一下filter()函数的用法。dir()返回的属性是字符串列表,如果已知一个属性名称,要获取或者设置对象的属性,就需要用getattr()和setattr()函数了:getattr(s'name') #name属性'Bob'>>>setattr(s,'name','Adam')#设置新的name属性>>>'Adam'getattr(s'age') #age属性,但是属性不存在,报错:(mostrecentcalllast):File"<stdin>",line1,in<module>AttributeError:'Student'objecthasnoattribute'age'>>>getattr(s'age',20) #age20任务对于Person类的定义:classPerson(object):definit(self,name,gender):=nameself.gender=gendername和genderPerson的init()定义,完成该功能。?不会了怎么办传入**kw即可传入任意数量的参数,并通过setattr()绑定属性。参考代码:classPerson(object):definit(self,name,gender,**kw):=nameself.gender=genderfork,vinkw.iteritems():setattr(self,k,v)p=Person('Bob','Male',age=18,course='Python')printprintp.genderprintp.ageprintp.course#输出结果:BobMale18Python第6章定制类什么是特殊方法1.例子:比较print的结果:>>>printlst[1,2,3]>>>printp<main.Personobjectat0x10da9e850>问题:Python是如何把任意变量变成str?因为任何数据类型的实例都有一个特殊方法,即:str()>>>printlst.str()[1,2,3]>>>printp.str()<main.Personobjectat0x10da9e850>2.Python的特殊方法:(1).print的str方法(2).len的len方法(3).cmp的cmp方法……特点:(1).特殊方法定义在class中(2).不需要直接调用(3).Python的某些函数或操作符调用对应的特殊方法3.正确的视线特殊方法(1).只需要编写用到的特殊方法(2).有关联性的特殊方法都必须实现getattr;; delattr 和 strstr():classPerson(object):definit(self,name,gender):=nameself.gender=genderdefstr(self):return'(Person:%s,%s)'%(,self.gender)现在,在交互式命令行下用print试试:>>>p=Person('Bob','male')>>>printp(Person:Bob,但是,如果直接敲变量p:>>>p<main.Personobjectat0x10c941890>似乎str()因为Python定义了str()和repr()两种方法,str()用于显示给用户,而repr()用于显示给开发人员。有一个偷懒的定义repr的方法:classPerson(object):definit(self,name,gender):=nameself.gender=genderdefstr(self):return'(Person:%s,%s)'%(,self.gender)repr =str 任务Student类定义str和repr<Student:name,score>:classStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=scoreStudents类加上str()和repr()classPerson(object):definit(self,name,gender):=nameself.gender=genderclassStudent(Person):definit(self,name,gender,score):super(Student,self).init(name,gender)self.score=scoredefstr(self):return'(Student:%s,%s,%s)'%(,self.gender,self.score)repr =str s=Student('Bob','male',88)prints#输出结果:(Student:Bob,male,88) int、str等内置数据类型排序时,Pythonsorted()按照默认的比较函cmpStudentcmp():classStudent(object):definit(self,name,score):=nameself.score=scoredefstr(self):return'(%s:%s)'%(,self.score)repr =str defcmp(self,s):if<:return-1elif>:return1else:return0上述Student类实现了cmp()方法,cmp用实例自身self和传入的实sselfs1,如果两者相当,返回0。Student类实现了按name进行排序:>>>L=[Student('Tim',99),Student('Bob',88),Student('Alice',77)]>>>printsorted(L)[(Alice:77),(Bob:88),(Tim:99)]注意:如果list不仅包含Student类,则cmp 可能会报错:L=[Student('Tim',99),Student('Bob',88),100,'Hello']printsorted(L)请思考如何解决。任务请修改Student的cmp 方法让它按照数从高到底排序分数相同的按名字排序。scorescorename。参考代码:classStudent(object):definit(self,name,score):=nameself.score=scoredefstr(self):return'(%s:%s)'%(,self.score)repr =str defcmp(self,s):ifself.score==s.score:returncmp(,)return-cmp(self.score,s.score)L=[Student('Tim',99),Student('Bob',88),Student('Alice',99)]printsorted(L)#输出结果:[(Alice:99),(Tim:99),(Bob:88)] len 如果一个类表现得像一个list,要获取有多少个元素,就得用len()函数。len()lenStudents类,把名字传进去:classStudents(object):definit(self,*args):s=argsdeflen(self):returnlen(s)只要正确实现了len()len()Students“长度”:>>>ss=Students('Bob','Alice','Tim')>>>printlen(ss)3任务斐波那契数列是由0,1,1,2,3,5,8...构成。请编写一个Fib类,Fib(10)表示数列的前10个元素,printFib(10)可以打印出数列的前10个元素,len(Fib(10))可以正确返回数列的个数10。numN参考代码:classFib(object):definitnum):a,b,L=0,1,[]forninrange(num):L.append(a)a,b=b,a+bself.numbers=Ldefstr(self):returnstr(self.numbers)repr =str deflen(self):returnlen(self.numbers)f=Fib(10)printfprintlen(f)#输出结果:[0,1,1,2,3,5,8,13,21,34]10数学运算PythonintfloatintfloatRational类classRational(object):definitp,q):=p=qp、q都是整数,表示有理数p/q。Rational进行+运算,需要正确实现add:classRational(object):definitp,q):=p=qdefadd(self,r):returnRational(self.p*+**defstr(self):return'%s/%s'%(self.p,self.q)repr =str 现在可以试试有理数加法:>>>r1=Rational(1,3)>>>r2=Rational(1,2)>>>printr1+r25/6任务Rational类虽然可以做加法,但无法做减法、乘方和除法,请继续完善Rational类,实现四则运算。提示:减法运算:sub 乘法运算:mul 除法运算:div 如果运算结果是6/8,在显示的时候需要归约到最简形式3/4。参考代码:defgcd(a,b):ifb==0:returnareturngcd(b,a%b)classRational(object):definitp,q):=p=qdefaddr):returnRational(self.p*+**defsubr):returnRational(self.p*-**defmulr):returnRational(self.p**defdivr):returnRational(self.p**defstr(self):g=gcd(self.p,self.q)return'%s/%s'%(self.p/g,self.q/g)repr =str r1=Rational(1,r2=Rational(1,printr1+r2printr1-r2printr1*printr1/r2#输出结果:3/41/41/82/1类型转换Rationalintfloat怎么办?考察整数和浮点数的转换:>>>int(12.34)12>>>float(12)12.0如果要把Rational转为int,应该使用:r=Rational(12,5)n=int(r)int()int():classRational(object):definit(self,p,q):self.p=p=qdefint(self):returnself.p//self.q结果如下:>>>printint(Rational(7,2))3>>>printint(Rational(1,3))0float()float()。任务请继续完善Rational,使之可以转型为float。将self.p转型为float类型,再作除法就可以得到float:float(self.p)/self.q参考代码:classRational(object):definitp,q):=p=qdefint(self):returnint(self.p)//self.qdeffloat(self):returnfloat(self.p)/self.qprintfloat(Rational(7,2))printfloat(Rational(1,3))#输出结果:3.50.333333333333@property考察Student类:classStudent(object):definit(self,name,score):=nameself.score=score当我们想要修改一个Student的scroe属性时,可以这么写:s=Student('Bob',59)s.score=60但是也可以这么写:s.score=1000如果利用两个方法:classStudent(object):definit(self,name,score):=nameself.score=scoredefget_score(self):returnscoredefset_score(self,score):ifscore<0orscore>100:raiseValueError('invalidscore')self.score=score这样一来,s.set_score(1000)就会报错。这种使用get/set方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。但是写s.get_score()和s.set_score()没有直写s.score来得直接。有没有两全其美的方法? 有。因为Python支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把get/set方法“装饰”成属性调用:classStudent(object):definit(self,name,score):=nameself.score=score@propertydefscore(self):returnself.score@score.setterdefscore(self,score):ifscore<0orscore>100:raiseValueError('invalidscore')self.score=score注意score(self)get方法,用@propertyscore(self,score)set\h方法,用@sc\hore.setter装饰,@score.setter是前一个@property装饰后的副产品。现在,就可以像使用属性一样设置score了:>>>s=Student('Bob',59)>>>s.score=60>>>prints.score60>>>s.score=1000Traceback(mostrecentcalllast):...ValueError:invalidscorescoreset方法任务如果没有定义set方法,就不能对“属性”赋值,这时,就可以创建一个只读“属性”。Studtdesce计算A(0、、(60用@property修饰grade的get方法即可实现只读属性。参考代码:classStudent(object):definit(self,name,score):=nameself.sco
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五版法律服务企业法务专员职位劳动合同3篇
- 二零二五版房屋买卖合同范本下载涉及装修及家具家电条款3篇
- 二零二五年时尚服饰品牌区域独家代理销售合同2篇
- 二零二五年度航空货运大客户承运合同范本3篇
- 二零二五年建筑材料出口销售与绿色认证合同3篇
- 二零二五版grc构件生产、安装与装配式建筑推广实施合同3篇
- 二零二五版技术开发与成果转化合同3篇
- 二零二五年建筑材料运输及安装服务合同6篇
- 二零二五年度家具安装与室内空气净化合同2篇
- 二零二五版展览馆场地租赁合同范本(含展览策划服务)3篇
- 公路工程施工现场安全检查手册
- 公司组织架构图(可编辑模版)
- 1汽轮机跳闸事故演练
- 陕西省铜川市各县区乡镇行政村村庄村名居民村民委员会明细
- 礼品(礼金)上交登记台账
- 北师大版七年级数学上册教案(全册完整版)教学设计含教学反思
- 2023高中物理步步高大一轮 第五章 第1讲 万有引力定律及应用
- 青少年软件编程(Scratch)练习题及答案
- 浙江省公务员考试面试真题答案及解析精选
- 系统性红斑狼疮-第九版内科学
- 全统定额工程量计算规则1994
评论
0/150
提交评论