美文网首页
零散笔记

零散笔记

作者: SHISHENGJIA | 来源:发表于2017-05-17 00:50 被阅读20次

    1

    函数式语言通常会提供 map、filter 和 reduce 三个高阶函数(有时使用不同的名称)。在 Python 3 中,map 和 filter 还是内置函数,但是由于引入了列表推导和生成器表达式,它们变得没那么重要了。列表推导或生成器表达式具有 map 和 filter 两个函数的功能,而且更易于阅读。

    2

    仅限关键字参数是 Python 3 新增的特性。定义函数时若想指定仅限关键字参数,要把它们放到前面有 * 的参数后面。如果不想支持数量不定的定位参数,但是想支持仅限关键字参数,在签名中放一个 *,如下所示:

    >>> def f(a, *, b):
    ...     return a, b
    ...
    >>> f(1, b=2)
    (1, 2)
    

    注意,仅限关键字参数不一定要有默认值,可以像上例中 b 那样,强制必须传入实参。
    下面看一个实例,生成HTML标签

    def tag(name, *content, cls=None, **attrs):
        if cls is not None:
            attrs['class'] = cls
        
        # 将attrs里的内容拼接
        if attrs:
            attrs_str = ' '.join('%s="%s"' % attr for attr in attrs.items() )
        else:
            attrs_str = ''
        
        # 组装一个完整的html标签
        if content:
            return '\n'.join('<%s %s>%s</%s>' % (name, attrs_str, c, name) for c in content)
        else:
            return '</ %s>' % name
    
    # cls是仅限关键字参数,赋值时必须以 参数名=值 的形式
    print(tag('a', '采纳', '点赞', cls='btn', href='www.baidu.com'))
    """
    <a class="btn" href="www.baidu.com">采纳</a>
    <a class="btn" href="www.baidu.com">点赞</a>
    """
    

    3

    要想创建可散列的类型,不一定要实现特性,也不一定要保护实例属性。只需正确地实现__hash____eq__ 方法即可。但是,实例的散列值绝不应该变化,因此我们借机提到了只读特性。

    4

    如果使用得当,__slots__ 能显著节省内存,不过有几点要注意。

    • 每个子类都要定义 __slots__ 属性,因为解释器会忽略继承的 __slots__ 属性。

    • 实例只能拥有 __slots__ 中列出的属性,除非把 __dict__ 加入 __slots__ 中(这样做就失去了节省内存的功效)。

    • 如果不把 __weakref__ 加入 __slots__,实例就不能作为弱引用的目标。

    5

    属性查找失败后,解释器会调用 __getattr__ 方法。简单来说,对 my_obj.x 表达式,Python 会检查 my_obj 实例有没有名为 x 的属性;如果没有,到类(my_obj.__class__)中查找;如果还没有,顺着继承树继续查找。 如果依旧找不到,调用 my_obj 所属类中定义的 __getattr__ 方法,传入 self 和属性名称的字符串形式(如 'x'

    6

    使用 reduce 函数时最好提供第三个参数,reduce(function, iterable, initializer),这样能避免这个异常:TypeError: reduce() of empty sequence with no initial value(这个错误消息很棒,说明了问题,还提供了解决方法)。如果序列为空,initializer 是返回的结果;否则,在归约中使用它作为第一个参数,因此应该使用恒等值。比如,对 +|^ 来说, initializer 应该是 0;而对 *& 来说,应该是 1

    7

    如果没有 __iter____contains__ 方法,Python 会调用 __getitem__ 方法,设法让迭代和 in 运算符可用。

    8

    猴子补丁

    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]
    

    FrenchDeck类还不能使用random.shuffle 函数随意打乱集合中元素的位置,因为FrenchDeck 只实现了不可变的序列协议。可变的序列还必须提供 __setitem__ 方法。
    下面在控制台进行修正

    >>> def set_card(deck, position, card): 
    ...     deck._cards[position] = card
    ...
    >>> FrenchDeck.__setitem__ = set_card 
    >>> shuffle(deck) 
    >>> deck[:5]
    [Card(rank='3', suit='hearts'), Card(rank='4', suit='diamonds'), Card(rank='4',
    suit='clubs'), Card(rank='7', suit='hearts'), Card(rank='9', suit='spades')]
    

    特殊方法 __setitem__的签名在 Python 语言参考手册的“3.3.6. Emulating container types”中定义。语言参考中使用的参数是 selfkeyvalue

    相关文章

      网友评论

          本文标题:零散笔记

          本文链接:https://www.haomeiwen.com/subject/idxlxxtx.html