Python学习8——面向对象

写在开头:

这部分学习总结本来应该是抽象的延续,但是我却不想用“抽象2”来给标题命名,我觉得这节的内容更适合称为“面向对象”。

 

创建自定义对象是Python的核心概念,Python可以同java语言一样,被视为是一种面向对象语言。在面向对象编程中,术语对象大致意味着一系列访问和操作这些数据的方法。

有一点java基础的同学应该都了解,面向对象的3个基本特征:封装,继承,多态

 

多态:可对不同类型的对象执行相同的操作,而这些操作就像“被施了魔法”一样能够正常的运行。

你收到一个对象,却不知道它是如何实现的,它可能有很多种形态,但你可以访问它。

>>> 'abc'.count('a')
1
>>> [1,2,'a'].count('a')
1

上面的栗子,你不在乎这个变量是列表还是字符串,你都能调用count,只要你提供一个字符作为参数,它都能正常运行。

>>> def length_message(x):
    print('The length of',repr(x),'is',len(x))

    
>>> length_message('Fnord')
The length of 'Fnord' is 5

repr()返回的是一个对象的string格式,可用于任何对象。

 

关于类 :

类是一种对象。

每个对象都属于特定的类,并被称为该类的实例。

例:头顶飞过一只鸟,这只鸟就是“鸟类”的一个实例。鸟类是一个抽象的类,它包含很多子类,飞过的那只鸟可能就属于子类“云雀”。此时你可把鸟类当作鸟的集合,而“云雀”就是其中的一个子集,也可以叫做“鸟类”的子类,而“鸟类”为“云雀”的超类。

 

创建自定义类:

>>> class Person:   #Person是类的名称,首字母需大写;class语句创建独立的命名空间,用于在其中定义函数。
    def set_name(self,name):
        self.name = name
    def get_name(self):
        return self.name
    def greet(self):
        print('Hello,world! I\'m {}'.format(self.name))

        
>>> foo = Person()
>>> bar = Person()
>>> foo.set_name('Luke Skywalker')
>>> bar.set_name('Anakin Skywalker')
>>> foo.greet()
Hello,world! I'm Luke Skywalker
>>> bar.greet()
Hello,world! I'm Anakin Skywalker

对foo调用set_name和greet时,foo都会作为第一个参数自动传递给它们。所以参数self,指向对象本身。

 

封装:向外部隐藏不必要的细节。让你无需知道对象的构造就能使用它。

默认情况下,可从外部访问对象的属性。

>>> class Secretive:
    def __inaccessible(self):     #名称以两个下划线打头,可以让方法成为私有的(外部不能访问)
        print('Bet you can\'t see me ...')
    def accessible(self):
        print('The secret message is:')
        self.__inaccessible()

        
>>> s = Secretive()
>>> s.__inaccessible()    #外部无法访问__inaccessible
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    s.__inaccessible()
AttributeError: 'Secretive' object has no attribute '__inaccessible'
>>> s.accessible()      #却可以直接访问到accessible中的__inaccessible
The secret message is:
Bet you can't see me ...
>>> s._Secretive__inaccessible()
Bet you can't see me ...

在类定义中,对所有以两个下划线打头的名称都进行转换,即在开头加上一个下划线和类名。这种处理方法能从类外访问私有方法。

 

继承:可基于通用类创建出专用类。一个类可以是一个或多个类的子类,在这种情况下,子类将继承超类的所有方法。

>>> class Filter:    #定义一个超类
    def init(self):
        self.blocked = []
    def filter(self,sequence):    
        return [x for x in sequence if x not in self.blocked]

    
>>> class SPAMFilter(Filter):     #SPAMFilter是Filter的子类
    def init(self):           #重写超类Filter的方法init
        self.blocked = ['SPAM']    

        
>>> s = SPAMFilter()
>>> s.init()
>>> s.filter(['SPAM','eggs','abc','SPAM','ccc','SPAM','SPAM'])
['eggs', 'abc', 'ccc']
SPAMFilter类从Filter类继承了方法filter的定义,因此不用再重写编写filter方法细节,便能直接使用。

判断一个类是否是另一个类的子类,可使用内置方法issubclass(object,class).
>>> issubclass(SPMFilter,Filter)
True
>>> SPMFilter.__bases__    #访问属性__bases__,可以知道1个类的基类
(<class '__main__.Filter'>,)
>>> s = SPMFilter()
>>> isinstance(s,Filter)      #确定对象是否是特定类的实例,可使用isinstance
True
>>> isinstance(s,SPMFilter)
True        
>>> s.__class__      #使用属性__class__可以获取对象属于哪个类
<class '__main__.SPMFilter'>

 

多重继承

>>> class Calculator:
    def calculate(self,expression):
        self.value = eval(expression)

        
>>> class Talker:
    def talk(self):
        print('Hi,my value is',self.value)

        
>>> class TalkingCalculator(Calculator,Talker):
    pass

>>> tc = TalkingCalculator()
>>> tc.calculate('1+2*3')
>>> tc.talk()
Hi,my value is 7

hasattr(object, name)
判断一个对象里面是否有属性或者方法,返回BOOL值,有talk方法返回True, 否则返回False。

>>> hasattr(tc,'talk')
True
>>> hasattr(tc,'fnord')
False

getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,下面的默认值是None。

>>> getattr(tc,'talk',None)    #需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址
<bound method Talker.talk of <__main__.TalkingCalculator object at 0x0000000002B1D1D0>>
>>> getattr(tc,'fnord',None)
>>> getattr(tc,'fnord','None')
'None'

setattr(object, name, values) 
给对象的属性赋值,若属性不存在,先创建再赋值。

>>> setattr(tc,'name','Mr.Gumby')
>>> tc.name
'Mr.Gumby'

callable() 函数用于检查一个对象是否是可调用的。

>>> callable(getattr(tc,'talk',None))
True
>>> callable(getattr(tc,'fnord',None))
False

__dict__属性可查看对象中存储的所有值

>>> tc.__dict__
{'value': 7, 'name': 'Mr.Gumby'}

 

 

抽象基类

抽象类是不能实例化的类,其职责是定义子类应实现的一组抽象方法。

>>> from abc import ABC,abstractmethod    
>>> class Talker(ABC): 
    @abstractmethod   #@abstractmethod将方法标记为抽象的
    def talk(self):
        pass

>>> Talker()    #抽象类不能实例化
Traceback (most recent call last):
File "<pyshell#104>", line 1, in <module>
Talker()
TypeError: Can't instantiate abstract class Talker with abstract methods talk

>>> class King(Talker):
    def talk(self):     #重写方法talk
        print('Hi!')

        

>>> k = King()
>>> isinstance(k,Talker)  #isinstance 检查对象是否是特定类的实例
True
>>> k.talk()
Hi!

 

确定需要哪些类以及这些类应包含哪些方法:

1.将有关问题的描述记录下来,给所有的名词,动词和形容词加上标记;

2.在名词中找出可能的类;

3.在动词中找出可能的方法;

4.在形容词中找出可能的属性;

5.将找出的方法和属性分配给各个类。



posted @ 2019-06-26 22:52  酸菜泡饭  阅读(130)  评论(0编辑  收藏  举报