1.3 Python列表、字典、集合和JSON四种数据类型
Applications of Deep Neural Networks with Keras
基于Keras的深度神经网络应用
著:Jeff Heaton 译:人工智能学术前沿
目录
1.Python基础
2.机器学习Python
3.TensorFlow简介
4.表格类数据的训练
5.正则化和Dropout
6.用于计算机视觉的卷积神经网络
7.生成对抗网络
8.Kaggle数据集
9.迁移学习
10.Keras的时间序列
11.自然语言处理与语音识别
12.强化学习
13.Advanced/Other Topics
14.其他神经网络技术
1.3 Python列表、字典、集合和JSON四种数据类型
Part 1.3: Python Lists, Dictionaries, Sets and JSON
python数据结构
data structures
与大多数现代编程语言一样,Python包括列表、集合、字典和其他数据结构作为内置类型。这两者的语法外观都类似于JSON。Python和JSON的兼容性将在本模块的后面讨论。本课程将主要关注列表、集合和字典。理解这三种基本集合类型之间的差异是至关重要的。
Dictionary
——字典是一个可变的无序集合,Python用名称和值对对其进行索引。
List
——列表是一种允许重复元素的可变有序集合。
Set
—集合是一个没有重复元素的可变无序集合。
Tuple
——元组是一种不可变的有序集合,允许重复元素
可变类型与不可变类型
mutable collection and immutable collection
大多数Python数据结构是可变的,这意味着程序可以在定义之后添加和删除元素。不可变数据结构不能在定义之后添加或删除项。同样重要的是,要理解有序集合意味着项目在程序将它们添加到集合时保持它们的顺序。这个顺序可能不是任何特定的顺序,比如字母或数字。
列表和元组在Python中非常相似,经常被混淆。显著的区别是 列表是可变的,而元组不是 。因此,当我们想要包含类似的项时,我们就会包含一个列表,当我们提前知道哪些信息会包含在其中时,我们就会包含一个元组。
许多编程语言都包含一个称为数组的数据集合。很明显,Python中没有数组类型。通常, 程序员在Python中会使用列表来代替数组 。大多数编程语言中的数组都是固定长度的,这要求程序提前知道所需元素的最大数量。这种限制导致了臭名昭著的数组溢出错误和安全问题。Python列表要灵活得多,因为程序可以动态更改列表的大小。
列表和元组
Lists and Tuples
对于Python程序来说,列表和元组非常相似。作为程序员,只使用列表而忽略元组是可能的。列表和元组都持有有序的项集合。
您将看到的语法上的主要区别是列表由方括号[]括起来,而元组由括号()括起来。下面的代码同时定义了list和tuple。
l = ['a', 'b', 'c', 'd']
t = ('a', 'b', 'c', 'd')
print(l)
print(t)
代码片段:可切换语言,无法单独设置文字格式
输出
['a', 'b', 'c', 'd']
('a', 'b', 'c', 'd')
您将通过编程方式看到的主要区别是,列表是可变的,这意味着程序可以更改它。元组是不可变的,这意味着程序不能更改它。下面的代码演示了该程序可以更改列表。这段代码还说明了Python索引从元素0开始。访问元素1将修改集合中的第二个元素。元组相对于列表的一个优点是元组的迭代速度通常比列表快一些。
l[1] = 'changed'
#t[1] = 'changed' # This would result in an error
print(l)
输出
['a', 'changed', 'c', 'd']
for 循环语句访问列表元素
for-each
与许多语言一样,Python也有for-each语句。该语句允许循环遍历集合(如列表或元组)中的每个元素。
# Iterate over a collection.
for s in l:
print(s)
输出
a
changed
c
d
enumerate函数
enumerate
enumerate函数在枚举集合和访问当前所在元素的索引时非常有用
# Iterate over a collection, and know where your index. (Python is zero-based!)
for i,l in enumerate(l):
print(f"{i}:{l}")
输出
0 : a
1 : changed
2 : c
3 : d
列表的操作
list
列表可以添加多个对象,比如字符串。允许重复值。元组不允许程序在定义之后添加其他对象。
Manually add i tems , l i s t s a l l o w d u p l i c a t e s
c = [ ]
c . append ( ' a ' )
c . append ( 'b ' )
c . append ( ' c ' )
c . append ( ' c ' )
print ( c )
代码片段:可切换语言,无法单独设置文字格式
输出
[ ' a ' , 'b ' , ' c ' , ' c ' ]
有序集合,如列表和元组,允许您通过索引号访问元素,如下面的代码所示。无序集合,如字典和集合,不允许程序以这种方式访问它们。
print ( c [ 1 ] )
代码片段:可切换语言,无法单独设置文字格式
输出
b
列表可以添加多个对象,比如字符串。允许重复值。元组不允许程序在定义之后添加其他对象。对于insert函数,程序员必须指定一个索引。不允许对元组进行这些操作,因为它们会导致更改。
# I n s e r t
c = [ ' a ' , 'b ' , ' c ' ]
c . i n s e r t ( 0 , ' a0 ' )
print ( c )
# Remove
c . remove ( 'b ' )
print ( c )
# Remove a t i n d e x
del c [ 0 ]
print ( c )
输出
[ ' a0 ' , ' a ' , 'b ' , ' c ' ]
[ ' a0 ' , ' a ' , ' c ' ]
[ ' a ' , ' c ' ]
集合
Sets
Python集合包含无序的对象集合,但集合不允许重复。如果程序向集合中添加重复项,则每个项只有一个副本保留在集合中。向集合中添加重复项不会导致错误。下面的任何一种技术都可以定义一个集合。
s = set ( )
s = { ' a ' , 'b ' , ' c ' }
s = set ( [ ' a ' , 'b ' , ' c ' ] )
print ( s )
输出
{ ' c ' , ' a ' , 'b ' }
列表总是用大括号[]括起来 , 元组用括号()括起来 ,现在我们看到程序员用大括号括起来了一个集合。程序可以在运行时向集合中添加项。程序可以使用add函数动态地向集合添加项。需要注意的是, append函数将项添加到列表和元组中,而add函数将项添加到集合中 。
# Manually add i tems , s e t s do no t a l l o w d u p l i c a t e s
# S e t s add , l i s t s append . I find this annoying
c = set ( )
c . add ( 'a' )
c . add ( 'b' )
c . add ( 'c' )
c . add ( 'c' )
print ( c )
输出
{ ' c ' , ' a ' , 'b ' }
Maps/Dictionaries/Hash Tables
Maps/Dictionaries/Hash Tables
许多编程语言都包含映射、字典或哈希表的概念。这些都是非常相关的概念。Python提供了一个字典,它本质上是一个名称-值对的集合。程序使用花括号定义字典,如下所示。
d = { 'name ' : " J e f f " , ' a d d r e s s ' : " 123 ␣Main " }
print ( d )
print ( d [ 'name ' ] )
i f 'name ' in d :
print ( "Name␣ i s ␣ d e fi n e d " )
i f ' age ' in d :
print ( " age ␣ d e fi n e d " )
e l s e :
print ( " age ␣ u n d e fi n e d " )
输出
{ 'name ' : ' J e f f ' , ' add re s s ' : '1 2 3 Main ' }
J e f f
Name i s d e fi n e d
age u n d e fi n e d
注意不要试图访问未定义的键,因为这会导致错误。您可以检查是否定义了一个键,如上所示。您还可以访问该目录并提供默认值,如下面的代码所示。
d . g e t ( ' unknown_key ' , ' d e f a u l t ' )
输出
' d e f a ul t '
您还可以访问字典的各个键和值
d = { 'name ' : " J e f f " , ' a d d r e s s ' : " 123 ␣Main " }
# A l l o f t h e k ey s
print ( f "Key : ␣ {d . key s ( ) } " )
# A l l o f t h e v a l u e s
print ( f " Values : ␣ {d . v al u e s ( ) } " )
输出
Key : dic t_ ke y s ( [ ' name ' , ' add re s s ' ] )
Values : di c t_ v al u e s ( [ ' J e f f ' , '1 2 3 Main ' ] )
字典和列表可以合并。此语法与JSON密切相关。字典和列表是构建非常复杂的数据结构的好方法。Python允许字符串使用引号(")和撇号('),而JSON只允许双引号(")。我们将在稍后的模块中更详细地讨论JSON。
下面的代码显示了字典和列表的混合用法。
# Python l i s t & map s t r u c t u r e s
cu s t ome r s = [
{ " name " : " J e f f ␣&␣Tracy ␣Heaton " , " p e t s " : [ "Wynton " , " C ri c k e t " ,
" Hickory " ] } ,
{ " name " : " John ␣ Smith " , " p e t s " : [ " r o v e r " ] } ,
{ " name " : " Jane ␣Doe " }
print ( cu s t ome r s )
for customer in cu s t ome r s :
print ( f " { customer [ ' name ' ] } : { customer . g e t ( ' p e t s ' , ␣ ' no␣ p e t s ') } " )
输出
[ { ' name ' : ' J e f f & Tracy Heaton ' , ' pe t s ' : [ 'Wynton ' , ' C ri c k e t ' ,' Hickory ' ] } , { 'name ' : ' John Smith ' , ' pe t s ' : [ ' r o ve r ' ] } , { 'name ' : ' JaneDoe ' } ]
J e f f & Tracy Heaton : [ ' Wynton ' , ' C ri c k e t ' , ' Hickory ' ]
John Smith : [ ' r o ve r ' ]
Jane Doe : no p e t s
变量customer是一个列表,包含三个表示客户的字典。您可以将这些字典视为表中的记录。这些单独记录中的字段是字典的键。
这里的键名和宠物是字段。然而,野外宠物有一个宠物名字的列表。嵌套列表和映射的深度是没有限制的。也可以在映射中嵌套映射,或者在另一个列表中嵌套列表。
更高级的列表
More Advanced Lists
本节介绍的列表有几个高级特性。 zip就是这样一个函数。两个列表可以通过zip命令组合成一个列表。下面的代码演示了zip命令。
a = [1,2,3,4,5]
b = [5,4,3,2,1]
print(zip(a,b))
输出
<zip object at 0x00000246ea2f1d40>
为了查看zip函数的结果,我们将返回的 zip 对象转换为一个列表。如您所见, zip 函数返回一个元组列表。每个元组表示函数压缩在一起的一对项。保持了两个列表中的顺序。
a = [1,2,3,4,5]
b = [5,4,3,2,1]
print(list(zip(a,b)))
输出
[(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)]
使用zip命令的通常方法是在for循环中。下面的代码展示了for循环如何将变量分配给程序正在迭代的每个集合。
a = [1,2,3,4,5]
b = [5,4,3,2,1]
for x,y in zip(a,b):
print(f'{x} - {y}')
输出
1 - 5
2 - 4
3 - 3
4 - 2
5 - 1
通常,当传递给zip命令时, 这两个集合的长度是相同的 。拥有不同长度的集合并不是错误。如下面的代码所示,zip命令只处理小于较小集合长度的元素。
a = [1,2,3,4,5]
b = [5,4,3]
print(list(zip(a,b)))
输出
[(1, 5), (2, 4), (3, 3)]
有时,当for循环遍历一个有序集合时,您可能希望知道当前的数字索引。使用enumerate命令跟踪集合元素的索引位置。因为enumerate命令处理集合的数字索引,zip命令将为无序集合中的元素分配任意索引。
考虑如何构造一个Python程序,将每个大于5的元素都修改为5。下面的程序执行这个转换。enumerate命令允许循环知道它当前所在的元素索引,从而允许程序能够更改集合中当前元素的值。
a = [2, 10, 3, 11, 10, 3, 2, 1]
for i, x in enumerate(a):
if x>5:
a[i] = 5
print(a)
输出
[2, 5, 3, 5, 5, 3, 2, 1]
列表生成式 命令可以动态构建一个列表。下面的 生成式 是: 从0到9,并将每个值(乘以10)加到一个列表中。
lst = [x*10 for x in range(10)]
print(lst)
输出
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
一本字典也可以是一种 生成式 。一般格式为:
dict_variable = {key:value for (key,value) in dictonary.items()}
它的一个常见用途是 建立符号列名的索引 。
text = ['col-zero','col-one', 'col-two', 'col-three']
lookup = {key:value for (value,key) in enumerate(text)}
print(lookup)
输出
{'col-zero': 0, 'col-one': 1, 'col-two': 2, 'col-three': 3}
这可以用来方便地根据名称查找列的索引。
print(f'The index of "col-two" is {lookup["col-two"]}')
输出
The index of "col-two" is 2
JSON的介绍
An Introduction to JSON
存储在CSV文件中的数据必须是平面的规整的;也就是说,它必须适合行和列。大多数人将这种类型的数据称为结构化数据或表格数据。这个数据是表格式的,因为 每一行的列数是相同的。单个行可能缺少列的值;但是,这些行仍然有相同的列 。
这种类型的数据对机器学习很方便,因为大多数模型,比如神经网络,也期望传入的数据是固定维度的。现实世界的信息并不总是那么表格化。考虑这些行是否代表客户。这些人可能有多个电话号码和地址。如何使用固定的列数来描述这样的数据?在每行中列出这些课程或学生的列表是很有用的,每行可以是可变长度的。
JavaScript对象表示法(JSON)是一种标准的文件格式 ,它以类似于可扩展标记语言(XML)的分层格式存储数据。JSON只不过是列表和字典的层次结构。程序员将这种数据称为半结构化数据或分层数据。下面是一个示例JSON文件。
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
"phoneNumbers": [
"type": "home",
"number": "212 555-1234"
"type": "office",
"number": "646 555-4567"
"type": "mobile",
"number": "123 456-7890"
"children": [],
"spouse": null
}
上面的文件看起来有点像Python代码。你可以看到定义字典的花括号和定义列表的方括号。 JSON要求只有一个根元素 。列表或字典可以完成这个角色。 JSON要求用双引号括住字符串和名称。JSON中不允许使用单引号。
JSON文件总是合法的JavaScript语法。JSON通常也和Python代码一样有效,如下面的Python程序所示。
jsonHardCoded = {
"firstName": "John",
"lastName": "Smith",
"isAlive": True,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
"phoneNumbers": [
"type": "home",
"number": "212 555-1234"
"type": "office",
"number": "646 555-4567"
"type": "mobile",
"number": "123 456-7890"
"children": [],
"spouse": None
}
通常,从文件、字符串或互联网读取JSON比硬编码更好,如这里所示。然而,对于内部数据结构,这种硬编码有时是有用的。
Python包含对JSON的支持。 当Python程序加载JSON时,会返回根列表或字典 ,如下面的代码所示。
import json
json_string = '{"first":"Jeff","last":"Heaton"}'
obj = json.loads(json_string)
print(f"First name: {obj['first']}")
print(f"Last name: {obj['last']}")
输出
First name: Jeff
Last name: Heaton
Python程序也可以从文件或URL加载JSON。
import requests