Python面向对象编程过程中,我们为类实例化对象,通过对象指针访问类中对应的资源,那么这些资源大致分为三部分,分别是字段、方法、和属性,我们将这三个块统称为一个类的成员。1.字段 字段分为静态字段和动态字段。下面代码展示了类classMyClass中的两类字段:#静态字段,属于一个类,多个对象共享一个静态字段leader="abuve"def__init__(self):#动态字段属于对象,并且可以也称为普通字段。每个对象都会有自己独有的动态字段self.name="kevin" 动态字段在类的实例化过程中很常见,通过self为每个对象封装自己独有的数据,但是如果全部使用动态字段在类中,也会遇到一些不合理的弊端,比如下面的代码:..ifname=="__main__":it_dept=Company("IT","Abuve")hr_dept=Company("HR","Kevin") 我们通过动态字段为对象封装了自己独有的数据,但是这里我们发现公司名称company_name是“Center”。无论创建哪个部门的对象,公司名称都保持不变。我们知道动态字段是存储在对象中的,这样每个对象都包含一个company_name字段,这无疑增加了程序的内存开销,所以更合理的方式应该是使用静态字段,代码如下:classCompany:company_name="Center"def__init__(self,dept,leader):self.dept=deptself.leader=leaderdef...ifname=="__main__":it_dept=Company("IT","Abuve")hr_dept=Company("HR","Kevin")同时我们在调用字段的方式上也需要遵循一些规则:1.静态字段属于类,通过类来访问。2、动态字段属于对象,通过对象访问。对于上面的代码,我们通过以下方式访问字段数据:printit_dept.deptprinthr_dept.leaderprintCompany.company_name如果通过对象访问静态字段,也可以访问数据,因为对象也是通过对象指针指向自己的类,不在对象中的数据最终会被在类中搜索过,但是这种调用方式并没有通过对象来调用,而且还访问了类的静态字段printit_dept.company_name字段前加两个下划线,可以将该字段设置为私有字段,例如:classMyClass:def__init__(self,name):self.__name=namedefshow(self):printself.__nameifname=="__main__":object=MyClass("Abuve")#私有字段不能通过对象访问printobject.__name#私有字段通过类对象的内部方法访问.show()#也可以通过在类名前加下划线来访问printobject._MyClass__name。最后一种方法也是通过在类名前加下划线来访问私有字段,但大多数情况下尽量不要使用这种方法访问。2、方法 在Python面向对象编程中,方法调用最为常见,分为动态方法(普通方法)、静态方法、类方法,下面通过代码展示。classMyClass:def__init__(self,name):self.name=name#Commonmethoddefshow(self):returnself.name#Staticmethod@staticmethoddefdetail(name):print'%sisgoodperson.'%name#动态方法@classmethoddefshow_detail(cls??):cls.detail('Kevin')ifname=="__main__":object=MyClass("Jack")p_name=object.show()MyClass.detail(p_name)MyClass.show_detail()和字段一样,在调用方法时还是有一些规则需要遵循的。1.普通方法,由对象调用2.静态方法,由类调用3.类方法,是静态方法的一种,由类调用,执行时会自动传入类名,所以必须有一个默认的接收参数。静态方法仍然可以通过对象指针访问,但是这样的调用是不合理的。之所以将这个略显特殊的方法写到类中,也是因为它与类有一定的相关性。3.属性 如果说字段属于左边,方法属于右边,那么属性就属于中性,因为它具有方法的功能,同时可以通过字段访问。以下是包含该属性的代码段。classPageSet:def__init__(self,count,page_size):self.count=countself.page_size=page_size#通过装饰器把page_num变成一个属性,调用对象时不需要加括号@propertydefpage_num(self):page_count,remainder=divmod(self.count,self.page_size)ifremainder==0:returnpage_countelse:returnpage_count+1ifname=="__main__":#传入条目总数,以及单页大小page_tools=PageSet(108,10)#像访问字段一样执行page_num方法printpage_tools.page_num 以上代码实现了一个分页设置,我们使用装饰器属性将page_num方法变成一个属性,那么当方法是被对象调用,会像访问字段一样,不需要加括号。此时,我们只实现通过字段访问方法。通过下面的代码,我们还可以调用相关的属性赋值和删除动作。classPageSet:def__init__(self,count,page_size):self.count=countself.page_size=page_size@propertydefpage_num(self):page_count,remainder=divmod(self.count,self.page_size)如果余数==0:returnpage_countelse:returnpage_count+1@page_num.setterdefpage_num(self,value):printvalueprint'Thisissetfunction.'@page_num.deleterdefpage_num(self):print'这是删除函数。ifname=="__main__":page_tools=PageSet(108,10)#调用property修改属性page_tools.page_num#调用page_num.setter修改属性page_tools.page_num=12#调用page_num.deleter修改属性delpage_tools.page_num4.特殊成员 特殊成员是函数两边带有下划线的特殊方法,提供类特有的功能。1、__init__构造方法是最常用的方法。当我们实例化一个类时,对象数据是通过__init__构造方法来封装的。2.__del__析构函数,通过__del__函数构造具体的函数,当对对象进行del操作时,可以自动调用这部分代码,在程序执行相关垃圾回收时应用析构函数方法.3、__doc__评论,通过该对象,可以访问__doc__函数中指定的评论内容。4.__module__这个方法可以显示当前对象属于哪个模块。5.__class__该方法可以显示当前对象属于哪个类。6.__call__如果我们在类的实例化对象后面加上括号,类中的call方法就会自动执行。classMyClass:def__call__(self):print'Thisissomething...'ifname=="__main__":object=MyClass()object()7.__str__默认打印对象时,只能显示内存地址。__str__可以显示你想要返回的内容。classMyClass:def__str__(self):return'ThisistextthatIwanttoreturn...'ifname=="__main__":object=MyClass()打印对象可以将两个对象的内容相加。类MyClass:def__init__(self,company,ceo):self.company=companyself.ceo=ceodef__add__(self,other):return"%s---%s"%(self.company,other.ceo)obj1=MyClass("A","Abuve")obj2=MyClass("B","Kevin")printobj1+obj2代码最终打印出"A---Kevin"9,__dict__对象调用这个方法,可以打印All显示封装的数据,调用这个access可以打印出所有的方法。10、__getitem__、__setitem__、__delitem__通过字典操作对象,可以为对象设置相应的执行动作。类MyClass(object):def__getitem__(self,key):print'__getitem__',keydef__setitem__(self,key,value):print'__setitem__',key,valuedef__delitem__(self,key):print'__delitem__',keyifname=="__main__":obj=Myclass()result=obj['k1']#执行了__getitem__方法obj['k2']='abuve'#执行了__setitem__方法delobj['k1']#执行了__delitem__方法11,__iter__用于迭代器,返回一个可迭代的对象classMyClass(object):def__iter__(self):returniter([1,2,3,4,5])ifname=="__main__":obj=MyClass()foriinobj:printi12,isinstance/issubclass可以通过isinstance判断一个对象的类型,issubclass可以判断某两个类是否是继承关系类Class1():passclassClass2(Class1):passifname=="__main__":obj=Class2()#判断obj的类型是否为Class2printisinstance(obj,Class2)#isinstance也可以判断是否继承自父类printisinstance(obj,Class1)打印issubclass(Class2,Class1)
