zoukankan      html  css  js  c++  java
  • Python用起来极度舒适的强大背后

      当你使用len(a)获取a的长度,使用obj[key]获取一个key的值时的畅快和舒适,在于Python庞大的设计思想(Pythonic)。

      而obj[key]背后其实是__getitem__方法,Python实现的会被框架本身调用的方法之一。像__len__,__getitem__这样的方法称为特殊方法或者双下方法。

      下面用一个例子展示如何实现这两个特殊方法,以及见证特殊方法的强大:

        此处用到collections模块中的namedtuple方法,返回一个具名元组子类。

    # -*- coding: utf-8 -*-
    # Nola
    
    import collections
    from random import choice
    
    Card = collections.namedtuple('Card', ['rank', 'suit'])  # 返回具有命名字段的元组的新子类 表示一张牌
    
    suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)  # ♣->♦->♥->♠ 2-A 花色和大小从小到大 0(2梅花色)-51(A黑桃色) 花色大小映射
    
    def spades_high(card):
        """
        纸牌升序
        :param card:
        :return:
        """
        rank_value = FrenchDeck.ranks.index(card.rank)  # 获取纸牌大小index
        return rank_value * len(suit_values) + suit_values[card.suit]  # 纸牌大小index * 4色 + 花色权重 2clubs=0 2diamonds=1
    
    
    class FrenchDeck(object):
        # ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] 13
        ranks = [str(n) for n in range(2, 11)] + list('JQKA')
        suits = 'spades diamonds clubs hearts'.split()  # ['spades', 'diamonds', 'clubs', 'hearts'] 4
    
        def __init__(self):
            self._cards = [Card(rank, suit) for rank in self.ranks
                                            for suit in self.suits]
    
        def __len__(self):
            return len(self._cards)
    
        def __getitem__(self, position):
            return self._cards[position]
    
    if __name__ == '__main__':
        # namedtuple用法
        Point = collections.namedtuple('Point', ['x', 'y'])
        print(Point.__doc__)  # docstring   Point(x, y)
        p = Point(11, 22)
        print(p[0] + p[1])  # 使用index
        x, y = p  # 像元组一样解包
        print(x, y)
        print(p.x, p.y)  # 使用字段名获取对应值
        d = p._asdict()  # 转为dict  OrderedDict([('x', 11), ('y', 22)]) 11 22
        print(d, d['x'], d['y'])
        print(Point(**d))  # dict打包为新子类  Point(x=11, y=22)
        print(p._replace(x=100))  # 类似str替换  Point(x=100, y=22)
        print('@.@ '*20 + "
    "*2)
    
    
        # 得到一个纸牌对象
        beer_card = Card('7', 'diamonds')
        print(beer_card)  # Card(rank='7', suit='diamonds')
        print('@.@ ' * 20 + "
    "*2)
    
        # len函数查看一叠牌有多少张
        deck = FrenchDeck()
        print(len(deck))  # 52
        print('@.@ ' * 20 + "
    "*2)
    
        # 使用__getitem__方法从一叠牌中抽取特定的一张牌
        print(deck[0])  # 第一张  Card(rank='2', suit='spandes')
        print(deck[-1])  # 最后一张  Card(rank='A', suit='hearts')
        print('@.@ ' * 20 + "
    " * 2)
    
        # 使用python内置函数random.choice随机抽取一张牌
        print(choice(deck))  # Card(rank='9', suit='hearts')
        print(choice(deck))  # Card(rank='3', suit='diamonds')
        print('@.@ ' * 20 + "
    " * 2)
    
        # 抽取最上面3张
        print(deck[:3])
        # 只看牌面是A的牌
        print(deck[-4:])
        print(deck[48:])
        print('@.@ ' * 20 + "
    " * 2)
    
        # 仅仅实现__getitem__方法,这一摞牌就编程可迭代了
        for card in deck[:5]:
            print(card)
        print('@.@ ' * 20 + "
    " * 2)
    
        # 反迭代reverse list
        for card in reversed(deck):
            if card.rank == "K":
                break
            print(card)
        print('@.@ ' * 20 + "
    " * 2)
    
        # in运算符可用在FrenchDeck类上,因为它是可迭代的
        print(Card('Q', 'diamonds') in deck)
        print(Card('S', 'diamonds') in deck)
        print('@.@ ' * 20 + "
    " * 2)
    
        # spades_high函数对牌进行升序排序 标准库中sorted函数自增可根据指定key自增排序 reverse参数为True倒序
        for card in sorted(deck[:8], key=spades_high, reverse=True):
            print(card)
        # Card(rank='3', suit='spades')
        # Card(rank='3', suit='hearts')
        # Card(rank='3', suit='diamonds')
        # Card(rank='3', suit='clubs')
        # Card(rank='2', suit='spades')
        # Card(rank='2', suit='hearts')
        # Card(rank='2', suit='diamonds')
        # Card(rank='2', suit='clubs')
        print('@.@ ' * 20 + "
    " * 2)
    实践出真知~
  • 相关阅读:
    号称简明实用的django上手教程
    转先验概率、最大似然估计、贝叶斯估计、最大后验概率
    转基于概率的矩阵分解原理详解(PMF)
    转浅谈矩阵分解在推荐系统中的应用
    转推荐算法——基于矩阵分解的推荐算法
    代码生成器的需求
    兼容性的设计要求
    API设计的需求
    有关表单的需求梳理
    element-ui table 点击分页table滚到顶部
  • 原文地址:https://www.cnblogs.com/NolaLi/p/10616878.html
Copyright © 2011-2022 走看看