python最好的品质之一就是一致性。初步接触python可能会len(collection)而不是collection.len()觉得不适应,这是通常所说的“python风格”(Pythonic)的关键,体现在Python的数据模型上,数据模型是对Python框架的描述,它规范了这门语言自身构建模块的接口,这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。

特殊方法:以两个下划线开头,两个下划线结尾(例如__getitem__)。比如obj[key]背后就是__getitem__方法,为了能求得my_collection[key]的值,解释器实际上会调用my_collection.__getitem__(key)。

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:
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]

collections.namedtuple构建了一个简单的类表示一张纸盘,用以构建只有少数属性但是没有方法的对象,比如数据库条目。

>>> beer_card = Card('', 'diamods')
>>> beer_card
Card(rank='', suit='diamods')

用len()函数看看一叠牌有多少张:

>>> deck = FrenchDeck()
>>> len(deck)
52

从一叠牌中抽取特定的一张,比如第一张或者是最后一张,以下这些都是由__getitem__方法提供的:

>>> deck[0]
Card(rank='', suit='spades')
>>> deck[-1]
Card(rank='A', suit='hearts')
>>>

也可以随机抽取一张纸牌

>>> from random import choice
>>> choice(deck)
Card(rank='', suit='clubs')
>>> choice(deck)
Card(rank='', suit='clubs')
>>> choice(deck)
Card(rank='', suit='diamonds')

这是因为__getitem__方法把[]操作交给了self._cards列表,所以deck类会自动支持切片操作。

>>> deck[:3]
[Card(rank='', suit='spades'), Card(rank='', suit='spades'), Card(rank='', suit='spades')]
>>> deck[12::13]
[Card(rank='A', suit='spades'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='clubs'), Card(rank='A', suit='hearts')]

另外仅仅实现了__getitem__方法,这一摞牌就变成可迭代了

>>> for card in deck:
... print(card)
...
Card(rank='', suit='spades')
Card(rank='', suit='spades')
...

in运算符会按照顺序做迭代搜索,

>>> Card('Q', 'hearts') in deck
True
>>> Card('', 'beasts') in deck
False

排序,按照黑桃最大、红桃次之、方块再次、梅花最小

>>> suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
>>> def spades_high(card):
... rank_value = FrenchDeck.ranks.index(card.rank)
... return rank_value * len(suit_values) + suit_values[card.suit]
...
>>> for card in sorted(deck, key=spades_high):
... print(card)
...
Card(rank='', suit='clubs')
Card(rank='', suit='diamonds')
Card(rank='', suit='hearts')

按照目前的设计,FrenchDeck是不能洗牌的。

如何使用特殊方法

特殊方法的存在是为了被Python解释器调用的,是隐式的,并不需要调用他们。也就是说没有my_object.__len__()这种写法,而应该是len(my_object)。如果是Python内置的类型,比如列表list、字符串str,等,那么__len__会直接返回ob_size属性。

比如for i in x:这个语句,背后用的是iter(x),而这个函数的背后则是x.__iter__()方法。

通常代码无需直接使用特殊方法,除了__init__方法。

通过内置的函数(例如len、iter、str等等)来使用特殊方法是最好的选择,他们的速度更快。

另外不要自己想当然地随意添加特殊方法,比如__foo__之类的,因为虽然现在这个名字没有被Python内部使用,以后就不一定了。

字符串表达形式

python有一个内置的函数是repr,它能把一个对象用字符串的形式表达出来以便辨认。

%和str.format这两种格式化字符串的方法目前都在使用,但是str.format可能会越来越适用。

__repr__和__str__的区别在于,后者是在str()函数被使用,或者是在print函数打印才被调用的,并且返回的字符串对终端用户更友好。如果只想实现这两种中的一种,那么__repr__会是更好的选择。

流畅的python--python数据模型的更多相关文章

  1. python --- Python中的callable 函数

    python --- Python中的callable 函数 转自: http://archive.cnblogs.com/a/1798319/ Python中的callable 函数 callabl ...

  2. Micro Python - Python for microcontrollers

    Micro Python - Python for microcontrollers MicroPython

  3. 从Scratch到Python——python turtle 一种比pygame更加简洁的实现

    从Scratch到Python--python turtle 一种比pygame更加简洁的实现 现在很多学校都开设了Scratch课程,学生可以利用Scratch创作丰富的作品,然而Scratch之后 ...

  4. 从Scratch到Python——Python生成二维码

    # Python利用pyqrcode模块生成二维码 import pyqrcode import sys number = pyqrcode.create('从Scratch到Python--Pyth ...

  5. [Python]Python 使用 for 循环的小例子

    [Python]Python 使用 for 循环的小例子: In [7]: for i in range(5): ...: print "xxxx" ...: print &quo ...

  6. [python]python 遍历一个list 的小例子:

    [python]python 遍历一个list 的小例子: mlist=["aaa","bbb","ccc"]for ss in enume ...

  7. [Python]Python日期格式和字符串格式相互转换

    由字符串格式转化为日期格式的函数为: datetime.datetime.strptime() 由日期格式转化为字符串格式的函数为: datetime.datetime.strftime() # en ...

  8. [python]Python 字典(Dictionary) update()方法

    update() 函数把字典dict2的键/值对更新到dict里.如果后面的键有重复的会覆盖前面的语法dict.update(dict2) dict = {'Name': 'Zara', 'Age': ...

  9. 流畅的python python 序列

    内置序列 容器类型 list .tuple和collections.deque这些序列能放入不同的类型的数据 扁平序列 str.byets.bytearray.memoryview(内存视图)和arr ...

  10. [python]python try异常处理机制

    #python的try语句有两种风格 #一:种是处理异常(try/except/else) #二:种是无论是否发生异常都将执行最后的代码(try/finally) try/except/else风格 ...

随机推荐

  1. ASP.NET Web API Basic Identity 中的基本身份验证

    缺点 用户凭证在请求中发送. 凭据作为明文发送. 每个请求都会发送凭据. 无法注销,除非结束浏览器会话. 易于跨站点请求伪造(CSRF); 需要反CSRF措施. 优点 互联网标准. 受所有主要浏览器支 ...

  2. 页面传递的都是string ; 每个标签要有name的原因是为了取值 因为传递给后台是键值对的形式

    页面传递的都是string ; 每个标签要有name的原因是为了取值  因为传递给后台是键值对的形式

  3. codeforces231C

    To Add or Not to Add CodeForces - 231C A piece of paper contains an array of n integers a1, a2, ..., ...

  4. 使用poi将Excel文件转换为data数据

    pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:// ...

  5. Python Argparse模块

    argparse模块 在Python中,argparse模块是标准库中用来解析命令行参数的模块,用来替代已经过时的optparse模块.argparse模块能够根据程序中的定义从sys.argv中解析 ...

  6. HBase读取与写入流程

    写入流程 读取流程 https://yq.aliyun.com/articles/670748?spm=a2c4e.11153940.blogcont684011.28.427e4648CTtaPL

  7. 【BZOJ3999】【TJOI2015】旅游 树剖

    题目大意 给你一棵树,有\(n\)个点.有\(q\)个操作,每次要你从\(x\)到\(y\)的路径上选两个点,使得距离\(x\)比较远的点的点权\(-\)距离\(x\)比较近的点的点权最大,然后把这条 ...

  8. ubuntu18.4 中 mysql5.7 全完卸载与安装

    卸载 sudo apt-get autoremove --purge mysql-server-5.7 sudo apt-get remove mysql-server sudo apt-get au ...

  9. MS-DOS 系统汇编环境之DOSBOX+vim

    经过虚拟机的体验,我发现还是dosbox里汇编比较方便..... 一.下载安装 dosbox DOSBOX 准备好 masm.exe.link.exe.debug.exe,放在~/dos下(文件夹名字 ...

  10. 【HDU5950】Recursive sequence(矩阵快速幂)

    BUPT2017 wintertraining(15) #6F 题意 \(f(1)=a,f(2)=b,f(i)=2*(f(i-2)+f(i-1)+i^4)\) 给定n,a,b ,\(N,a,b < ...