1.1一摞Python风格的纸牌

参考资料Luciano Ramalho《流畅的python》

1、具名元组

from collections import namedtuple

City = namedtuple('City', 'name,country,population,coordinates')
# 创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。
# name country population coordinates都被称为“字段名”
# 后者也可以是由数个字符串组成的可迭代对象
# ['name','country','population','coordinates']
# 或者是由空格或逗号分隔开的字段名组成的字符串
# 'name,country,population,coordinates'
# 'name country population coordinates'
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
# 存放在对应字段里的数据要以一串参数的形式传入到构造函数中(注意,元组的构造函数却只接受单一的可迭代对象)
# 这个“却”字是相对于上面具名元组的创建而言的,因为在上面,参数各个字段名的传入就可以用多种对象
print(tokyo)
# City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))
print(tokyo.population)
# 36.933
print(tokyo[1])
# JP
# 可以通过“字段名”或者“位置(index)”来获取一个字段的信息。

2、一摞python风格的纸牌

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()

    # [str(n) for n in range(2, 11)] + list('JQKA') 即为['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
    # list('JQKA') 即为['J', 'Q', 'K', 'A']
    # 'spades diamonds clubs hearts'.split()即为['spades', 'diamonds', 'clubs', 'hearts']
    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits
                       for rank in self.ranks]

    # 类FrenchDeck的实例已被创建就会拥有属性_cards,该属性是一个list,list中的元素都是有名元组,这些元组都是由生成器
    # collections.namedtuple('Card', 'rank,suit')生成的。在向这个生成器传入参数时,运用了遍历操作。

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

    # 定义了一个实例方法,返回值是这个类的属性_cards的长度
    # 在计算机执行指令len(object)时,会立即映射这个方法,返回该方法的返回值,
    # 此时,len指令没有什么关于len本身的特定意义,只是简单地映射了这个方法。

    def __getitem__(self, position):
        return self._cards[position]
    # 在定义了方法__getitem__以后,这个对象就变得iterable,可以当做可迭代对象来使用
    # 具体把它当做什么可迭代对象,就要由__getitem__的返回值来定了
    # 一般而言,这个可迭代对象存储在实例的一个属性里


deck = FrenchDeck()
# 我们创建了一个对象deck
# 它具有属性_cards,它可具有方法__len__和__getitem__
# print(len(deck))
# print(deck[0])  # 第一张纸牌,应该是黑桃2
# print(deck[-1])  # 最后一张纸牌,应该是红桃A
# 上两行的代码得以实现是因为方法__getitem__

# from random import choice
#
# print(choice(deck))  # 从一个iterable中随机选取一个
# print(choice(deck))
# print(choice(deck))
# print(choice(deck))

# for card in deck:
#     print(card)# 这里用到了方法__getitem__
# # 还可以反向迭代
# for card in reversed(deck):
#     print(card)

suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)  # suit的值


def spade_high(card):
    rank_value = FrenchDeck.ranks.index(card.rank)  # rank的值
    # 在实例deck里面,每一个元素都是一个有名tuple,我们获取这个tuple的属性rank,即得到了扑克牌的点数,
    # 然后用index函数得到了点数在列表FrenchDeck.ranks中对应的索引,并将它作为扑克牌排序的依据之一赋值给rank_value
    return rank_value * len(suit_values) + suit_values[card.suit]
    # 这个排序依据的含义:
    # suit_values[card.suit]就是花色在字典suit_values中对应的值
    # len(suit_values)就是4
    # rank_value*4,也就是扑克牌的数字乘以4,那么要注意JQKA的处理


for card in sorted(deck, key=spade_high):  # deck是我们要进行排序的iterable,key=spade_high是排序依据
    print(card)
    # 这里的排序依据是一个函数,那么肯定是这样的:
    # 将iterable的每一个元素作为参数传入这个函数,得到int类型的返回值,根据这个返回值来进行排序
    # 由此可以推测,在spade_high函数体里的card其实是可迭代对象deck的元素。
    # sorted接受两个参数
    # arg1是需要进行排序的iterable
    # arg2是一个函数,这个函数应该满足以下条件
    # 参数是iterable arg1的element
    # 返回值是element通过某种法则得到的int

猜你喜欢

转载自blog.csdn.net/xi_yang_hui/article/details/83116352