【九】面向对象
一:使用class定义类
假设你要定义一下对象用于记录联系人,每个对象对应一个人,首先需要定义person类作为生产对象的模具。
首先创建一个没有任何内容的空类:
In [301]: class person(): ...: pass
二:对类进行初始化
init()是python中一个特殊的函数名,用户根据类的定义创建实例对象,self参数指向了这个正在被创建对象本身
#定义一个person类 #给person类创建一个初始化函数 In [302]: class person(): ...: def __init__(self,name): ...: self.name=name ...:
用person类创建一个对象,为name特性传递一个字符串参数:
#python执行:person.__init__(huahua,"cmf"),self代表实例化的对象,这个例子指的是huahua In [304]: huahua=person("cmf") In [305]: huahua.name Out[305]: 'cmf'
上述代码做了如下工作:
- 查看person类的定义
- 在内存中实例化一个新的对象
- 调用对象的init方法,将这个新创建的对象作为self传入,并将并一个参数cmf作为name传入
- 将name的值存入对象
- 返回这个新的对象
- 将huahua与这个对象关联
三:继承
利用类的继承,从已有类中衍生出新的类,添加和修改部分功能。使用继承得到的新类会自动获取旧类中的很多方法,从而不需要复制
#创建一个person类 In [306]: class person(): ...: pass #创建一个testperson类,继承person ...: class testperson(person): ...: pass
接着,为每个类创建一个实例对象:
In [307]: ren=person()
In [308]: test1=testperson()
子类是父类的一种特殊情况,它属于父类
#创建父类 In [310]: class person(): ...: def exclain(self): ...: print("i am a person") ...: #创建子类,并继承父类 In [311]: class testperson(person): ...: pass ...: #实例化 In [312]: ren=person() In [313]: test=testperson() #调用父类的方法 In [314]: ren.exclain() i am a person #调用父类的方法 In [315]: test.exclain() i am a person
四:覆盖方法
新创建的子类会自动继承父类的所有信息,接下来我们来看看子类如何替代(覆盖)父类的方法
In [316]: class person(): ...: def exclain(self): ...: print("i am a person") ...: #创建一个新的同名方法,覆盖父类方法 In [317]: class testperson(person): ...: def exclain(self): ...: print("i am a testperson") ...: ...: In [318]: ren=person() In [319]: test=testperson() In [320]: ren.exclain() i am a person In [321]: test.exclain() i am a testperson
为子类添加新方法
In [325]: class person(): ...: def __init__(self,name): ...: self.name=name ...: ...: In [326]: class testperson(person): ...: def __init__(self,name,email): ...: super().__init__(name) #super:继承父类的name方法 ...: self.email=email ...: In [327]: test=testperson("test","test@qq.com") In [328]: test.name Out[328]: 'test' In [329]: test.email Out[329]: 'test@qq.com' In [330]: ren=person("ren") In [331]: ren.name Out[331]: 'ren' #父类不能访问子类特有的方法 In [332]: ren.email --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-332-0d7ad82f0acc> in <module>() ----> 1 ren.email AttributeError: 'person' object has no attribute 'email'
五:property属性
property() 函数的作用是在新式类中返回属性值。
In [375]: class duck(): ...: def __init__(self,input_name): ...: self.hidden_name=input_name #定义get和set方法 ...: def get_name(self): ...: print("inside the getter") ...: return self.hidden_name ...: def set_name(self,input_name): ...: print("inside the setter") ...: self.hidden_name=input_name ...: name=property(get_name,set_name) ...: #方式1 In [376]: fowl=duck("caicai") In [377]: fowl.name inside the getter Out[377]: 'caicai' In [378]: fowl.get_name() inside the getter Out[378]: 'caicai' #方式二 In [379]: fowl.name="cmf" inside the setter In [380]: fowl.name inside the getter Out[380]: 'cmf' #方式三 In [382]: fowl.set_name("caiminfang") inside the setter In [383]: fowl.name inside the getter Out[383]: 'caiminfang'
实例
In [2]: class Duck(): ...: def __init__(self,input_name): ...: self.hidden_name=input_name ...: @property ...: def name(self): ...: print("insede the getter") ...: return self.hidden_name ...: @name.setter ...: def name(self,input_name): ...: print("inside the setter") ...: self.hidden_name=input_name ...: In [3]: ff=Duck("huahua") In [4]: ff.name insede the getter Out[4]: 'huahua' In [5]: ff.name="cmf" inside the setter In [6]: ff.name insede the getter Out[6]: 'cmf'
property底层代码
In [7]: property? Init signature: property(self, /, *args, **kwargs) Docstring: property(fget=None, fset=None, fdel=None, doc=None) -> property attribute fget is a function to be used for getting an attribute value, and likewise fset is a function for setting, and fdel a function for del'ing, an attribute. Typical use is to define a managed attribute x: class C(object): def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I'm the 'x' property.") Decorators make defining new properties or modifying existing ones easy: class C(object): @property def x(self): "I am the 'x' property." return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x Type: type
六:类方法
也叫类型方法,用@classmethod做标记的方法.假设其有n个必传参数,如果是类调用,则需要传n-1个参数,第一个参数同样是内定的类型本身。如果是实例调用,则需要传n个参数。类方法要让类型能调用,当然也需要至少一个参数.
类方法,第一个参数必须要默认传类,一般习惯用cls。
In [24]: class a(): ...: count=0 ...: def __init__(self): ...: a.count+=1 ...: print(a.count) ...: def ex(self): ...: print("i am a") ...: @classmethod ...: def kids(cls): ...: print("a has",cls.count) ...: In [25]: aa=a() 1 In [26]: bb=a() 2 In [27]: cc=a() 3 In [28]: a.kids() a has 3
七:静态方法
@staticmethod标记的方法。类和实例都可以调用。无内定的参数问题,方法有多少参数就必须传递多少参数。
静态方法,参数没有要求。下面例子为空
In [29]: class a(): ...: @staticmethod ...: def name(): ...: print("name") ...: In [30]: a.name() name
八:魔术方法
除了__init__()外,还有最常用的__str__(),他用于定义如何打印信息。print()方法,str()方法以及一些字符串格式化的相关方法都会用到__str__(),交互式解释器则用__repr__()方法输出变了。
如果你的类既没有定义__str__()也没有定义___repr__(),python会输出类似下面的默认字符串:
In [37]: class word(): ...: def __init__(self,text): ...: self.text=text ...: def equals(self,word2): ...: return self.text.lower()==word2.text.lower() ...: In [38]: first=word('ha') In [39]: second=word("qwe") In [40]: third=word('HA') In [41]: first.equals(third) Out[41]: True In [42]: first.equals(second) Out[42]: False In [43]: first==second Out[43]: False #由于该类中没有__str__(),__repr__()方法,所以出现了下面的字符串 In [44]: first Out[44]: <__main__.word at 0x7f841efaaeb8>
我们将__str__()和__repr__()方法都加到word类中,让输出的信息更变好看些
In [45]: class word(): ...: def __init__(self,text): ...: self.text=text ...: def equals(self,word2): ...: return self.text.lower()==word2.text.lower() ...: def __str__(self): ...: return self.text ...: def __repr__(self): ...: return 'word('+self.text+')' ...: In [46]: first=word('ha') In [47]: first Out[47]: word(ha) In [48]: print(first) ha
九组合(compositoon)和聚合(aggregation)
In [62]: class hair(): ...: def __init__(self,color): ...: self.color=color ...: #定义头发的颜色 In [63]: class mouth(): ...: def __init__(self,size): ...: self.size=size ...: #定义嘴巴的函数 In [64]: class Person(): ...: def __init__(self,hair,mouth): ...: self.hair=hair ...: self.mouth=mouth ...: def about(self): #print(Hair.color,Mouth.size)该处的Hair必须写hair的实例化对象 ...: print(Hair.color,Mouth.size) ...: In [65]: Hair=hair("yellow") In [66]: Mouth=mouth("small") In [67]: person=Person(Hair,Mouth) In [68]: person.about() yellow small