流畅的python–第一章 数据模型

Guido 对语言设计美学的深入理解让人震惊。我认识不少很不错的
编程语言设计者,他们设计出来的东西确实很精彩,但是从来都不
会有用户。Guido 知道如何在理论上做出一定妥协,设计出来的语
言让使用者觉得如沐春风,这真是不可多得。

——Jim Hugunin
Jython 的作者,AspectJ 的作者之一,.NET DLR 架构师

Python是我最喜欢的编程语言,可能是Python的风格吸引了我,比如获取一个字符串的长度可以用len(str),其他语言的风格可能是str.len()咳咳!

Python最好的品质就是一致性,这是这本书上说的,我的理解就是比如:我们可以用len获取大多数对象的长度,如,字符串,列表,元组,还有我们自定义的类通过实现__len__()也可以实现同样的特性,这样就保持了程序的一致性。这就是所谓的”Pythonic”吧。

python的数据模型

本书第一章讲的就是Python 的数据模型,因为数据模型是Python的核心组成。我的理解是Python的数据模型就是为了创建Python风格,而创建的个个组件,比如每个对象的底层都有很多的类似__len__()这样带前后双下划线的方法。这些方法赋予了Python魔力。Python的设计思想非常的有特色,通过慢慢学习就会体会到这门语言的特征。Python的设计思想完全体现在了数据模型上,数据模型是一堆一堆的为Python提供特色而发明的小组件。

不管在哪种框架下写程序,都会花费大量时间去实现那些会被框架本身调用的方法, Python 也不例外。Python 解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下划线开头,以两个下划线结尾(例如 __getitem__)。比如 obj[key]的背后就是 __getitem__ 方法,为了能求得 my_collection[key] 的值,解释器实际上会调用my_collection.__getitem__(key)。这些特殊方法名能让你自己的对象实现和支持以下的语言构架,并与之交互:

  • 迭代集合类
  •  属性访问
  • 运算符重载
  • 函数和方法的调用
  • 对象的创建和销毁
  • 字符串表示形式和格式化
  • 管理上下文(即 with 块)

上面这段是从该书上复制的,我的理解就是通过给我们自己的类添加实现__xxx__()这样的方法,就能与Python语言自身的大多数特性与之交互,这样我们自己的类看着就跟Python自身自带的类就没什么两样了。__xxx__()类似这样的方法在Python中称为特殊方法,我们用不到直接调用它们,比如在一个类中如果实现了__len__()这个方法,我们就可以直接使用len(类名)这样间接的调用__len__(),这就是Python的特殊所在。

一个纸牌程序

import collections
from random import choice

# 创建一个纸牌类,有两个属性1:rank,2: suit
Card = collections.namedtuple('Card', ['rank', 'suit'])


class FrenchDeck(object):
    """

    """
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits
                       for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]

    def getRandomCard(self):
        return choice(self._cards)

    def get4Card(self):
        card1 = list()
        for i in range(13):
            card1.append(self.getRandomCard())
            self._cards.pop(self._cards.index(card1[-1]))
        return card1

这个程序是从该书上复制的,getRandomCard()和get4Card()两个函数是我自己加的,前者是从随机抽取一张牌,用到了random模块中的choice方法,后者是抽取13张牌并且从原有牌中删除掉抽取出来的牌,相当于发13张牌,调用四次刚好把牌发完。该程序的核心是__len__()、__getitem__()这两个方法。

代码解释:

  1. 导入collections模块和random模块里边的choice方法
  2. 用collections模块里边的namedtuple()创建一个带名字的元组类Card,该类有两个属性’rank’和’suit’,用该模块创建的类只有属性。
  3. 创建类一个FrenchDeck类,该类是Python中的普通类
  4. 创建类中所需要的属性和方法
    1. 创建ranks列表,用了python中的列表生成表达式, range(2, 11)是生成纸牌的数字2~10, list(‘JQKA‘)是纸牌的非数字那几张
    2. suits是纸牌的花色,用到了字符串的split()方法,此方法将会分割字符串中有空格间隔的字符
    3. 在__init__()方法中再次用到Python中的列表生成表达式生成整副牌,列表生成式中用到了Card元组类,注意着里成员变量的前面有单下划线说明是私有的,尽量只在类内使用

发布者

峰影

峰影

做好自己,不要让自己后悔,每时每刻都要鼓励自己,这样才会有动力。现在是灰色的,但将来一定是彩色的,希望彩色不会来的太晚!

发表评论

电子邮件地址不会被公开。 必填项已用*标注