python 序列和字典相关知识点整理

python 序列和字典

序列:字符串,元组,列表 这三种类型的统称
他们有一些共同特点,所以我们将其称之为 序列

字典:这是一个键值对结构,他和序列不太一样
但是他也是很常用的东西


序列:

概念:
包含若干个元素, 元素有序排列, 可以通过下标访问到一个或者多个元素.
这样的对象, Python中统一称为序列(Sequence)

序列里面的元素的顺序是很重要的
a = [1,2,3]
b = [3,2,1]
print(a == b)
False

Python中的以下对象都属于序列:字符串 列表 元组
同是序列, 他们的使用方式有很多相通之处


标准类型操作符

下列标准类型操作符, 大多数情况下都是适用于序列对象的
(少部分特例是, 序列中保存的元素不支持标准类型操作符)

操作符 功能
如果是字符串,我们用字典序进行比较
如果是链表?按照元素顺序,依次进行比较
链表进行比较一般情况是没有意义的,有可能会出错
我们知道链表里面的元素类型没有限制,可以存储不同类型
如果 1 和 “hehe” 进行比较?这就很难说明这个谁大谁小

举例:
a = [1,2,3]
b = ['hehe',6,7]
print(a<b)
TypeError: '<' not supported between instances of 'int' and 'str'
不能把整形和字符串类型进行比较
即:不是所有的列表都能进行比较,还是要看里面的类型

expr1 < expr2        expr1 小于 expr2 
expr1 > expr2        expr1 大于 expr2 
expr1 <= expr2      expr1 小于等于 expr2 

比较里面的元素是否一样,并且顺序是否一样
expr1 >= expr2      expr1 等于 expr2 
expr1 != expr2       expr1 不等于 expr2 

序列类型操作符

in/not in: 判定一个元素是否存在于序列中, 返回布尔值
a = [1, 2, 3, 4]
print(1 in a )

连接操作符(+): 把两个相同类型的序列进行连接.
连接操作符往往并不高效(新创建对象, 把原有对象拷贝进去).
对于列表, 推荐使用extend来完成这样的操作;
对于字符串, 推荐使用join这样的方法
a = [1, 2, 3, 4]
b = [5, 6]
print(a + b) # 返回一个新的列表, 包含了a和b中的所有元素

对于a和b其本身没有发生任何变化
a+b 是新创建的一个变量

重复操作符(*): 让一个序列重复N次
序列和元组都可以进行 *

a = [1, 2, 3, 4]
print(a * 2)
执行结果
[1, 2, 3, 4, 1, 2, 3, 4]

序列的切片操作

切片操作符([], [:], [::]): 通过下标访问其中的某一个元素, 或者某个子序列

a = (1,2,3)
print(a[100])
IndexError: tuple index out of range
索引下标越界 

扩展切片操作[::] 除了可以表示子序列的起始和结束位置, 还可以表示 “步长”

a = [1, 2, 3, 4, 5]
print(a[::2]) # 每隔一个元素取一个子元素.
执行结果
[1, 3, 5]
[开始:结束:中间间隔]

延伸:字符串反转问题

方法一:
char str[] = "abcdefg";
char* beg = str;
char* end = str + strlen(str);
while (beg < end) {
    swap(*beg++, *--end);
}

方法二:
char str[] = "abcdefg";
Stack stack;
char* p = str;
while(p) {
    stack.push(*p++);
}
int index = 0;
while(!stack.empty()){
    str[index++] = stack.top();
    stack.pop();
}

方法三:C++
include <algorithm>
char str[] = "abcdefg";
std::reverse(str, str + strlen(str));

python方法:
a = "abcdefg"
print(a[::-1])
gfedcba

另外, 对于切片语法来说, 下标越界也没关系. 因为取的是前闭后开区间.
区间里的元素, 能取到多少就取到多少


序列内建函数

len: 返回序列的长度
a = [1, 2, 3, 4]
print(len(a))
# 执行结果
4

max: 返回序列中的最大值
min: 返回序列中的最小值
sorted: 排序. 这是一个非常有用的函数. 返回一个有序的序列(输入参数的副本)
sum: 序列中的元素求和(要求序列中的元素都是数字)

enumerate: 同时枚举出序列的下标和值.
这个是一个非常有用的函数, 可以避免很多丑陋的代码.
找出元素在列表中的下标

def Find(input_list, x):
    for i in range(0, len(input_list)):
        if input_list[i] == x:
            return i
    else:
        return None
使用enumerate
def Find(input_list, x):
    for i, item in enumerate(input_list):
        if item == x:
            return i
    else:
        return None
zip: 这个函数的本意是 "拉链", 我们先看代码
x = [1, 2, 3]
y = [4, 5, 6]
z = [7, 8, 9, 10]
print(zip(x, y, z))
# 执行结果
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

zip其实可以理解成矩阵的 行列互换

zip的一个比较常见的用法, 就是构造字典
key = ('name', 'id', 'score')
value = ('tangzhong', 1234, 60)
d = dict(zip(key, value))
print(d)
# 执行结果
{'score': 60, 'name': 'tangzhong', 'id': 1234}

字符串

三种引号的区别
1.Python中单引号(’)字符串和双引号(")字符串是等价的.
而不像有些编程语言(比如Linux Shell), 转义字符只在双引号中有效.
2.Python中使用 “原始字符串” 来完成这样的功能(我们稍后再说)
3.三引号(’’’/""")相比于前两种的区别是, 可以跨多行

理解字符串“不可变”
字符串实际上是不可变的对象.
你不能修改这个字符串, 只能创建一个新的字符串

a = 'aaaa'
a[0] = 'b'
print(a)
# 执行结果
TypeError: 'str' object does not support item assignment
str这个元素对象不支持给元素赋值
你不能直接修改元素里面的内容

要打到同样的效果, 我们可以这么做
a = 'b' + a[1:] # 重新生成一个对象. 并使用a这个引用绑定到这个对象.
print(a)
# 执行结果
baaa

字符串的标准类型操作符
==, !=, <, <=, >, >= 这些操作符的行为前面已经提到过. 不赘述了.
需要记得字符串比较大小是按照字典序.
in/not in的规则和序列的规则一致.
切片操作和序列规则一致

只适用于字符串的操作符
python的底层也是c语言,所以有一些风格也是一样的

%: 格式化替换
x = 1
print("x = %d" % x)
# 执行结果
x = 1

x = 10
y = 20
a = 'x = %d, y = %d'%(x,y)
print(a)
x = 10, y = 20

推荐:相当于嵌入了一段python的代码
x = 10
y = 20
a = f'x = {x},y = {y}'
print(a)
x = 10,y = 20

原始字符串(raw strings)

有的时候, 我们需要有 \n 这样的字符作为转义字符.
但是有些时候我们又不希望进行转义, 只需要原始的\n 作为字符串的一部分

a = r'hello \n world'
print(a)
hello \n world
正则表达式:特殊字符串里面有许多奇奇怪怪的符号,

repr函数和反引号操作符

我们前面讲了, 用str函数可以将一些对象转换成字符串. repr也有类似的效果

举例:
a = 1
print(repr(a))
a = 1.0
print(repr(a))
a = [1, 2, 3, 4]
print(repr(a))

看起来好像和str没啥区别, 我们再看两个例子
print(str(1.0/7.0))
print(repr(1.0/7.0))
# 执行结果
0.142857142857
0.14285714285714285

不仅仅是精确度的问题, 再看这个
print(str('hello'))
print(repr('hello'))
# 执行结果
hello
'hello'

总结一下, str转换出的字符串是给人看的. 而repr转换出的字符串, 是给Python解释器看的. 意思是说, repr得出的结
果, 其实是一个Python语句, 可以直接放到解释器里执行~
反引号, 和repr函数等价


string 模块常用函数

将序列中的字符串合并成一个字符串
a = ['aa', 'bb', 'cc', 'dd']
print(' '.join(a))
# 执行结果
'aa bb cc dd'

按空格将字符串分割成列表
a = 'aa bb cc dd'
print(a.split(' '))
# 执行结果
['aa', 'bb', 'cc', 'dd']

判定字符串开头结尾
a = 'hello world'
print(a.startswith('hello'))
print(a.endwith('world'))
# 执行结果
True
True

去除字符串开头结尾的空格/制表符
a = '          hello world            '
print(a.strip())
# 执行结果
hello world
延伸:只去除字符串左边或者右边的空格
a = '          hello world            '
print(a.rstrip())
print(a.lstrip())

左对齐/右对齐/中间对齐
(这里的数字代表这个输出一共是30个字符)
a = 'hello world'
print('[' + a.ljust(30) + ']')
print('[' + a.rjust(30) + ']')
print('[' + a.center(30) + ']')
# 执行结果:
[hello world           ]
[           hello world]
[      hello world     ]

查找子串
a = 'hello world'
print(a.find('world'))
# 执行结果
6

替换子串(记得字符串是不可变对象, 只能生成新字符串)
a = 'hello world'
print(a.replace('world', 'python'))
# 执行结果
hello python

判定字符串是字母/数字
a = 'hello'
print(a.isalpha())
a = '1234'
print(a.isdigit())
# 执行结果
True
True

转换大小写
a = 'Hello World'
print(a.lower())
print(a.upper())
# 执行结果
hello world
HELLO WORLD

关于结束符

学过C语言的同学, 可能会问, Python的字符串是否需要 ‘\0’ 之类的结束符来做结尾?

Python中并没有那个讨厌的 ‘\0’. 准确的说, 对于C语言来说, 语言本身的缺陷并不支持 “字符串类型”,
才被迫使用字符数组来凑合. 但是Python完全没有这个包袱


列表:

字符串只能由字符组成, 而且不可变; 但是列表中可以包含任意类型的对象, 使用更加灵活

使用切片操作符访问列表元素:
列表的切片操作和字符串完全一致.
但是列表还可以使用切片操作修改元素.

a = [1, 2, 3, 4]
a[0] = 100
print(a)
# 执行结果
[100, 2, 3, 4]

列表常用操作:

append: 追加元素
a = [1, 2]
a.append(3)
print(a)
# 执行结果
[1, 2, 3]

删除指定下标元素
a = [0, 1, 2]
del (a[0])
print(a)
# 执行结果
[1, 2]

按值删除元素
a = [1, 2, 3]
a.remove(1)
print(a)
# 执行结果
[2, 3]
等价于a.pop(0)

列表比较操作: ==/!= 为判定所有元素都相等, 则认为列表相等; 
< <= > >= 则是两个列表从第一个元素开始依次比较, 直到某一方胜出
a = ['abc', 123]
b = ['xyz', 789]
c = ['abc', 123]
print(a < b)
print(b < c)
print(b > c and a == c)
# 执行结果
True
False
True

in/not in: 和序列操作完全一致
连接操作符(+): 和序列操作完全一致
extend: 列表连接. 可以理解成 += (列表不支持 += 运算符)

a = [1, 2]
a.extend([3, 4])
print(a)
# 执行结果
[1, 2, 3, 4]

重复操作符(*): 和序列操作完全一致

列表的深拷贝/浅拷贝

a = [10,20,30,40]
b = a
a[0] = 100
print(b)
如果是深拷贝,我修改了a,b不会影响
如果是浅拷贝,我修改了a,b会受影响
[100, 20, 30, 40]--》浅拷贝

如果有时候,我不想用浅拷贝,如何用深拷贝
import copy
a = [10,20,30,40]
b = copy.deepcopy(a)
a[0] = 100
print(b)
[10, 20, 30, 40]

延伸:深拷贝只能针对可变对象使用

元组tuple

元组常用操作
切片操作: 和列表相同
比较运算符, 规则和列表相同.
连接操作(+), 重复操作(*), 判定元素存在(in/not in)都和列表相同.
由于元组不可变, 所以并不支持append, extend, sort等修改自身的操作

元组用的(),有的时候会产生一些歧义

a = (10)
print(type(a))
<class 'int'>

为什么?
a = (10 + 2) * 5
此时的a即使带了(),那也是整数

如果一个元组确实只有一个元素?
a = (10 + 20,)*3
print(a)
print(type(a))
(30, 30, 30)
<class 'tuple'>

元组的两个重要应用场景

1.函数传参的时候使用元组可以避免函数内部把函数外部的内容修改掉
a = [1,2,3]
def func(input_list):
    input_list[0] = 100

func(a)
print(a)

2.元组是可 hash 的,元组就可以作为字典的key,而列表不行
a = (1,2,3)
b = {
    a:100
}
print(b)
{(1, 2, 3): 100}

理解元组的  不可变
1.元组的 "不可变" 指的是元组的每个元素的id不可变. 就是说一个元组包含了几个对象, 然后不可以给这个元
组再添加或者删除其中的某个对象, 也不可以将某个对象改成其他的对象.
2.如果元组中的某个元素, 是可变对象(比如列表或字典), 那么仍然是可以修改的

a = ([1, 2, 3], [4, 5, 6])
a[0][0] = 100 # 这个东西是不是看起来长的很像C语言的 "二维数组" ?
print(a)
# 执行结果
([100, 2, 3], [4, 5, 6])

字典

Python的字典是一种映射类型数据. 里面的数据是 键值对 .
Python的字典是基于hash表实现的
1.键(key): 字典的键是唯一的(一个字典对象中不能有两个相同的键).
同时字典的键必须是可hash的(能够计算出一个固定的hash值)
2.值(value): 字典的值没啥限制. 数字, 字符串, 以及其他容器, 都可以作为字典的值.

创建字典
使用 { } 的方法, 我们前面已经介绍过了
使用工厂方法 dict

a = dict((['x', 1], ['y', 2]))
使用字典的内建方法 fromkeys
a = {}.fromkeys(('x', 'y'), 0)
print a
# 执行结果
{'x':0, 'y':0}
字典的键和值的类型, 不需要相同

字典的 key 必须是可 hash ,
不可变是可 hash 的必要条件

如何知道一个东西是否可 hash

print(hash(()))
如果括号内的可以哈希,那么他就会打印出一个哈希值
如果不可哈希,那么就会异常

最中间的空的括号,表示一个元组----》运行5740354900026072187
这个哈希值如何得到,我们不需要进行深究

md5/sha1 字符串 hash算法

访问字典中的元素

使用 [] 可以获取到元素的值.
a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
print(a['ip'])
for循环遍历字典中的元素
a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
for key in a:
    print(key,a[key])
ip 127.0.0.1
port 80

修改字典元素

使用 [] 可以新增/修改字典元素.
如果key不存在, 就会新增; 如果已经存在, 就会修改

a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
a['ip'] = '192.168.1.1'
print(a)
{'ip': '192.168.1.1', 'port': 80}
修改只能修改这个值,不能修改key
对于key只能删除,再加新的
a['name'] = 'zhangsan'
print(a)
{'ip': '192.168.1.1', 'port': 80, 'name': 'zhangsan'}

如果直接打印一个不存在的键值对
KeyError : ‘不存在的key’
所以以后要访问key时,要先确认这个key是否存在

删除字典元素

使用del来删除某一个键值对
a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
del(a['ip'])
print(a)
{'port': 80}

查找元素是否是字典的key
使用in/not in来判定一个key是否在字典中

常用内置函数
len: 字典中键值对的数目
hash: 判定一个对象是否可hash. 如果可hash, 则返回hash之后的hashcode.
否则会运行出错

print(hash(()))
print(hash([]))
执行结果
3527539
Traceback (most recent call last):
File "test.py", line 4, in <module>
print(hash([]))
TypeError: unhashable type: 'list'
keys: 返回一个列表, 包含字典的所有的key
a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
print(a.keys())
dict_keys(['ip', 'port'])
(['ip', 'port']) 这个的类型是 dict_keys 
使用和列表很像 ,但他还具有一些列表不具有的操作
values: 返回一个列表, 包含字典的所有value
a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
print(a.values())
dict_values(['127.0.0.1', 80])
items: 返回一个列表, 每一个元素都是一个元组, 包含了key和value
a = {
    'ip' : '127.0.0.1',
    'port' : 80
}
print(a.items())
dict_items([('ip', '127.0.0.1'), ('port', 80)])

集合(set)

集合是基于字典实现的一个数据结构.
集合数据结构实现了很多数学中的交集, 并集, 差集等方法,
可以很方便的进行这些操作.
集合的使用方法很简单, 同学们课后自学.
注意!! 熟练掌握集合操作, 对我们后续解笔试题面试题, 都会有很大帮助

a = set([1,2,3])
b = set([3,2,1])
print(a == b)
True
print(a,b)
{1, 2, 3} {1, 2, 3}
数据去重
a = [1, 1, 2, 2, 3, 3]
b = set(a)
print(b)
{1, 2, 3}

集合是基于hash来实现的
1.能够帮助我们进行一些判断存在,查找这样的工作
2.完成集合基本操作 : 交集 并集 差集

a = set([1,2,3,4])
b = set([3,4,5])
print(a & b) #求交集
{3, 4}
print(a | b) # 求并集
{1, 2, 3, 4, 5}
print(a - b)
{1, 2}
print(a ^ b) #对称差集  
这两个集合相互之间做差集,然后放在一起
{1, 2, 5}

集合的底层是基于字典进行实现的
字典中有:{}.keys() 会返回一个dict_items 类型的数据
这个类型的数据可以进行 集合 操作
列表没有这种功能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值