美文网首页
《python基础教程(第三版)》第七章 抽象

《python基础教程(第三版)》第七章 抽象

作者: Colleen_oh | 来源:发表于2019-08-07 14:25 被阅读0次

    7.1 封装

    封装(encapsulation)指的是向外部隐藏不必要的细节。假设你有一个名为OpenObject的类:

    >>> o = OpenObject() # 对象就是这样创建的
    >>> o.set_name('Sir Lancelot')
    >>> o.get_name()
    'Sir Lancelot'
    

    你(通过像调用函数一样调用类)创建一个对象,并将其关联到变量o,然后就可以使用方法set_name和get_name了(假设OpenObject支持这些方法)。

    7.2 类

    每个对象都属于特定的类,并被称为该类的实例。
    例如,如果你在窗外看到一只鸟,这只鸟就是“鸟类”的一个实例。鸟类是一个非常通用(抽象)的类,它有多个子类:你看到的那只鸟可能属于子类“云雀”。你可将“鸟类”视为由所有鸟组成的集合,而“云雀”是其一个子集。一个类的对象为另一个类的对象的子集时,前者就是后者的子类。因此“云雀”为“鸟类”的子类,而“鸟类”为“云雀”的超类。

    7.2.1 创建自定义类

    下面是一个简单的示例:

    class Person:
         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))
    

    Person当然是类的名称。class语句创建独立的命名空间,用于在其中定义函数。self是什么。它指向对象本身。那么是哪个对象呢?下面通过创建两个实例来说明这一点。

    >>> 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. 
    

    7.2.2 深入探讨继承

    要确定一个类是否是另一个类的子类,可使用内置方法issubclass。
    如果你有一个类,并想知道它的基类,可访问其特殊属性bases

    >>> SPAMFilter.__bases__
    (<class __main__.Filter at 0x171e40>,)
    >>> Filter.__bases__
    (<class 'object'>,) 
    

    同样,要确定对象是否是特定类的实例,可使用isinstance。

    >>> s = SPAMFilter()
    >>> isinstance(s, SPAMFilter)
    True
    >>> isinstance(s, Filter) 
    True
    >>> isinstance(s, str)
    False 
    

    如果你要获悉对象属于哪个类,可使用属性class

    >>> s.__class__
    <class __main__.SPAMFilter at 0x1707c0>
    

    7.2.3 多个超类

    你可使用它来获悉类的基类,而基类可能有多个。为说明如何继承多个类,下面来创建几个类。

    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 
    

    子类TalkingCalculator本身无所作为,其所有的行为都是从超类那里继承的。关键是通过从Calculator那里继承calculate,并从Talker那里继承talk,它成了会说话的计算器。

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

    这被称为多重继承,是一个功能强大的工具。然而,除非万不得已,否则应避免使用多重继承,因为在有些情况下,它可能带来意外的“并发症”。

    7.2.4 接口和内省

    通常,你要求对象遵循特定的接口(即实现特定的方法),但如果需要,也可非常灵活地提出要求:不是直接调用方法并期待一切顺利,而是检查所需的方法是否存在;如果不存在就改弦易辙。

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

    在上述代码中,你发现tc(本章前面介绍的TalkingCalculator类的实例)包含属性talk(指向一个方法),但没有属性fnord。如果你愿意,还可以检查属性talk是否是可调用的。

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

    请注意,这里没有在if语句中使用hasattr并直接访问属性,而是使用了getattr(它让我能够指定属性不存在时使用的默认值,这里为None),然后对返回的对象调用callable。

    相关文章

      网友评论

          本文标题:《python基础教程(第三版)》第七章 抽象

          本文链接:https://www.haomeiwen.com/subject/movwdctx.html