5.3. 类的定义

Python 是完全面向对象的:你可以定义自已的类,从自已的或内置的类继承,然后从你定义的类创建实例。

Python 中定义类很简单。就像定义函数,没有单独的接口定义。只要定义类,然后就可以开始编码。Python 类以保留字 class 开始,后面跟着类名。从技术上讲,有这些就够了,因为一个类并非必须从其它类继承。

例 5.3. 最简单的 Python


class Loaf: 
    pass    
这个类的名字是 Loaf,它没有从其它类继承。类名通常是第一个字母大写,如:EachWordLikeThis,但这只是一个习惯,不是一个必要条件。
这个类没有定义任何方法或属性,但是从语法上,需要在定义中有些东西,所以你使用 pass。这是一个 Python 保留字,仅仅表示 “向前走,不要往这看”。它是一条什么都不做的语句,当你删空函数或类时,它是一个很好的占位符。
你可能猜到了,在类中的所有东西都要缩近,就像位于函数、if 语句,for 循环,诸如此类的代码。第一条不缩近的东西不属于这个类。
Python 中的 pass 语句就像 JavaC 中的大括号空集 ({})。

当然,实际上大多数的类都是从其它的类继承来的,并且它们会定义自已的类方法和属性。但是就像你刚才看到的,除了名字以外,类没有什么必须要具有的。特别是,C++ 程序员可能会感到奇怪,Python 的类没有显示的构造函数和析构函数。Python 类的确存在与构造函数相似的东西:__init__ 方法。

例 5.4. 定义 FileInfo


from UserDict import UserDict

class FileInfo(UserDict): 
Python 中,类的基类只是简单地列在类名后面的小括号里。所以 FileInfo 类是从 UserDict 类 (它是从 UserDict 模块导进来的) 继承来的。UserDict 是一个像字典一样工作的类,它允许你完全子类化字典数据类型,同时增加你自已的行为。{也存在相似的类 UserListUserString ,它们允许你子类化列表和字符串。)[2] 在这个类的背后有一些“巫术”,我们将在本章的后面,随着更进一步地研究 UserDict 类,揭开这些秘密。
Python 中,类的基类只是简单地列在类名后面的小括号里。不像在 Java 中有一个特殊的 extends 关键字。

Python 支持多重继承。在类名后面的小括号中,你可以列出许多你想要的类名,以逗号分隔。

5.3.1. 初始化并开始类编码

本例演示了使用 __init__ 方法来进行 FileInfo 类的初始化。

例 5.5. 初始化 FileInfo


class FileInfo(UserDict):
    "store file metadata"              
    def __init__(self, filename=None): 
类也可以 (并且应该) 有 doc strings ,时时彩计划软件公式:就像方法和函数一样。
__init__ 在类的实例创建后被立即调用。它可能会引诱你称之为类的构造函数,但这种说法并不正确。说它引诱,是因为它看上去像 (按照习惯,__init__ 是类中第一个定义的方法),行为也像 (在一个新创建的类实例中,它是首先被执行的代码),并且叫起来也像 (“init”当然意味着构造的本性)。说它不正确,是因为对象在调用 __init__ 时已经被构造出来了,你已经有了一个对类的新实例的有效引用。但 __init__ 是在 Python 中你可以得到的最接近构造函数的东西,并且它也扮演着非常相似的角色。
每个类方法的第一个参数,包括 __init__,都是指向类的当前实例的引用。按照习惯这个参数总是被称为 self。在 __init__ 方法中,self 指向新创建的对象;在其它的类方法中,它指向方法被调用的类实例。尽管当定义方法时你需要明确指定 self,但在调用方法时,你 用指定它,Python 会替你自动加上的。
__init__ 方法可以接受任意数目的参数,就像函数一样,参数可以用缺省值定义,即可以设置成对于调用者可选。在本例中,filename 有一个缺省值 None,即 Python 的空值。
习惯上,任何 Python 类方法的第一个参数 (对当前实例的引用) 都叫做 self。这个参数扮演着 C++Java 中的保留字 this 的角色,但 selfPython 中并不是一个保留字,它只是一个命名习惯。虽然如此,也请除了 self 之外不要使用其它的名字,这是一个非常坚固的习惯。

例 5.6. 编写 FileInfo


class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)        
        self["name"] = filename        
                                       
一些伪面向对象语言,像 Powerbuilder 有一种“扩展”构造函数和其它事件的概念,即父类的方法在子类的方法执行前被自动调用。Python 不是这样,你必须显示地调用在父类中的合适方法。
我告诉过你,这个类像字典一样工作,那么这里就是第一个印象。我们将参数 filename 赋值给对象 name 关键字,作为它的值。
注意 __init__ 方法从不返回一个值。

5.3.2. 了解何时去使用 self__init__

当定义你自已的类方法时,你必须 明确将 self 作为每个方法的第一个参数列出,包括 __init__。当从你的类中调用一个父类的一个方法时,你必须包括 self 参数。但当你从类的外部调用你的类方法时,你不必对 self 参数指定任何值;你完全将其忽略,而 Python 会自动地替你增加实例的引用。我知道刚开始这有些混乱,它并不是自相矛盾的,因为它依靠于一个你还不了解的区别 (在绑定与非绑定方法之间),故看上去是矛盾的。

噢。我知道有很多知识需要吸收,但是你要掌握它。所有的 Python 类以相同的方式工作,所以一旦你学会了一个,就是学会了全部。如果你忘了别的任何事,也要记住这件事,因为我认定它会让你出错:

__init__ 方法是可选的,但是一旦你定义了,就必须记得显示调用父类的 __init__ 方法 (如果它定义了的话)。这样更是正确的:无论何时子类想扩展父类的行为,后代方法必须在适当的时机,使用适当的参数,显式调用父类方法。

Footnotes

[2] 在 2.2 之后已经可以从 dict、list 来派生子类了,关于这一点作者在后文也会提到。――译注

时时彩胆拖 时时彩赔率是多少 时时彩博客计划分享 时时彩api接口 时时彩五星走势图网易
时时彩后二万能7码 很准的时时彩软件 新宝gg注册 手机版五星缩水软件 免费预测时时彩软件
重庆时时彩qq群号推荐 时时彩都有哪些软件 十分精彩时时彩软件 吉林时时彩11选5开奖结果走势图 时时彩投注网址
江西时时彩必赢技巧 江西时时彩每天几点开始 江西时时彩票网站 时时彩网站银狐娱乐 大淘宝时时彩官网怎么样
网易11选5走势图山东 德州扑克荷官教学视频 黑龙江11选5彩乐乐 北京11选5任五最大遗漏 内蒙古十一选五体彩图
22选5走势图 北京pk10计划软件 幸运赛车奖金对照表 上海11选5开奖结果查询 排列5走势图360
剑道独神txt下载 北京赛车是合法的吗 江西多乐彩开奖视频 安徽十一选五前三直选 捕鱼电玩游戏
幸运28评测网 江西快3开奖历史开奖 时时乐开奖走势图连线 海南飞鱼彩票技巧 盛兴彩票秒速赛车官网