流畅的Python

第一章 Python数据模型
魔术方法(magic method)或者说双下方法(dunder method)表示特殊方法。以双下划线开始和结束,比如getitem
len()需要实现len()
[]和切片需要实现getitem()
可迭代或者反向迭代,至少需要实现getitem()
in需要实现contains(),如果没有实现,则至少需要实现getitem(),因为它可以自己做迭代搜索
repr,它能把一个对象有字符串的形式表达出来,repr就是通过repr这个特殊方法来得到一个字符串的表达形式的。如果没有实现repr,输出实例时,得到的字符串就是<Vector object at 0x10e100070>之类的
注意reprstr的区别,后者是在str()函数中使用,或者是在用print函数打印的时候才被调用。
如果一个对象没有str函数,而Python又需要调用它的时候,解释器会用repr作为替代。

在if,while或者and or not运算符中,为了判定一个值x是真还是假,Python会调用bool(x),这个函数只能返回True或者False。
bool(x),其实调用的是x.bool()的结果,如果不存在bool,bool(x)会尝试调用x.len().若返回0,则bool会返回False,否则True。

第二章 序列构成的数组
序列类型概览
1、容器序列
list、tuple、collections.deque这些序列都能存放不同类型的数据

2、扁平序列
str、bytes、bytearray、memoryview和array.array,这些序列只能容纳一种类型。

注意:容器序列存放的是它们所包含任意类型的对象的引用,二扁平序列里存放的是值而不是引用。换句话说,扁平序列其实是一系列连续的内存空间,但是扁平序列只能存放字符、字节和数值这种基础类型。

可变序列
list、bytearray、array.array、collections.deque和memoryview

不可变序列
tuple、str和bytes

列表推倒
symbols = 'abc'
codes = []
for symbol in symbols:
codes.append(symbol)

codes = [symbol for symbol in symbols]
第一种就是正常的for循环,第二种就是列表推导

生成器表达式
虽然可以用列表推导来初始化元组、数组或者其他序列类型,但是生成器表达式更好。因为生成器表达式背后遵循了迭代器协议,可以逐个产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里面。
和列表推导差不多,就是方括号改成圆括号

symbols = 'abc'

array.array('i', (symbol for symbol in symbols))

元组的应用:
1、当作记录,因为它是不可更改的
2、元组拆包,可以得到里面的数据 类似于 a, b = (first, second)
3、具名元组,从collections.namedtuple生成具名元组,除了继承普通元组的属性,具名元组还有一些自己专有的属性。_fields类属性,类方法_make(iterable)和实例方法_asdict()。
_fields类属性:包含具名元组的各个字段名称
_make(iterable):通过_make()接受一个可迭代对象来生成这个类的一个实例
_asdict():把具名元组以collections.ordereddict的形式返回。

from collections import namedtuple
City = namedtuple('City', 'name country population coordinates')
tokyo = ('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
City._fields
('name', 'country', 'population', 'coordinates')
delhi_data = ('Delhi NCR', 'IN', 21.935, (28.613889,  77.208889))
delhi = City._make(delhi_data)  ###它的作用和City(*delhi_data)是一样的

delhi._asdict()
OrderedDict([('name', 'Delhi NCR'), ('country', 'IN'), ('population',  21.935), ('coordinates', (28.613889,  77.208889))])

切片:
s[a:b:c] s在a到b之间以c为间隔取值,c还可以是负,负值意味着取反。如s[::-1]意味着,将这个list倒置
给切片赋值:
l=list(range(5))
print(l) [0,1,2,3,4]
l[1:3]=[20,30]

print(l) [0,20,30,4]
l[1:3]=100 报错,需要写成[100]

对序列使用+和*
+是把两个序列合并,在拼接过程中,两个被操作对序列都不会被修改,Python会新建一个包含同类型数据对序列作为拼接结果。
是把序列复制几份然后拼接起来。例如 l=[1,2] l3=[1,2,1,2,1,2] *也会构建新的序列而不修改原有的对象。

序列的增量赋值
+=背后的特殊方法是iadd,但是如果一个类没有实现这个方法,Python会退一步调用add

第三章 字典和集合
字典推导
country_code = {country: code for code, country in dial_doces} dial_doces是一个元组的list
{code:country.upper() for country, code in country_code.items() if code<66}
第一个是把国家作为键,第二个把code作为键

if key not in my_dict:
my_dict[key]=[]
my_dict[key].append(new_value)
可以直接写成my_dict.setdefault(key,[]).append(new_value)

所有映射类型在处理找不到的键的时候,都会牵扯到missing方法,
集合
{1,2}这是集合
集合推导
from unicodedata import name
{chr(i) for i in range(32,256) if 'SIGN' in name(chr(i),'')}
a.union(b,c,d) 这里a必须是set,b、c和d则可以是任何类型的可迭代对象

为了获取dict[key]背后的值,python会调用hash(key)来计算key的散列值,然后去散列表里面查找表元,若找到的表元是空的,则抛keyerror,若不是空的,则表元里会有一对found_key:found_value,这个时候Python会检验key == found_key是否为真,如果他们相等的话,会返回found_value。如果不等,说明出现了散列冲突。发生这种情况的原因是,散列表所做的只是把随机的元素映射到只有几位的数字上,而散列表本身的索引又只依赖于这个数字的一部分。为了解决散列冲突,算法会在散列值中另外取几位,然后用特殊方法处理一下,把新得到的数字再当作索引来寻找表元。

dict的实现
1、支持hash()函数,并且通过hash()方法所得到的的散列值是不变的。
2、通过eq()来检测相等性
3、若a == b,则 hash(a) == hash(b)

往字典添加新键可能会改变已有键的顺序
无论何时往字典里添加新键,python解释器都可能作出字典扩容的决定。扩容导致的结果就是需要新建一个更大的散列表,并把字典里已有的元素添加到新表。这个过程可能会发生散列冲突,导致新散列表次序发生变化。
由此可知,不要对字典同时进行迭代和修改。如果你想扫描并修改一个字典,最好分成两步来解决,首先对字典迭代,以得出需要添加对内容,把这些内容放到一个新字典里,迭代结束之后再对原字典进行更新。

字符问题
字节序列-解码-unicode
字符串-解码-unicode
b = str.encode('utf8') 字符串转化成字节码 是编码
b.decode('utf8') 把字节码还原成字符串 是解码

一等函数
一等函数满足以下条件:
1、在运行时创建
2、能赋值给变量或数据结构中的元素
3、能作为参数传给函数
4、能作为函数的返回结果

高阶函数
接受函数为参数,或者把函数作为结果返回的函数时高阶函数。

匿名函数
通过对比可以看出,匿名函数lambda x: x * x实际上就是:
def f(x):
return x * x
关键字lambda表示匿名函数,冒号前面的x表示函数参数。

可调用类型
任何python对象都可以表现的像函数。只需要实现实例方法call
实现call方法的类是创建函数类对象的简便方式

函数内省
可以用dir(len)查看所有的函数属性
sorted(set(dir(func))-set(dir(obj))) 计算差集 然后排序 得到类的实例没有 而函数有的属性列表

对象引用、可变性和垃圾回收

==运算符比较两个对象的值(对象中保存的数据),而is是比较对象的标识。
通常,我们关注的是值,而不是标识,因此python中==出现的频率比is高。
a==b是语法糖,等同于a.eq(b) 装饰器也是语法糖

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容