zoukankan      html  css  js  c++  java
  • Data Model: A Pythonic Card Deck & two-dimensional Vector

    1.  Example of two-dimensional vector: Vector(2,4) + Vector(2,1) results in Vector(4,5)

    import math
    
    
    # special methods used: __repr__ , __abs__ , __add__ , __mul__
    
    
    class Vector:
    
        def __init__(self, x=0, y=0):
            self.x = x
            self.y = y
    
        def __repr__(self):
            return "Vector(%r, %r)" % (self.x, self.y)
            # we use %r to obtain the standard representation of the attributes to be displayed.
            # !r should be used in the str.format method.
    
        def __abs__(self):
            return math.hypot(self.x, self.y)
            # math.hypot(x, y) 即相当于 math.sqrt(x*x + y*y)
    
        def __bool__(self):
            """
            By default, instances of user-defined classes are considered truthy, unless either __bool__ or __len__ is
            implemented. Basically, bool(x) calls x.__bool__() and uses the result. If __bool__ is not implemented, Python
            tries to invoke x.__len__(), and if that returns zero, bool returns False. Otherwise bool returns True.
            :return:
            """
            return bool(self.x or self.y)
    
        def __add__(self, other):
            x = self.x + other.x
            y = self.y + other.y
            return Vector(x, y)  # create and return a new instance of Vector
    
        def __mul__(self, other):
            return Vector(self.x * other, self.y * other)
    
        """
        in both __add__ and __mul__ , the methods should create and return a new instance of Vector, and DO NOT modify
        either operand -- 'self' or 'other'  (应该生成新的对象)
        """
    
    
    v1 = Vector(2, 4)
    v2 = Vector(2, 1)
    
    print(v2)
    print("add: v1 + v2", v1 + v2)
    
    v = Vector(3, 4)
    print("abs(3,4)", abs(v))
    
    print("v * 3", v * 3)
    
    print("abs(v*3)", abs(v * 3))

    2.1.  列表生成式的嵌套 for 循环:

    示例如下:

    li1 = range(1,6)
    li2 = list("ABC")    # list("ABC") 的结果为 ["A", "B", "C"]    
    
    for m in li1:
        for n in li2:
            print((m,n))
    
    li = [(m,n) for m in li1 for n in li2]
    print(li)
    
    
    # 输出结果:
    (1, 'A')
    (1, 'B')
    (1, 'C')
    (2, 'A')
    (2, 'B')
    (2, 'C')
    (3, 'A')
    (3, 'B')
    (3, 'C')
    (4, 'A')
    (4, 'B')
    (4, 'C')
    (5, 'A')
    (5, 'B')
    (5, 'C')
    [(1, 'A'), (1, 'B'), (1, 'C'), (2, 'A'), (2, 'B'), (2, 'C'), (3, 'A'), (3, 'B'), (3, 'C'), (4, 'A'), (4, 'B'), (4, 'C'), (5, 'A'), (5, 'B'), (5, 'C')]
    
    # 列表生成式中的 两个 for 循环 作用就相当于 for 循环的嵌套

    参考链接: https://www.jb51.net/article/150400.htm

    2.2   A Pythonic Card Deck: __len__ & __getitem__ 

    示例如下:

    import collections
    
    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]
    
    
    deck = FrenchDeck()
    
    print(len(deck))  # len() 实际只适合 dict, list 等;想要 适用于 deck ,就需要重写 __len__ 方法
    
    # output:
    # 52
    
    print(deck[0], deck[1])  # __getitem__ delegates to the [] operator
    """
    Special methods是理解Python语言的关键之一。例如,__getitem__特殊方法用来支持obj[key]。因此,当实现my_collection[key],解释器实际上调用的是my_collection.__getitem__(key)
    """
    
    # output:
    # Card(rank='2', suit='spades') Card(rank='3', suit='spades')
    
    import random
    
    print(random.choice(deck))
    print(random.choice(deck))
    print(random.choice(deck))
    
    # output:
    # Card(rank='8', suit='clubs')
    # Card(rank='J', suit='clubs')
    # Card(rank='2', suit='diamonds')
    
    """
    random.choice(seq) 的原理:
    random.choice内部实现是先用len方法获取总长度然后从0到总长度时间取一个随机数作为索引获取
    
    源码如下:
        def choice(self, seq):
            # Choose a random element from a non-empty sequence.
            try:
                i = self._randbelow(len(seq))
            except ValueError:
                raise IndexError('Cannot choose from an empty sequence') from None
            return seq[i]
    """
    
    # 切片: class slice(start, stop[, step])
    
    print(deck[12::13])
    
    # output:
    # [Card(rank='A', suit='spades'), Card(rank='A', suit='diamonds'),
    # Card(rank='A', suit='clubs'), Card(rank='A', suit='hearts')]
    
    
    for card in deck:
        print(card)
    # by implementing the __getitem__ special method, deck is also iterable
    # the statement -- for i in x: actually causes the invocation of iter(x), which in turn may call x.__iter__() if that is possible.
    
    # the deck can also be iterated in reverse :
    for card in reversed(deck):
        print(card)
    
    """
    reversed(seq)
        Return a reverse iterator. seq must be an object which has a __reversed__() method or supports the sequence protocol (the __len__() method and the __getitem__() method with integer arguments starting at 0).
    """
    
    print(Card("Q", "hearts") in deck)
    print(Card("7", "beasts") in deck)
    
    # output:
    # True
    # False
    
    # 特殊方法 __contains__ 是用来进行in检验的。
    
    
    # Sorting:
    """
    要求: 
    A common system of ranking cards is by rank(with aces being highest),then by suit the order of spades(highest), then hearts,
    diamonds, and clubs(lowest).
    """
    suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
    
    
    def spades_high(card):
        card_rank = FrenchDeck.ranks.index(card.rank)
        return card_rank * len(suit_values) + suit_values[card.suit]
    
    
    for card in sorted(deck, key=spades_high):
      # deck 中的每个 item 会传为 spades_high 的参数 传入 spades_high 中
    print(card) """ By implementing the special methods __len__ and __getitem__ , our FrenchDeck behaves like a standard Python sequence.

    The `list.sort` method sorts a list in place -- that is, without making a copy. (list.sort 方法是对一个列表进行【就地】排序;返回 None);
    In contrast , the built-in function `sorted` creates a new list and returns it. (返回排序后的 list)
    """
  • 相关阅读:
    查询详细信息和删除记录
    软件开发过程中常用到的一些工具
    无服务器端的UDP群聊功能剖析(WCF版)
    vim插件使用
    C#中ConnectionStrings和AppSettings的区别
    《Effective C++》简明笔记上
    设计模式的一些所想所得
    对RESTful Web API的理解与设计思路
    js加载脚
    OSGi.NET 学习笔记 [模块可扩展支持][概念][实例]
  • 原文地址:https://www.cnblogs.com/neozheng/p/12008795.html
Copyright © 2011-2022 走看看