元组:
用于存储数据,行为不能被存储在元组中。
是不可变的,即不能对其添加、删除或替换对象。
主要好处就是它的不可变性,可以把它作为字典的键,或者用在一个对象需要散列值的地方。
以下两种写法都可以创建元组,推荐加括号。当把元组集成到其他对象中,如函数调用、列表解析、生成器,括号是必须的,否则解释器不能识别这是一个元组还是另一个参数。
t1 = "A", 1, 2, 3
t2 = ("B", 4, 5, 6)
元组拆分:在拆分时,元组必须拆分为与其长度相等的变量,否则解释器回抛出异常。
symbol, num1, num2, num3 = t1
还可以用分片符提取元组中的数据:
t1[1, 3] #得(1, 2)
元组的主要缺点就是数据的可读性差,当我们没有给数据分配名字时,即没有像symbol, num1, num2, num3 = t1这种代码时,我们不会知道t1元组里的第一个值代表symbol,第二个值代表num1…我们访问元组时也只能是类似t1[1]这样,不能知道数据的具体指代。
->解决方案:命名元组
命名元组:
from collections import namedtuple
T = namedtuple("T", "symbol num1 num2 num3")
#step1:使用collections.namedtuple来创建一个类
t3 = T("C", 7, 8, 9)
#step2:创建该类的实例
- 命名元组像普通元组那样可以打包或拆分,还可以像访问类属性一样访问其中某个属性,如图:
如果我们需要改变存储的数据,那么就需要用到字典了。
字典:
被存储的对象称为值,被用作索引的对象成为键。
键可以是字符串、整数、浮点数甚至元组,但不能是列表和字典(原因见注2)。值则没有限制,可以是列表和字典。
可以用dict()构造函数或{}快捷语法来构造字典,在实践中一般用{}。例如,在股票应用中,我们需要通过股票代码查找股价,可以创建一个一股票代码为键,包含现价、最高价、最低价的元组为值的字典:
stocks = {"GOOG": (613.30, 625.86, 610.50),
"MSFT": (30.25, 30.70, 30.19)}
常用方法:
get方法:接收一个键作为第一个参数,第二个参数可选,当键不存在时输出第二个参数中的语句(如没有第二个参数则需要用print,输出结果为None),存在时输出对应的值。
setdefault方法:如果该键在字典中,行为同get方法,如果键不在字典中,它不仅会返回我们在调用方法时给出的默认值(同get),还会将该键设置为相同的值。
keys(),values():返回一个包含所有键或所有值的迭代器,可以像列表一样使用它们,或是通过for循环来遍历它们。
items()方法:返回一个对字典中每个项目形成一个如(键,值)对这样的元组的迭代器。这个迭代器结合元组拆分,可以在for循环中使遍历键和值事半功倍。
注1:字典打印时并不会按照数据插入字典的顺序打印出来。为了使键查找足够快,字典使用了哈希算法,因此字典在内部是无序的。
注2:列表可能在任何时候发生变化(如添加或删除列表中元素),所以列表不能被哈希称一个特定的值,所以列表不能用作键。出于同样原因,字典也不能用作另一字典的键。
defaultdict:
defaultdict类在它的构造函数中可以接收一个函数作为参数,当访问字典中一个不存在的键时,它就会以不含参数的形式调用该函数,创建一个默认值。
一个例子:统计一个字母在给定句子中出现的次数。
#使用setdefault
def letter_frequency(sentence):
frequencies = {}
for letter in sentence:
frequency = frequencies.setdefault(letter, 0)
frequencies[letter] = frequency + 1
return frequencies
#使用defaultdict
from collections import defaultdict
def letter_frequency(sentence):
frequencies = defaultdict(int)
for letter in sentence:
frequencies[letter] += 1
return frequencies
在这个例子中,所调用的函数是int,也就是一个整数对象的构造函数。通常情况下,在代码中创建一个整数只需要键入一个整数数字。而如果使用int构造函数来创建一个整数,我们可以将想要创建的项目传给它(如将一连串的数字字符转换成一个整数)。但如果我们调用int时不带任何参数,它就会简单地返回0。
在这段代码中,如果字母在defaultdict中不存在,则在我们访问它时会返回0,之后我们为这个数字加1来表示我们发现了该字母的一个实例,当我们下次再找到一个时,就再增加其值。
- 又一个例子:创建一个defaultdict,其中每个元素都包含一个元组,记录当时插入字典中的项目数量和一个用来存储其他数据的空列表。
from collections import defaultdict
num_items = 0
def tuple_counter():
global num_items
num_items += 1
return (num_items, [])
当我们运行这段代码时,可以再同一行代码中同时做到访问空键并插入列表两个动作:
注:这个例子虽然简洁地展示了如何用自己的函数创建defaultdict,但实际上这并不是很好的代码。全局变量的使用意味着如果我们创建了4个不同点defaultdict代码段,每个都使用一个tuple_counter,那么它将计算再所有字典中全部条目的数量,而不是为每一个字典记录不同的数。最好的办法是创建一个类,并将这个类中的一个方法传给defaultdict。
参考资料:《Python 3 面向对象编程》 Dusty Phillips著