《Dive into Python》读书笔记之对象和面向对象

来源:互联网 发布:浙大恩特软件 编辑:程序博客网 时间:2024/05/17 04:49

Chapter 5:对象和面向对象

两种import方法

import random   # 使用时需要加上random前缀random.randint  # <bound method Random.randint of <random.Random object at 0x10101f620>>randint         # name 'randint' is not definedfrom random import randint  # 可以直接使用randint         # <bound method Random.randint of <random.Random object at 0x10101f620>>from random import *    # 导入所有方法

类的定义

from UserDict import UserDictclass FileInfo(UserDict):   # 创建FileInfo类并继承UserDict类    "store file metadata"   # 类的docstring    def __init__(self, filename=None):  #【1】        UserDict.__init__(self)         #【2】        self["name"] = filename         #【3】

【1】:__init__类似构造函数,self为每一个类方法都需要指定的参数,调用时不需指定,会自动加上。
【2】:Python不会自动调用父类的构造函数,必须显式调用父类合适的方法,包括__init__函数。
【3】:一般只能用self.name方式来指定成员变量,但此处因为继承了UserDict类,所以可以使用self["name"]方法来赋值。参考stackoverflow上的一篇文章:http://stackoverflow.com/questions/4117060/confused-by-selfname-filename。

垃圾回收

当指派给实例的变量超出作用域时,python会自动释放其空间。在下面的代码中,每一次执行leakmem函数时,之前的f已经超出了作用域被销毁,故执行过程中始终只有一个实例,不会发生内存泄漏。

def leakmem():     f = fileinfo.FileInfo('/music/_singles/kairo.mp3') for i in range(100):    leakmem()

探索UserDict:一个封装类

  • 可以在ipython中from UserDict import UserDict,再用UserDict?查看其内容和相关属性。
  • 在 Python 2.2 之前的版本中,你不可以直接子类化字符串、列表以及字典之类的内建数据类型。作为补偿,Python 提供封装类来模拟内建数据类型的行 为,比如:UserStringUserList 和 UserDict。通过混合使用普通和特殊方法, UserDict 类能十分出色地模仿字典。在 Python 2.2 和其后的版本中,你可以直 接从 dict 内建数据类型继承。这样之前的代码可以改写成如下代码。且无需导入UserDict模块和初始化子类。
  • 考虑两个类,base 和 child,base 中的 方法 a 需要调用 self.b;而我们又在 child 中覆盖了方法 b。然后我们创建一个 child 的实例,ch。调用 ch.a,那么此时的方法 a 调用的 b 函数将不是 base.b, 而是 child.b。
class FileInfo(dict):     "store file metadata"    def __init__(self, filename=None):        self["name"] = filename

专用类方法

  • __getitem__:使类可以模拟使用instance["key"]语句,即使用该语句时,python自动调用instace.__getitem__("key")方法,下同
  • __setitem__:模拟instance["key"] = value
  • __repr__: 返回对象的机器友好的字符串表示
  • __str__: 返回对象的人类友好的字符串表示,两者的区别详见此处。
  • __cmp__: 模拟cmp(instance1, instance2)
  • __len__: 模拟len(instance)
  • __delitem__ 模拟del instance[key]
  • 更多专用类方法详见官方文档。

类属性

在 Java 中,静态变量 (在 Python 中叫类属性) 和实例变量 (在 Python 中叫数 据属性) 两者都是紧跟在类定义之后定义的 (一个有 static 关键字,一个没有)。 在 Python 中,只有类属性可以定义在这里,数据属性定义在 __init__ 方法中

class counter:    count = 0   # 紧跟类名定义类属性    def __init__(self):    self.__class__.count += 1   # 通过该方法修改类属性 【1】counter.count   # 0c = counter()   c.count         # 1counter.count   # 1d = counter()d.count         # 2c.count         # 2counter.count   # 2

【1】:__class__ 是每个类实例的一个内置属性 (也是每个类的)。它是一个类的引 用,而 self 是一个类 (在本例中,是 counter 类) 的实例。

私有函数

  • 如果一个 Python 函数,类方法,或属性的名字以两个下划线开始 (但不是结束),它是私有的;其它所有的都是公有的。
  • 在 Python 中,所有的专用方法 (像 __setitem__) 和内置属性 (像 __doc__) 遵守一 个标准的命名习惯:开始和结束都有两个下划线。命名自己的私有函数时要避免这种做法。
class Test:    def _print(self):        print "hello, world!"    def __print(self):        print "can you see me?"t = Test()  t._print()   # "hello, world!"t.__print()  # AttributeError: Test instance has no attribute '__print'
0 0
原创粉丝点击