首页 > 代码库 > 【九】面向对象

【九】面向对象

一:使用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

上述代码做了如下工作:

  1. 查看person类的定义
  2. 在内存中实例化一个新的对象
  3. 调用对象的init方法,将这个新创建的对象作为self传入,并将并一个参数cmf作为name传入
  4. 将name的值存入对象
  5. 返回这个新的对象
  6. 将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 deling, 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

【九】面向对象