流畅的python记录

流畅的python记录

记录一下书中自己容易混淆和错误的知识点~~~

一: 序列类型

python的序列类型,如果从能否被修改来分类,可以分为以下两类:

可变序列list,bytearray,array.array,collections.deque,memoryview
不可变序列tuplestrbytes

其中,加了下划线的序列类型可以存放不同类型的数据。剩下的都为扁平序列,只能容纳一种类型。从我们最常用的tuple和list出发,接下来介绍一下他们特有的知识点:

1. 常用序列

tuple元组:
  • 元组拆包:用*处理多余的元素,把一个可迭代对象拆开作为函数的参数。

    a,b,*rest=range(5)
    a,b,rest
    
    a,*body,c,d=range(5)
    a,body,c,d
    

分别输出:(0, 1, [2, 3, 4])和(0, [1, 2], 3, 4)

*前缀只能用在一个变量名前面,但这个变量可以出现在赋值表达式的任意位置。

  • 具名元组:collections.namedtuple,可以用来构建一个带字段名的元组和一个有名字的类

    构建一个具名元组需要两个 参数,1.类名 2.类的各个字段的名字。其中,后者有两种定义方式:

    from collections import namedtuple
    city1=namedtuple("city1","name country population")
    city2=namedtuple("city2",["name","country","population"])
    city1._fields
    city2._fields
    

    city1和city2的字段名相同。

list列表:
  • list.sort()和sorted

    两者我想从以下列表介绍一下:

    相同点都有两个可选的关键字参数reverse和key
    不同点list.sort()就地排序,改变原列表
    sorted创建一个新列表作为返回值

    两者的不同点相信通过以下的代码就可以区分清楚:

    fruits=["grape","raspberry","apple","banana"]
    print(sorted(fruits))
    print(fruits)
    fruits.sort()
    print(fruits)
    

    三个输出将分别为:

    ['apple', 'banana', 'grape', 'raspberry']
    ['grape', 'raspberry', 'apple', 'banana']
    ['apple', 'banana', 'grape', 'raspberry']
    
  • list推导:如何只用列表推导来创建新的列表,尽量保持简短

    list作为可变序列,最大的陷阱就是引用可变对象背后的陷阱,看下面这个例子:

    board=[["-"]*3 for i in range(3)]
    board[1][2]="X"
    board
    
    [['-', '-', '-'], ['-', '-', 'X'], ['-', '-', '-']]
    

这个结果似乎很好理解,但我们换一个写法可能会得到不同的结果:

board=[["-"]*3]*3
board[1][2]="X"
board
[['-', '-', 'X'], ['-', '-', 'X'], ['-', '-', 'X']]

为什么结果会完全不同呢?因为这个列表的3个引用都指向同一个对象,每次循环都追加同一个对象到board中。而上一个例子,是在每次循环中创新一个新对象追加到board中。


最后,对于list和tuple,我还想从下面这个表对比一下两者可操作的区别:

操作列表元组
+✔︎✔︎
+=✔︎
append✔︎
index索引✔︎✔︎

2. 序列共有操作

切片操作

切片操作应该是序列操作中最常用的之一,这里只讲述三个特殊的点。

  • 为什么切片和区间操作总是忽略最后一个元素?

    1.可以快速看出切片和区间里有几个元素

    2.起止位置可见时,可以快速计算出切片和区间的长度

    3.可以把序列分割成不重复的两部分

  • 间隔取值

    s[a: b :c]表示s在a和b之间以c为间隔取值,c为负代表反向取值。因此s[::-1]可以表示翻转。

  • 切片赋值

    把切片放在赋值语句的左边,或作为del操作的对象,就可以对序列进行嫁接,切除或修改。

3. 其他序列

有序序列管理:

bisect模块有两个主要函数,bisect和insort,都使用二分查找对有序序列进行查找或者插入元素的操作。

import bisect
s=[1,2,3,4,6,7]
bisect.bisect(s,5)

输出为4,代表把5这个值插入到“4”这个位置之后,序列还能保持有序。

bisect.insort(s,5)
s

输出[1, 2, 3, 4, 5, 6, 7],即插入值后的序列。

array.array:

与list的区别是,在处理只有数字的列表时,array.array将更加高效。

双向队列collections.deque

双向队列可以快速从两端添加和删除元素。创建时,可以 指定队列大小。

二:字典等操作

1. dict.setdefault处理找不到的键

通常使用d[k]不能找到正确的键时,python会抛出异常。一个方法是如下设置默认值:

d={1:"apple",2:"banana",3:"watermelon"}
d.get(4,"None")

返回设置好的默认值“None”。但这样处理并不自然,且效率低,如果寻找字典中键值为空且进行赋值更新,dict.setdefault更简洁。

d.setdefault(key,[]).append(new_value)就等于以下的操作:

if 4 not in d:
    d[4]=[]
d[4].append("grape")
d
{1: 'apple', 2: 'banana', 3: 'watermelon', 4: ['grape']}

2.collections模块中的字典变种

映射类型功能
collections.defaultdict处理找不到键的一个选择,具体见下面代码块
collections.OrderDict有序的添加键,键的迭代次数一致,因为字典默认是无序的。
collections.Counter给键准备一个整数计数器。
ct=collections.Counter(“abracadabra”)
输出:Counter({“a”:5, “b”:2, “r”:2, “c”:1, ‘d’:1})
import collections
index=collections.defaultdict(list)
index["apple"].append("1")
index
defaultdict(list, {'apple': ['1']})

或者:

import collections
index=collections.defaultdict(tuple)
index["apple"]=(1,2,3)
index
defaultdict(tuple, {'apple': (1, 2, 3)})

三:python函数

1. 函数参数

调用函数时可以使用*和**(传入字典)展开可迭代对象,见下例

def tag(name,*content,cls=None,**attrs):
    if cls is not None:
        print("cls value is:",cls)
        attrs["class"]=cls
    if attrs:
        print("attrs is:",attrs)
    else:
        print("attr is empty")
    if content:
        print("content is:",content)
        
print("-"*50)
tag("p","hello")
print("-"*50)
tag("p","hello",id=33)
print("-"*50)
tag("p","hello","world",cls="sidebar")
print("-"*50)
tag(content="testing",name="img")
my_tag={"name":"img","title":"sunset","cls":"framed"}
print("-"*50)
tag(**my_tag)
--------------------------------------------------
attr is empty
content is: ('hello',)
--------------------------------------------------
attrs is: {'id': 33}
content is: ('hello',)
--------------------------------------------------
cls value is: sidebar
attrs is: {'class': 'sidebar'}
content is: ('hello', 'world')
--------------------------------------------------
attrs is: {'content': 'testing'}
--------------------------------------------------
cls value is: framed
attrs is: {'title': 'sunset', 'class': 'framed'}

考虑上面五种代入参数的形式,尤其关注最后一种,当传入整个字典的时候,同名键名会自动绑定到对应的具名参数上,剩下的被**atts捕捉。

2. 函数注解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值