当前位置: 首页 > Linux

[Python]-8-对象与类(中)

时间:2023-04-07 01:42:16 Linux

简介本文介绍了Python如何将函数和数据集成到类中,并通过对象名来访问它们。文章目录0×5。获取对象信息0×6。实例属性和类属性0×7。属性和方法的动态绑定0×8。如何将类方法封装成属性0×5。使用isinstance以外的方式获取对象信息除了匹配对象类型外,还可以使用type来获取这些对象的类型,看下面的例子:#!/usr/bin/envpython#coding=utf-8#types的模块中定义的常量可以用来判断函数类型importtypes#输出对象的类型print(type("www.qingsword.com"))#判断对象是否为字符串typeprint(type("qingsword.com")==str)#程序输出TRUE#如果对象是函数,需要使用types模块中定义的常量来判断#------deffx():return0#判断fx是否为函数类型print(type(fx)==types.FunctionType)#判断是否为lambda类型print(type(lambda:0)==types.LambdaType)#判断len是否为内置函数typeprint(type(len)==types.BuiltinFunctionType)#判断表达式公式是否为列表生成器typeprint(type((xforxinrange(10)))==types.GeneratorType)#程序的输出为True#isinstance也可以完成这些操作,比如把判断fx函数的语句改成如下,返回值也是Trueprint(isinstance(fx,types.FunctionType))除了以上两种对象类型判断,通过getattr()、setattr()和hasattr(),我们可以直接操作一个对象的状态,看下面的例子:#!/usr/bin/envpython#coding=utf-8classOb_A(object):#--------def__init__(self,x=0):iftype(x)==int:self.a=xelse:raiseTypeError("不正确的参数类型(%s),正确的参数类型int"%type(x))#--------defsq(self):returnself.a*self.aoba=Ob_A(12)#判断oba中是否有属性object(ormethod)a,returnTrueprint(hasattr(oba,"a"))#获取属性(或方法)a,本例中a为属性值12,所以直接printprint(getattr(oba,"a"))#是否有属性(或方法)b,返回Falseprint(hasattr(oba,"b"))#给对象设置一个属性b,值为13setattr(oba,"b",13)#因为已经给对象添加了属性b,再次判断,返回True,打印出b的值13print(hasattr(oba,"b"))print(getattr(oba,"b"))#判断oba对象中是否存在sq属性(或方法)print(hasattr(oba,"sq"))#使用sq对象指向oba对象的sq方法sq=getattr(oba,"sq"))#从type可以看出sq是一个方法typeprint(type(sq))#执行sq方法,返回144print(sq())#程序输出TRUE12FALSETRUE13TRUE144这三个函数可以用来检测对象中的信息,只有在不知道对象信息的情况下,才会用到这三个函数,如果你已经知道一个对象中包含了哪些属性和方法,请直接调用0×6。实例属性和类属性Python是一种动态语言。实例化后,可以在实例中加入新的属性,但最好不要和类中的属性重名。请看下面的例子:#!/usr/bin/envpython#coding=utf-8#Ob_A类中定义了一个类属性x,其值配置为2classOb_A(object):x=2#InstantiatetheOb_Aclassoba=Ob_A()#给oba的一个实例创建一个新的属性x,因为它和Ob_A类中的属性同名,所以会覆盖原来的属性值oba.x=1#打印出来1print(oba.x)#类中的属性不变,打印出来2print(Ob_A.x)#此时如果手动删除oba实例的x对象,重新打印oba实例的x对象,会打印出原类中绑定的属性x的值,打印出2deloba.xprint(oba.x)#Procedure输出122类实例化后,如果需要给实例增加一个属性,它建议不要使用与原类中已有属性同名的属性名,因为同名的实例属性会屏蔽类属性。0×7。属性和方法的动态绑定Python是一种高级动态语言,不同于静态语言。当我们实例化一个类对象时,我们可以动态地将属性或方法绑定到这个类实例上。请看下面的例子:#!/usr/bin/envpython#coding=utf-8fromtypesimportMethodType#DefineaclassthatcontainsonlyoneageattributeclassOb_A(object):def__init__(self,age=0):self.age=age#实例化Ob_A类a=Ob_A(23)#给Ob_A类的实例a添加name属性a.name="qingsword"#定义一个外部方法,后面绑定到a实例上defget_sex(self):return"male"#使用types模块中的MethodType方法将外部方法get_sex绑定到a实例的getsex变量a.getsex=MethodType(get_sex,a)#执行getsex()的a实例相当于执行get_sex()print(a.getsex())#Programoutputmale#getsexname仅限于一个实例调用,如果此时再实例化一个Ob_A类,除非你使用MethodType绑定一个新的get_sex方法,否则新的Class实例不能使用外部方法get_sex。从上面的例子我们可以看出Python并没有限制一个对象实例绑定多少个外部属性和方法,但是如果你想限制它们,你可以在类中使用__slots__属性,请看下面的例子:#!/usr/bin/envpython#coding=utf-8fromtypesimportMethodType########classOb_A(object):def__init__(self,age=0):self.age=age#定义后__slots__属性,Ob_A本身和所有实例只能使用这个元组包含的元素作为属性或方法名__slots__=("name","age","get_sex")#########但是__slots__属性对于继承它的子类是无效的,除非子类也包含__slots__属性,那么这个子类可以定义的属性或方法名就是它自己__slots__元组包含的元素集合加上父类__slots__元组包含的元素classOb_B(Ob_A):x=0#######defget_sex(self):return"male"a=Ob_A(23)a.name="qingsword"a.get_sex=MethodType(get_sex,a)print(a.get_sex())#Ob_B类虽然继承了Ob_A,但是不包含__slots__属性,所以实例b可以添加任意属性或者方法名称。本例中增加了一个web属性,指向网站URL的字符串地址b=Ob_B()b.web="www.qingsword.com"print(b.web)0×8。如何将类方法封装成属性这部分将使用python内置的@property装饰器将类中的方法封装成属性。从外面看,这个方法就像一个普通的属性一样使用,请看下面的示例:#!/usr/bin/envpython#coding=utf-8fromdatetimeimportdatetime########classOb_A(object):def__init__(self,birth=2016):"""初始化配置出生年份"""self.__birth=birth#使用@property装饰器将birth方法转化为属性@propertydefbirth(self):"""获取出生年份"""returnself.__birth#使用@方法名.setter将该方法设置为可写属性(方法名必须先使用属性装饰器才能使用setter)@birth.setterdefbirth(self,birth):"""设置出生年份"""self.__birth=birth#只有一个@property方法没有setter,相当于只读属性@propertydefage(self):"""返回年龄"""y=datetime.now()返回rny.year-self.__birthx=Ob_A(2008)print(x.birth)#可以像设置属性值一样复制(如果是方法语法应该是x.birth(2000))x.birth=2000print(x.birth)print(x.age)#Programoutput2008200016虽然在上面的例子中,没有进一步检测年龄(比如年龄范围,输入类型等),但是不难看出封装函数intoattributes可以让调用者写出更直观的代码(比如x.birth=2000而不是x.birth(2000)),对于wrapper,可以在函数中进行各种条件判断,保证逻辑合理