1.现在在看《流畅的Python》这本书,看了三页就发现,这本书果然不是让新手来入门的,一些很常见的知识点能被这个作者玩出花来,

唉,我就在想,下面要分析的这些的代码,就算我费劲巴拉的看懂了,又有什么用呢,我其实不想靠着技术吃饭,但是现在在这个岗位上,

就得在其位谋其职,悲哀。我在敲代码方面也没什么天赋,也没什么热情,老话说得好,‘女怕嫁错郎,男怕入错行’,

所以我得从IT行业抽出身来。anyway,进入正题。

2.python解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下划线开头,

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

import collections

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

class FrenchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
# ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
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):
# print("用的是我写的lenth")
# 如果不写这个方法,用len(deck)时会报错:TypeError: object of type 'FrenchDeck' has no len()
return len(self._cards) def __getitem__(self, position):
return self._cards[position]
>>> beer_card = Card('7','hearts')
>>> beer_card
Card(rank='7', suit='hearts')
这张牌就是红心7
FrenchDeck类中的self._cards生成了一个有52张'牌'的列表
[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), ...共52个]
suits = ['spades', 'diamonds', 'clubs', 'hearts']
namedtuple的作用:
>>> beer_card = Card('7','hearts')
>>> beer_card
Card(rank='7', suit='hearts')
FrenchDeck类支持的方法:
>>> deck = FrenchDeck()
>>> len(deck)
52
>>> from random import choice
>>> choice(deck)
支持分片:只看牌面是A的牌--先抽出索引是12的那张牌,然后每隔13张拿一张
>>> 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)
反向迭代
>>> for card in reversed(deck):
... print(card)
一个集合类型如果没有实现__contains__方法,in运算符就会按顺序做一次迭代搜索
>>> Card(rank='A', suit='spades') in deck
True

下面这段就厉害了,弄得我眼黑头晕的,弄了一早上才搞明白,怎么对这些扑克牌进行排序?

首先你会想到sorted,但我连它的key参数都不会用,何谈去排序这些扑克。sorted用法:

sorted最简单用法是对元素全部是数字的列表排序,另一种用法是对元素是元组或字典的列表排序

用到的参数是key,比如:对学生的分数进行排序:

list1 = [('david', 90), ('mary',90), ('sara',80),('lily',95)]
sorted(list1, key=lambda x: x[0]) # 按照元组中第一个元素排序
sorted(list1, key=lambda x: x[1]) # 按照元组中第二个元素排序
array = [{"age":20,"name":"a"},{"age":25,"name":"b"},{"age":10,"name":"c"}]
array1 = sorted(array,key=lambda x:x["age"]) # 按照年龄排序

下面要讲的例子,先抛个砖:

1.需求:将列表中的元素按照绝对值大小进行升序排列
list1 = [3,5,-4,-1,0,-2,-6]
sorted(list1, key=lambda x: abs(x)) 当然,也可以如下: list1 = [3,5,-4,-1,0,-2,-6]
def get_abs(x):
return abs(x)
sorted(list1,key=get_abs)
只不过这种方式的代码看起来不够Pythonic
2、应用在闭包中
def get_y(a,b):
return lambda x:ax+b
y1 = get_y(1,1)
y1(1) # 结果为2 当然,也可以用常规函数实现闭包,如下: def get_y(a,b):
def func(x):
return ax+b
return func
y1 = get_y(1,1)
y1(1) # 结果为2
只不过这种方式显得有点啰嗦。
那么是不是任何情况下lambda函数都要比常规函数更清晰明了呢?
Python之禅中有这么一句话:Explicit is better than implicit(明了胜于晦涩),就是说那种方式更清晰就用哪一种方式,不要盲目的都使用lambda表达式。

扑克牌排序代码:

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

一、这段代码我看了很长时间,这本书的作者竟然将这段代码放在书的第二页,我也是醉了,我觉得是挺难的,但不管怎样,硬着头皮上吧!

扑克牌排序规则:

用点数来判断扑克牌的大小,2最小,A最大;同时还要加上对花色的判断:

黑桃最大,红桃次之,方块再次,梅花最小。那么梅花2的大小是0,黑桃A是51.

分析一下这个函数:sorted(deck,key=spades_high),我在这里卡了很长时间,所以就有了上面的那块砖,先说一下这个函数是怎么运行的吧:

通过sorted将deck这一摞牌和排序函数spades_high()联系起来,每张牌都有数字,先获取牌面的数字在FrenchDeck.ranks中的索引,即:2的索引0,

3的索引1,4的索引2,类推3,4,5,6,7,8,9,10,11,A的索引12,这张牌多大取决于它的花色,即索引 乘 4 加 花色值,

二、spades_high(card),这里的card就是传进来的每一张牌,rank_values = FrenchDeck.ranks.index(card.rank),

获取这张纸牌(即纸牌的数字)在FrenchDeck.ranks中的索引,['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']

"最后返回这个牌的得分",rank_values * len(suit_values) + suit_values[card.suit],此时就讲完了么?

灵光一闪,这个函数返回了所有得分有什么用?sorted()拿到这些得分,怎么把牌排好序?我觉得是这样:

在得到了[所有得分]这个列表之后,进行排序,得到:[0,1,2,3,4,...51],

然后将原扑克列表中的元素,一一对应,是怎么对应的?函数在处理的时候应该记录了每张卡的得分,所以能对应上。

如下(原来的扑克列表可不是这样的,排好序的应该是重新开辟了一个内存空间):

[Card(rank='2', suit='clubs'),Card(rank='2', suit='diamonds'),Card(rank='2', suit='hearts'),...Card(rank='A', suit='spades')]

三、比如上面第一块砖:

list1 = [3,5,-4,-1,0,-2,-6]

def get_abs(x):
    return abs(x)
sorted(list1,key=get_abs)

函数先返回[3,5,4,1,0,2,6],然后排序[0,1,2,3,4,5,6],接着将list1中的每个元素,与排序后的列表对应,

0不变,1、2变成-1、-2,3不变,4变成-4,5不变,6变成-6,输出[0,-1,-2,3,-4,5,-6]

四、看不懂的lambda,只是把这两道题放在在这里提醒我,不要迷进去:

一道面试题:
list1=[7, -8, 5, 4, 0, -2, -5]
要求1.正数在前负数在后 2.整数从小到大 3.负数从大到小
解题思路:先按照正负排先后,再按照大小排先后
list1=[7, -8, 5, 4, 0, -2, -5]
print(sorted(list1,key=lambda x:(x<0,abs(x))))
[7, 5, 4, 0, -8, -2, -5]
[0, 4, 5, 7, -2, -5, -8] 一个经典的复杂例子
这是一个字符串排序,排序规则:小写<大写<奇数<偶数
s = ‘asdf234GDSdsf23’ #排序:小写-大写-奇数-偶数
print(“”.join(sorted(s, key=lambda x: (x.isdigit(),x.isdigit() and int(x) % 2 == 0,x.isupper(),x))))
原理:先比较元组的第一个值,FALSE

也不说什么脏话了,反正没什么成就感,这些东西耗费我整整一天时间啊,就这本书作者随手扔出来的一些小玩意,搞得我很不堪,

这就是传说当中的以我之短击他之长吧,法克!但还是会有不服,别人能会,我为什么嫌难,人总是活在矛盾中。总之,以后尽量不搞这些东西了。

《流畅的Python》一副扑克牌中的难点的更多相关文章

  1. 【转】从一副扑克牌中随机抽取N张

    该问题为产生不重复的随机数序列,形象点就是一副扑克牌中随机抽取N张. 摘自:不重复随机数列生成算法 改了一部分 /** * 从0-max随机选N个数出来 * **/ public static int ...

  2. C语言:判断t所指字符串中的字母是否由连续递增字母组成。-判断一个输入的任何整数n,是否等于某个连续正整数序列之和。-将一副扑克牌编号为1到54,以某种方式洗牌,这种方式是将这副牌分成两半,然后将他们交叉,并始终保持编号1的牌在最上方。

    //判断t所指字符串中的字母是否由连续递增字母组成. #include <stdio.h> #include <string.h> void NONO(); int fun( ...

  3. 《流畅的python》读书笔记

    流畅的python 第1章 python数据模型 ---1.1 一摞Python风格的纸牌 特殊方法,即__method__,又被称为魔术方法(magic method)或者双下方法(dunder-m ...

  4. 流畅的python(笔记)

    流畅的python中有很多奇技淫巧,整本书都在强调如何最大限度地利用Python 标准库.介绍了很多python的不常用的数据类型.操作.库等,对于入门python后想要提升对python的认识应该有 ...

  5. 流畅的python 对象引用 可变性和垃圾回收

    对象引用.可变性和垃圾回收 变量不是盒子 人们经常使用“变量是盒子”这样的比喻,但是这有碍于理解面向对象语言中的引用式变量.Python 变量类似于 Java 中的引用式变量,因此最好把它们理解为附加 ...

  6. [读书笔记]流畅的Python(Fluent Python)

    <流畅的Python>这本书是图灵科技翻译出版的一本书,作者Luciano Ramalho. 作者从Python的特性角度出发,以Python的数据模型和特殊方法为主线,主要介绍了pyth ...

  7. 《流畅的Python》Object References, Mutability, and Recycling--第8章

    Object References, Mutability, and Recycling 本章章节: Variables Are Not Boxes identity , Equality ,  Al ...

  8. SyntaxError: Non-UTF-8 code starting with '\xbb' in file D:\流畅学python\ex32.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

    1. 报错如下: SyntaxError: Non-UTF-8 code starting with '\xd3' in file D:\流畅学python\ex34.py on line 4, bu ...

  9. 如何使用Python在Kaggle竞赛中成为Top15

    如何使用Python在Kaggle竞赛中成为Top15 Kaggle比赛是一个学习数据科学和投资时间的非常的方式,我自己通过Kaggle学习到了很多数据科学的概念和思想,在我学习编程之后的几个月就开始 ...

随机推荐

  1. C语言中最常用标准库函数

    标准头文件包括: <asset.h>      <ctype.h>       <errno.h>       <float.h> <limits ...

  2. ★房贷计算器 APP

    一.目的 1. 这是一个蛮有用的小工具 2. 之前看了很多demo,第一次来完全的自己实现一个APP 3. 完成之后提交 App Store 4. 作为Good Coder的提交审核材料 二.排期 周 ...

  3. iOS开发遇到的坑之一: 开发遇见如下错误:Undefined symbols for architecture arm64

    博客处女作,写得不好望谅解! “for architecture arm64”就是说没有支持arm64,在Build settings里architecture相关的几项需要配置正确 在最近升级coc ...

  4. windows10锁定屏幕聚焦图片导出

    打开运行,输入%LocalAppData%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Ass ...

  5. 【计算机网络】Session机制

    1. Http请求中Session机制 先简单说一下HTTP请求中的Session机制:Session数据保存在服务器端,SessionID保存在客户端的Cookies中(关闭浏览器时过期).当客户端 ...

  6. 下载PhantomJS

    PhantomJS新手?阅读并学习快速入门指南. 视窗 下载phantomjs-2.1.1-windows.zip(17.4 MB)并解压缩(解压缩)内容. 可执行文件phantomjs.exe已准备 ...

  7. springboot的启动类不能直接放在src/java目录下,不然会报错

    jar包的application.yml 会被项目的覆盖,导致找不到原有的配置

  8. fsm三种建模思路比较

    ==================================================================================================== ...

  9. NSArray 排序

    先研究一种方法 NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:]; ; i < ; i++) { ; [arr ...

  10. gnu printf可变参数宏

    可变参数的宏 标准C只支持可变参数的函数,意味着函数的参数可以是不固定的 例如printf()函数的原型是int printf(const char *format [,argument]...) 而 ...