引言
这篇文章介绍Python如何将函数与数据整合成类,并通过一个对象名称来拜访它们。
文章目录
0×5.获取对象信息
0×6.实例属性与类属性
0×7.属性和办法的动静绑定
0×8.如何将类办法封装成属性
0×5.获取对象信息
除了应用isinstance来匹配对象类型外,还能应用type来获取这些对象的类型,请看上面的实例:
#!/usr/bin/env python#coding=utf-8#types模块中定义的常量可用于判断函数类型import types#输入对象的类型print(type("www.qingsword.com"))#判断对象是否为字符串类型print(type("qingsword.com")==str)#程序输入<class 'str'>TRUE#如果对象是一个函数,就须要借助types模块中定义的常量来判断了#--------def fx(): return 0#判断fx是否为函数类型print(type(fx)==types.FunctionType)#判断是否为lambda类型print(type(lambda :0)==types.LambdaType)#判断len是否为内置的函数类型print(type(len)==types.BuiltinFunctionType)#判断表达式是否为列表生成器类型print(type((x for x in range(10)))==types.GeneratorType)#程序输入都为True#isinstance同样可能实现这些操作,例如将判断fx函数的语句改成上面这样,返回值同样是Trueprint(isinstance(fx,types.FunctionType))
除了下面的两种对象类型判断外,配合getattr()、setattr()以及hasattr(),咱们能够间接操作一个对象的状态,请看上面的实例:
#!/usr/bin/env python#coding=utf-8class Ob_A(object): #--------- def __init__(self,x=0): if type(x)==int: self.a=x else: raise TypeError("传入参数类型(%s)谬误,正确的参数类型int"%type(x)) #--------- def sq(self): return self.a*self.aoba=Ob_A(12)#判断oba对象中是否有属性(或办法)a,返回Trueprint(hasattr(oba,"a"))#获取属性(或办法)a,本例中a是一个属性值12,所以被print间接打印了进去print(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是一个办法类型print(type(sq))#执行sq办法,返回144print(sq())#程序输入TRUE12FALSETRUE13TRUE<class 'method'>144
这三个函数可用于探测对象中的信息,只有在不晓得对象信息的时候,才会应用这三个函数,如果曾经明确晓得了一个对象中蕴含了哪些属性和办法,请间接调用他们。
0×6.实例属性与类属性
python是动静语言,在实例化后,还能给实例增加新的属性,但最好不要与类中的属性同名,请看上面的实例:
#!/usr/bin/env python#coding=utf-8#Ob_A类中定义了一个类属性x,并且配置了其值为2class Ob_A(object): x=2#实例化Ob_A类oba=Ob_A()#给oba实例创立一个新属性x,因为和Ob_A类中的属性同名,所以会笼罩原有属性值oba.x=1#打印出1print(oba.x)#类中的属性放弃不变,打印出2print(Ob_A.x)#此时如果手动删除oba实例的x对象,再次打印oba实例的x对象,就会打印出原类中绑定的属性x值,打印出2del oba.xprint(oba.x)#程序输入122
类在实例化后,如果须要给实例新增属性,倡议属性名不要应用与原类中曾经存在的属性同名,因为雷同名称的实例属性将屏蔽掉类属性。
0×7.属性和办法的动静绑定
Python属于高级动静语言,与动态语言不同,当咱们实例化一个类对象后,能够动静的给这个类实例绑定属性或办法,请看上面的实例:
#!/usr/bin/env python#coding=utf-8from types import MethodType#定义一个类,仅蕴含一个age属性class Ob_A(object): def __init__(self,age=0): self.age=age#实例化Ob_A类a=Ob_A(23)#给Ob_A类的实例a新增一个name属性a.name="qingsword"#定义一个内部办法,稍后将它绑定到a实例def get_sex(self): return "male"#应用types模块中的MethodType办法,将get_sex这个内部办法绑定到a实例的getsex变量上a.getsex=MethodType(get_sex,a)#执行a实例的getsex()就相当于执行了get_sex()print(a.getsex())#程序输入male#getsex名称仅限于a实例调用,如果此时再实例化一个Ob_A类,除非再次应用MethodType绑定一个新的get_sex办法,否则这个新的类实例是不能应用get_sex这个内部办法的
从下面这个实例能够看出,Python不会限度一个对象实例绑定多少内部属性和办法,但如果要限度他们,能够在类中应用__slots__属性,请看上面的实例:
#!/usr/bin/env python#coding=utf-8from types import MethodType########class Ob_A(object): def __init__(self,age=0): self.age=age #定义了 __slots__属性后,Ob_A本身和所有实例,都只能应用这个元组中所蕴含的元素作为属性或办法名称 __slots__=("name","age","get_sex")#########但__slots__属性对继承它的子类有效,除非这个子类中也蕴含一个__slots__属性,那么这个子类能够定义的属性或办法名就是本人的__slots__元组中蕴含的元素加上父类__slots__元组中蕴含的元素的汇合class Ob_B(Ob_A): x=0########def get_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属性,指向了本站网址这段字符串地址b=Ob_B()b.web="www.qingsword.com"print(b.web)
0×8.如何将类办法封装成属性
这一部分将应用python内置的@property装璜器,将类中的办法转换成属性,在内部看来,这个办法就像一个一般属性那样应用,请看上面的实例:
#!/usr/bin/env python#coding=utf-8from datetime import datetime########class Ob_A(object): def __init__(self,birth=2016): """初始化配置出身年份""" self.__birth=birth #应用@property装璜器将birth办法转换成属性 @property def birth(self): """获取出身年份""" return self.__birth #应用@办法名.setter将这个办法设置成可写属性(一个办法名称必须先应用过property装璜器,能力应用setter) @birth.setter def birth(self,birth): """设置出身年份""" self.__birth=birth #仅有一个@property没有setter的办法,相当于一个只读属性 @property def age(self): """返回年龄""" y=datetime.now() return y.year-self.__birthx=Ob_A(2008)print(x.birth)#能够像设置属性值那样复制(如果是办法语法应该是x.birth(2000))x.birth=2000print(x.birth)print(x.age)#程序输入2008200016
尽管下面的实例中,并没有对年龄做进一步的检测(比方年龄范畴,输出类型等),但也不难看出,将函数封装成属性的款式能够让调用者写出更直观代码(比方x.birth=2000,而不是x.birth(2000)),而对封装者而言,能够在函数中去做各种条件判断来保障逻辑的正当。