Python的类

什么时候你应该使用 from module import

  • 如果你要经常访问模块的属性和方法,且不想一遍又一遍地敲入模块名,使用 from module import
  • 如果你想要有选择地导入某些属性和方法,而不想要其它的,使用 from module import
  • 如果模块包含的属性和方法与你的某个模块同名,你必须使用 import module 来避免名字冲突。

尽量少用 from module import * ,因为判定一个特殊的函数或属性是从哪来的有些困难,并且会造成调试和重构都更困难。

例子

>>> import types
>>> types.FunctionType             1
<type 'function'>
>>> FunctionType 2
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
NameError: There is no variable named 'FunctionType'

>>> from types import FunctionType 3
>>> FunctionType                   4
<type 'function'>

 

UserDict 是一个像字典一样工作的类,它允许你完全子类化字典数据类型,同时增加你自已的行为。{也存在相似的类 UserListUserString ,它们允许你子类化列表和字符串。)

from UserDict import UserDict

class FileInfo(UserDict):

Python 中,类的基类只是简单地列在类名后面的小括号里。不像在 Java 中有一个特殊的 extends 关键字。

 

class FileInfo(UserDict):
    "store file metadata"              1
    def __init__(self, filename=None): 2 3 4

1

类也可以 (并且应该) 有 doc strings ,就像方法和函数一样。

2

__init__ 在类的实例创建后被立即调用。它可能会引诱你称之为类的构造函数,但这种说法并不正确。说它引诱,是因为它看上去像 (按照习惯,__init__ 是类中第一个定义的方法),行为也像 (在一个新创建的类实例中,它是首先被执行的代码),并且叫起来也像 (“init”当然意味着构造的本性)。说它不正确,是因为对象在调用 __init__ 时已经被构造出来了,你已经有了一个对类的新实例的有效引用。但 __init__ 是在 Python 中你可以得到的最接近构造函数的东西,并且它也扮演着非常相似的角色。

3

每个类方法的第一个参数,包括 __init__,都是指向类的当前实例的引用。按照习惯这个参数总是被称为 self。在 __init__ 方法中,self 指向新创建的对象;在其它的类方法中,它指向方法被调用的类实例。尽管当定义方法时你需要明确指定 self,但在调用方法时,你 用指定它,Python 会替你自动加上的。

4

__init__ 方法可以接受任意数目的参数,就像函数一样,参数可以用缺省值定义,即可以设置成对于调用者可选。在本例中,filename 有一个缺省值 None,即 Python 的空值。


注意
习惯上,任何 Python 类方法的第一个参数 (对当前实例的引用) 都叫做 self。这个参数扮演着 C++Java 中的保留字 this 的角色,但 selfPython 中并不是一个保留字,它只是一个命名习惯。虽然如此,也请除了 self 之外不要使用其它的名字,这是一个非常坚固的习惯。

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)        1
        self["name"] = filename        2
                                       3

1

一些伪面向对象语言,像 Powerbuilder 有一种“扩展”构造函数和其它事件的概念,即父类的方法在子类的方法执行前被自动调用。Python 不是这样,你必须显示地调用在父类中的合适方法。

2

我告诉过你,这个类像字典一样工作,那么这里就是第一个印象。我们将参数 filename 赋值给对象 name 关键字,作为它的值。

3

注意 __init__ 方法从不返回一个值。
 
 
__init__ 方法是可选的,但是一旦你定义了,就必须记得显示调用父类的 __init__ 方法 (如果它定义了的话)。这样更是正确的:无论何时子类想扩展父类的行为,后代方法必须在适当的时机,使用适当的参数,显式调用父类方法。
>>> f=FileInfo("E:\KuGou\can you feel the love tonight.mp3")
>>> f.__class__
<class __main__.FileInfo at 0x00D841E0>
>>> f.__doc__
>>> f
{'name': 'E:\\KuGou\\can you feel the love tonight.mp3'}
实例化类对象
还记得什么时候 __init__ 方法将它的 filename 参数赋给 self["name"] 吗?哦,答案在这。在创建类实例时你传入的参数被正确发送到 __init__ 方法中 (当我们创建类实例时,我们所传递的参数被正确地发送给 __init__ 方法 (随同一起传递的还有对象的引用,self,它是由 Python 自动添加的)。
通常,你可以完全忘记内存管理,让 Python 在后面进行清理。
update 方法是一个字典复制器:它把一个字典中的键和值全部拷贝到另一个字典。这个操作并不 事先清空目标字典,如果一些键在目标字典中已经存在,则它们将被覆盖,那些键名在目标字典中不存在的则不改变。应该把 update 看作是合并函数,而不是复制函数。
JavaPowerbuilder 支持通过参数列表的重载,也就是 一个类可以有同名的多个方法,但这些方法或者是参数个数不同,或者是参数的类型不同。其它语言 (最明显如 PL/SQL) 甚至支持通过参数名的重载,也就是 一个类可以有同名的多个方法,这些方法有相同类型,相同个数的参数,但参数名不同。Python 两种都不支持,总之是没有任何形式的函数重载。
应该总是在 __init__ 方法中给一个实例的所有数据属性赋予一个初始值。这样做将会节省你在后面调试的时间,不必为捕捉因使用未初始化 (也就是不存在) 的属性而导致的 AttributeError 异常费时费力。
posted @ 2009-06-16 11:49  ninahan  阅读(5580)  评论(0编辑  收藏  举报