利用Python进行数据分析学习笔记二:Python的数据结构、函数和文件

本文详细介绍了Python的基础知识,包括内置功能、数据结构(元组、列表、字典、集合)、函数等核心概念。并通过实例展示了如何利用这些数据结构进行高效的数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本章讨论Python的内置功能,这些功能本书会⽤到很多。虽然扩展库,⽐如pandas和Numpy,使处理⼤数据集很⽅便,但它们是和Python的内置数据处理⼯具⼀同使⽤的。我们会从Python最基础的数据结构开始:元组、列表、字典和集合。然后会讨论创建你⾃⼰的、可重复使⽤的Python函数。最后,会学习Python的⽂件对象,以及如何与本地硬盘交互。

一、数据结构和序列

1、元组()

在这里插入图片描述
在这里插入图片描述
(元组本身是不可变的,但当元组存储的对象是可变对象,那就可以对其中的可变对象进行修改)
在这里插入图片描述

2、拆分元组

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、tuple方法

在这里插入图片描述

4、列表 [ ]

在这里插入图片描述
在这里插入图片描述

5、添加和删除元素

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、串联和组合列表

在这里插入图片描述

7、排序

在这里插入图片描述
在这里插入图片描述

8、二分搜索和维护已排序的列表

在这里插入图片描述
在这里插入图片描述

bisect(c,2),是指在保证排序的情况下,将2插入c的位置(从0开始)
返回4就是说,可以2可以插在第四个位置,不会影响排序。

9、切片

在这里插入图片描述
在这里插入图片描述

10、序列函数

1、enumerate函数
在这里插入图片描述
2、sorted函数
在这里插入图片描述
sorted函数是生成一个副本,而sort是对原对象进行排序。

3、zip函数(主要用在for循环中的in,将多个列表、元组组合成一个方便使用)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3、reversed函数
在这里插入图片描述

11、字典 { }

在这里插入图片描述
在这里插入图片描述

字典由键-值组成,值可以是任意一个对象(元组、列表、数字、字符串),键也可以是(数字、字符)

你可以像访问列表或元组中的元素⼀样,访问、插⼊或设定字典中的元素:

In [104]: d1[7] = 'an integer'
In [105]: d1
Out[105]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
In [106]: d1['b']
Out[106]: [1, 2, 3, 4]

你可以⽤检查列表和元组是否包含某个值得⽅法,检查字典中是否包含某个键:

In [107]: 'b' in d1
Out[107]: True
可以⽤ del 关键字或 pop ⽅法(返回值得同时删除键)删除值:
In [108]: d1[5] = 'some value'
In [109]: d1
Out[109]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an integer',
5: 'some value'}
In [110]: d1['dummy'] = 'another value'
In [111]: d1
Out[111]:
{'a': 'some value',
'b': [1, 2, 3, 4],
 7: 'an integer',
5: 'some value',
'dummy': 'another value'}
In [112]: del d1[5]
In [113]: d1
Out[113]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an integer',
'dummy': 'another value'}
In [114]: ret = d1.pop('dummy')
In [115]: ret
Out[115]: 'another value'
In [116]: d1
Out[116]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}

keys 和 values 是字典的键(keys)和值(values)的迭代器⽅法。虽然键-值对没有顺序,这两个⽅法可以⽤相同的顺序输出键和值:

In [117]: list(d1.keys())
Out[117]: ['a', 'b', 7]
In [118]: list(d1.values())
Out[118]: ['some value', [1, 2, 3, 4], 'an integer']

⽤ update ⽅法可以将⼀个字典与另⼀个融合:

In [119]: d1.update({'b' : 'foo', 'c' : 12})
In [120]: d1
Out[120]: {'a': 'some value', 'b': 'foo', 7: 'an integer', 'c': 12}

update ⽅法是原地改变字典,因此任何传递给 update 的键的旧的值都会被舍弃。

12、用序列创建字典

在这里插入图片描述
因为字典本质上是2元元组的集合,dict可以接受2元元组的列表:

In [121]: mapping = dict(zip(range(5), reversed(range(5))))
In [122]: mapping
Out[122]: {0: 4, 1: 3, 2: 2, 3: 1, 4: 0}

后⾯会谈到 dict comprehensions ,另⼀种构建字典的优雅⽅式。

13、默认值

在这里插入图片描述
get默认会返回None,如果不存在键,pop会抛出⼀个例外。关于设定值,常⻅的情况是在字典的值是属于其它集合,如列表。
例如,你可以通过⾸字⺟,将⼀个列表中的单词分类:

In [123]: words = ['apple', 'bat', 'bar', 'atom', 'book']
In [124]: by_letter = {}
In [125]: for word in words:
.....: letter = word[0]
.....: if letter not in by_letter:
.....: by_letter[letter] = [word]
.....: else:
.....: by_letter[letter].append(word)
.....:
In [126]: by_letter
Out[126]: {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}

setdefault ⽅法就正是⼲这个的。前⾯的for循环可以改写为:

for word in words:
	letter = word[0]
	by_letter.setdefault(letter, []).append(word)

在这里插入图片描述

14、有效的键类型(可哈希性)

字典的值可以是任意Python对象,⽽键通常是不可变的标量类型(整数、浮点型、字符串)或元组(元组中的对象必须是不可变的)。 这被称为 “可哈希性”。
可以⽤ hash 函数检测⼀个对象是否是可哈希的(可被⽤作字典的键):
I

n [127]: hash('string')
Out[127]: 5023931463650008331
In [128]: hash((1, 2, (2, 3)))
Out[128]: 1097636502276347782
In [129]: hash((1, 2, [2, 3])) # fails because lists are mutable
-------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-800cd14ba8be> in <module>()
----> 1 hash((1, 2, [2, 3])) # fails because lists are mutable
TypeError: unhashable type: 'list'

要⽤列表当做键,⼀种⽅法是将列表转化为元组,只要内部元素可以被哈希,它也就可以被哈希:

In [130]: d = {}
In [131]: d[tuple([1, 2, 3])] = 5
In [132]: d
Out[132]: {(1, 2, 3): 5}

15、集合 { }

集合是⽆序的不可重复的元素的集合。你可以把它当做字典,但是只有键没有值。 可以⽤两种⽅式创建集合:通过set函数或使⽤尖括号set语句:
在这里插入图片描述
集合具有数学的性质(唯一性)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

16、列表、集合和字典推导式

在这里插入图片描述
filter条件可以被忽略,只留下表达式就⾏。例如,给定⼀个字符串列表,我们可以过滤出⻓度在2及以下的字符串(就是选择长度>=3的字符串),并将其转换成⼤写:

In [154]: strings = ['a', 'as', 'bat', 'car', 'dove', 'python']
In [155]: [x.upper() for x in strings if len(x) > 2]
Out[155]: ['BAT', 'CAR', 'DOVE', 'PYTHON']

⽤相似的⽅法,还可以推导集合和字典。字典的推导式如下所示:

dict_comp = {key-expr : value-expr for value in collection if condition}

集合的推导式与列表很像,只不过⽤的是尖括号:

set_comp = {expr for value in collection if condition}

与列表推导式类似,集合与字典的推导也很⽅便,⽽且使代码的读写都很容易。来看前⾯的字符串列表。假如我们只想要字符串的⻓度,⽤集合推导式的⽅法⾮常⽅便:

In [156]: unique_lengths = {len(x) for x in strings}
In [157]: unique_lengths
Out[157]: {1, 2, 3, 4, 6}

map 函数可以进⼀步简化:

In [158]: set(map(len, strings))
Out[158]: {1, 2, 3, 4, 6}

作为⼀个字典推导式的例⼦,我们可以创建⼀个字符串的查找映射表以确定它在列表中的位置:

In [159]: loc_mapping = {val : index for index, val in enumerate(strings)}
In [160]: loc_mapping
Out[160]: {'a': 0, 'as': 1, 'bat': 2, 'car': 3, 'dove': 4, 'python': 5}

17、嵌套列表推导式

假设我们有⼀个包含列表的列表,包含了⼀些英⽂名和⻄班⽛名:

In [161]: all_data = [['John', 'Emily', 'Michael', 'Mary', 'Steven'],
.....: ['Maria', 'Juan', 'Javier', 'Natalia', 'Pilar']]

你可能是从⼀些⽂件得到的这些名字,然后想按照语⾔进⾏分类。现在假设我们想⽤⼀个列表包含所有的名字,这些名字中包含两个或更多的e。可以⽤for循环来做:

names_of_interest = []
for names in all_data:
enough_es = [name for name in names if name.count('e') >= 2]
names_of_interest.extend(enough_es)

可以⽤嵌套列表推导式的⽅法,将这些写在⼀起,如下所示:

In [162]: result = [name for names in all_data for name in names
.....: if name.count('e') >= 2]
In [163]: result
Out[163]: ['Steven']

嵌套列表推导式看起来有些复杂。列表推导式的for部分是根据嵌套的顺序,过滤条件还是放在最后。下⾯是另⼀个例⼦,我们将⼀个整数元组的列表扁平化成了⼀个整数列表:

In [164]: some_tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
In [165]: flattened = [x for tup in some_tuples for x in tup]
In [166]: flattened
Out[166]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

记住,for表达式的顺序是与嵌套for循环的顺序⼀样(⽽不是列表推导式的顺序):

flattened = []
for tup in some_tuples:
for x in tup:
flattened.append(x)

你可以有任意多级别的嵌套,但是如果你有两三个以上的嵌套,你就应该考虑下代码可读性的问题了。分辨列表推导式的列表推导式中的语法也是很重要的:

In [167]: [[x for x in tup] for tup in some_tuples]
Out[167]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

这段代码产⽣了⼀个列表的列表,⽽不是扁平化的只包含元素的列表。

二、函数

函数是Python中最主要也是最重要的代码组织和复⽤⼿段。作为最重要的原则,如果你要重复使⽤相同或⾮常类似的代码,就需要写⼀个函数。通过给函数起⼀个名字,还可以提⾼代码的可读性。

函数使⽤ def 关键字声明,⽤ return 关键字返回值:

def my_function(x, y, z=1.5):
 if z > 1:
	return z * (x + y)
else:
	return z / (x + y)

同时拥有多条return语句也是可以的。如果到达函数末尾时没有遇到任何⼀条return语句,则返回None。

1、位置参数与关键字参数

函数可以有⼀些位置参数(positional)和⼀些关键字参数(keyword)。关键字参数通常⽤于指定默认值或可选参数。在上⾯的函数中,x和y是位置参数,⽽z则是关键字参数。也就是说,该函数可以下⾯这两种⽅式进⾏调⽤:

my_function(5, 6, z=0.7)
my_function(3.14, 7, 3.5)
my_function(10, 20)

函数参数的主要限制在于:关键字参数必须位于位置参数(如果有的话)之后。你可以任何顺序指定关键字参数。也就是说,你不⽤死记硬背函数参数的顺序,只要记得它们的名字就可以了。

也可以⽤关键字传递位置参数。 前⾯的例⼦,也可以写为:

my_function(x=5, y=6, z=7)
my_function(y=6, x=5, z=7)

这种写法可以提⾼可读性。

2、命名空间、作用域和局部函数

函数可以访问两种不同作⽤域中的变量:全局(global)和局部(local)。Python有⼀种更科学的⽤于描述变量作⽤域的名称,即命名空间(namespace)任何在函数中赋值的变量默认都是被分配到局部命名空间(local namespace)中的。 局部命名空间是在函数被调⽤时创建的,函数参数会⽴即填⼊该命名空间。

在函数执⾏完毕之后,局部命名空间就会被销毁(会有⼀些例外的情况,具体请参⻅后⾯介绍闭包的那⼀节)。看看下⾯这个函数:

def func():
a = []
for i in range(5):
a.append(i)

调⽤func()之后,⾸先会创建出空列表a,然后添加5个元素,最后a会在该函数退出的时候被销毁。假如我们像下⾯这样定义a:

a = []
def func():
for i in range(5):
a.append(i)

虽然可以在函数中对全局变量进⾏赋值操作,但是那些变量必须⽤global关键字声明成全局的才⾏:

In [168]: a = None
In [169]: def bind_a_variable():
.....: global a
.....: a = []
.....: bind_a_variable()
.....:
In [170]: print(a)

注意:我常常建议⼈们不要频繁使⽤global关键字。因为全局变量⼀般是⽤于存放系统的某些状态的。如果你发现⾃⼰⽤了很多,那可能就说明得要来点⼉⾯向对象编程了(即使⽤类)。

3、返回多个值

在我第⼀次⽤Python编程时(之前已经习惯了Java和C++),最喜欢的⼀个功能是:函数可以返回多个值。下⾯是⼀个简单的例⼦:

def f():
a = 5
b = 6
c = 7
return a, b, c
a, b, c = f()

在数据分析和其他科学计算应⽤中,你会发现⾃⼰常常这么⼲。该函数其实只返回了⼀个对象,也就是⼀个元组,最后该元组会被拆包到各个结果变量中。在上⾯的例⼦中,我们还可以这样写:

return_value = f()

这⾥的return_value将会是⼀个含有3个返回值的三元元组。此外,还有⼀种⾮常具有吸引⼒的多值返回⽅式——返回字典:

def f():
a = 5
b = 6
c = 7
return {'a' : a, 'b' : b, 'c' : c}

取决于⼯作内容,第⼆种⽅法可能很有⽤。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@u@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值