《Python基础教程》读书笔记(2)之第7章更加抽象(关键词:Python/面向对象/多态/封装/方法/继承)

本文是《Python基础教程》第七章的读书笔记,深入探讨Python的面向对象特性:多态允许对不同类的对象使用相同的操作,封装隐藏对象的工作细节,继承则基于普通类创建专门的类对象。同时,介绍了类的定义、方法、命名空间、接口与内省等概念,强调了合理使用接口和内省的重要性。
摘要由CSDN通过智能技术生成

第7章 更加抽象

7.1 对象的魔力

□多态:意味着可以对不同类的对象使用同样的操作。
□封装:对外部世界隐藏对象的工作细节。
□继承:以普通的类为基础建立专门的类对象。

7.1.1 多态

    多态意味着,就算不知道变量所引用的对象类型是什么,还是能对它进行操作,而它也会根据对象(或类)类型的不同而表现出不同的行为。

1. 多态和方法

>>> object.getPrice()
2.5

绑定到对象特性上面的函数,称为方法(method)。

7.1.2 封装

    封装是对全局作用域中其他区域隐藏多余信息的原则。
    特性(attribute,属性)是对象内部的变量;
    方法更像是绑定到函数的属性。

7.1.3 继承

    如果已经有了一个类,而又想建立一个非常类似的呢?新的类可能只是添加几个方法。在编写新的类时,又不想把旧类的代码全都复制过去。

7.2 类和类型

7.2.1 类到底是什么

7.2.2 创建自己的类

__metaclass__ = type

class Person:

    def setName(self, name):
        self.name = name

    def getName(self):
        return self.name

    def greet(self):
        print "hello, world! i'm %s." % self.name

注意 新式类的语法中,需要在模块或者脚本开始的地方放置赋值语句__metaclass__ = type

    self是对于对象自身的引用。
>>> foo = Person()
>>> foo.setName('henry')
>>> foo
<__main__.Person object at 0x7f4f7e17db50>
>>> foo.greet()
hello, world! i'm henry.
>>> Person.greet(foo)
hello, world! i'm henry.

提示 foo是Person的实例,foo.greet()等价于Person.greet(foo)。

7.2.3 特性、函数和方法

self参数正是方法和函数的区别。方法(更专业一点可以称为绑定方法)将它们的第一个参数绑定到所属的实例上,因此这个参数可以不提供。

>>> p = Person()
>>> p.setName('henry')
>>> p.name
'henry'
>>> p.getName()
'henry'
>>> p.name = 'yan'
>>> p.getName()
'yan'
    每个对象管理自己的特性还不够吗?为什么还要对外部世界隐藏呢?毕竟,如果能直接使用ClosedObject的name特性的话,就不用使用setName和getName方法了。
    关键在于,其他程序员可能不知道(可能也不应该知道)你的对象内部的具体操作。例如,ClosedObject可能会在其他对象更改自己的名字的时候,还有其他的一些动作(例如,给一些管理员发送邮件信息)。这应该是setName方法的一部分。但是,如果直接用p.name设定名字,会发生什么?什么也没发生,Email也没发送出去。为了避免这类事情发生,应该使用私有(private)特性,这是外部对象无法访问,但是getName和setName等访问器(accessor)能够访问的特性。

Python并不直接支持私有方式,而要靠程序员自己把握在外部进行特性修改的时机。

    为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可:
__metaclass__ = type

class Secretive():

    def __inaccessible(self):
        print "you can't see me."

    def accessible(self):
        print "the secret message is:"
        self.__inaccessible()

现在__inaccessible从外界是无法访问的,而在类内部还能使用(比如从accessible)访问:

>>> s = Secretive()
>>> s.__inaccessible()

Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    s.__inaccessible()
AttributeError: 'Secretive' object has no attribute '__inaccessible'
>>> s.accessible()
the secret message is:
you can't see me.

类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。

>>> Secretive._Secretive__inaccessible
<unbound method Secretive.__inaccessible>

在了解了这些幕后的事情后,实际上还是能在类外访问这些私有方法,尽管不应该这么做:

>>> s._Secretive__inaccessible()
you can't see me.

简而言之,确保其他人不会访问对象的方法和特性是不可能的。

    如果不需要使用这种方法但是又想让其他对象不要访问内部数据,那么可以使用单下划线。例如,前面有下划线的名字都不会被带有星号的imports语句(from module import *)导入。

7.2.4 类的命名空间

定义类时,所有位于class语句中的代码都在特殊的命名空间中执行——类命名空间(class namespace)。这个命名空间可由类内所有成员访问。
并不是所有Python程序员都知道类的定义其实就是执行代码块,这一点非常有用,比如,在类的定义区并不只限使用def语句:

>>> class C:
    print 'Class C being defined...'


Class C being defined...

7.2.5 指定超类

7.2.6 调查继承

内建的issubclass函数可以查看一个类是否是另一个的子类。

>>> issubclass(SPAMFilter, Filter)

__bases__可以查看已知类的基类:

>>> class A(object):
...     pass
... 
>>> A.__bases__
(<type 'object'>,)

isinstance方法可以检查一个对象是否是一个类的实例:

>>> a = A()
>>> isinstance(a, A)
True

注意 使用isinstance并不是个好习惯,使用多态会好一些。
__class__可以知道一个对象属于哪个类。

>>> a.__class__
<class '__main__.A'>

注意 如果使用__metaclas__ = type或从object继承的方式来定义新式类,那么,可以使用type(s)查看实例的类。

7.2.7 多个超类

详见书上。
除非非常熟悉多重继承,否则应该尽量避免使用,因为有时候会出现不可预见的麻烦。

7.2.8 接口和内省

“接口”的概念与多态有关。
在处理多态对象时,只要关心它的接口(或称“协议”)即可——也就是公开的方法和特性。
hasattr()可以检查方法是否已经存在:

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

对象tc有一个叫做talk的特性(包含一个方法)。
callable能检查talk特性是否可调用:

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

注意 callable函数在Python3.0中已经不再可用。可以使用hasattr(x, __call__)代替callable(x)。

如果要查看对象内所有存储的值,那么可以使用__dict__特性。

>>> Person.__dict__
dict_proxy({'__module__': '__main__', 'setName': <function setName at 0x7f7b2abb5140>, 'getName': <function getName at 0x7f7b2abb51b8>, 'greet': <function greet at 0x7f7b2abb5230>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}) 

如果想要找到对象是由什么组成的,可以看看inspect模块。

7.4 小结

对象。对象包括属性和方法。属性只是作为对象的一部分的变量,方法则是存储在对象内的函数。(绑定)方法和其他函数的区别在于方法总是将对象作为自己的第一个参数,这个参数一般称为self。
类。
多态。
封装。对象可以将它们内部状态隐藏(或封装)起来。在Python中,所有的特性都是公开可用的。
继承。
接口和内省。
面向对象设计。


参考文献:
1.《Python基础教程(第2版·修订版)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值