- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python序列操作之进阶篇由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
简介 。
Python 的序列(sequence)通常指一个可迭代的容器,容器中可以存放任意类型的元素。列表和元组这两种数据类型是最常被用到的序列,python内建序列有六种,除了刚刚有说过的两种类型之外,还有字符串、Unicode字符串、buffer对像和最后一种xrange对像,这几种都是不常使用的。本文讲解了列表推导式、切片命名、列表元素排序、列表元素分组的使用方法。学习了 Python 基本的列表操作后,学习这些进阶的操作,让我们写出的代码更加优雅简洁和 pythonic .
列表推导式 。
当我们想要根据某些规则来构造一个列表时,首先想到的应该是列表推导式。列表推导式简化了循环操作,例如我们想要从一个原始文件名列表中获取全部 .py 文件,在没有列表推导式的情况下,我们通常会这样做:
1
2
3
4
5
6
7
8
9
|
file_list
=
[
'foo.py'
,
'bar.txt'
,
'spam.py'
,
'animal.png'
,
'test.py'
]
py_list
=
[]
for
file
in
file_list:
if
file
.endswith(
'.py'
):
py_list.append(
file
)
print
(py_list)
# output
[
'foo.py'
,
'spam.py'
,
'test.py'
]
|
而如果使用列表推导式则可简化为:
1
2
3
4
|
py_list
=
[f
for
f
in
file_list
if
f.endswith(
'.py'
)]
print
(py_list)
# output
[
'foo.py'
,
'spam.py'
,
'test.py'
]
|
列表推导式的介绍网上资源很多,不再赘述。这里只强调,当你需要根据某个规则来构造一个列表时,首先应该想一想,能否使用简洁的列表推导式来实现该需求,否则再回到常规的方式.
为切片命名 。
Python 的列表切片使用起来非常方便,但有时也会影响代码可读性。例如有一个字符串:
1
|
record
=
'..........19.6..........100..........'
|
19.6 为产品价格,100 为产品数量,那么计算总价格为
但是如果这样写,可能过一段时间我们再来读代码时已经忘记了 record[10:14] 、record[24:27] 切出来的究竟是什么?为了解决上述问题,可以给切片命个名来增强可读性.
1
2
3
4
|
record
=
'..........19.6..........100..........'
price
=
slice
(
10
,
14
)
count
=
slice
(
24
,
27
)
total_price
=
float
(record[price])
*
int
(record[count])
|
slice 接收的参数格式为 slice(stop) 、slice(start, stop[, step]) 。如果只接收了一个参数,则等价于切片语法 [:stop] ,如果接收两个参数,则等价于切片语法 [start:stop] ,如果接收三个参数,则等价于切片语法 [start:stop:step] .
排序 。
排序相关的任务通常由内置函数 sorted 完成。需要排序的元素一般存放在一个列表容器中,列表可以存放任意类型的元素,而 sorted 函数的 key 关键字使得我们能够轻松地指定元素排序的关键字,让排序变得异常简单。下面将给出几个常见的排序例子以说明 key 关键字的使用方法。注意 Python3 和 Python2 的排序方法不能通用,下面的例子只适用于 Python3 ,Python2 的排序方法未包含在本文中.
情况一 。
列表中的元素已经是可比较元素,直接将列表传入 sorted 函数即可返回一个已排序列表。默认为升序排列,降序排列可以指定 reverse 参数,例如:
1
2
3
4
5
6
|
>>> l
=
[
3
,
5
,
4
,
1
,
8
]
>>>
sorted
(l)
[
1
,
3
,
4
,
5
,
8
]
>>>
sorted
(l, reverse
=
True
)
[
8
,
5
,
4
,
3
,
1
]
>>>
|
情况二 。
需要排序的元素是一个元组或者字典,希望根据我指定的关键字来排序,例如有如下两个列表:
1
2
3
4
5
6
7
|
l_v1
=
[(
'b'
,
2
),(
'a'
,
1
),(
'c'
,
3
),(
'd'
,
4
)]
l_v2
=
[
{
'fname'
:
'Brian'
,
'lname'
:
'Jones'
,
'uid'
:
1003
},
{
'fname'
:
'David'
,
'lname'
:
'Beazley'
,
'uid'
:
1002
},
{
'fname'
:
'John'
,
'lname'
:
'Cleese'
,
'uid'
:
1001
},
{
'fname'
:
'Big'
,
'lname'
:
'Jones'
,
'uid'
:
1004
}
]
|
l_v1 是一个元组列表, l_v2 是一个字典列表。对 l_v1 我们希望根据元组中第二个元素来排序,对 l_v2 我们希望根据字典的关键字 uid 进行排序.
sorted 函数接收一个关键字参数 key ,该参数指定一个可调用函数,函数返回一个值(只要是可比较的),那么 sorted 函数将根据返回的关键字对列表中的元素进行排序.
例如对上面的例子:
1
2
3
4
5
6
7
8
9
10
11
|
>>> l_v1
=
[(
'b'
,
2
),(
'a'
,
1
),(
'c'
,
3
),(
'd'
,
4
)]
>>>
sorted
(l_v1, key
=
lambda
x: x[
1
])
[(
'a'
,
1
), (
'b'
,
2
), (
'c'
,
3
), (
'd'
,
4
)]
>>> l_v2
=
[
{
'fname'
:
'Brian'
,
'lname'
:
'Jones'
,
'uid'
:
1003
},
{
'fname'
:
'David'
,
'lname'
:
'Beazley'
,
'uid'
:
1002
},
{
'fname'
:
'John'
,
'lname'
:
'Cleese'
,
'uid'
:
1001
},
{
'fname'
:
'Big'
,
'lname'
:
'Jones'
,
'uid'
:
1004
}
]
>>>
sorted
(l_v2, key
=
lambda
x: x[
'uid'
])
[{
'lname'
:
'Cleese'
,
'uid'
:
1001
,
'fname'
:
'John'
}, {
'lname'
:
'Beazley'
,
'uid'
:
1002
,
'fname'
:
'David'
}, {
'lname'
:
'Jones'
,
'uid'
:
1003
,
'fname'
:
'Brian'
}, {
'lname'
:
'Jones'
,
'uid'
:
1004
,
'fname'
:
'Big'
}]
|
这里 lambda 函数是一个常用的技巧。lambda 关键字后边的 x 是该函数接收的参数,冒号后边的表达式是该函数的返回值。对 l_v1 来说,传递给参数 x 的就是每一个元组,其返回元组的第二个元素用于排序;对 l_v2 来说,传递给参数 x 的就是列表中的每一个字典元素,其返回字典中 uid 对应的值用于排序.
除了使用匿名函数 lambda 这种通用的方法外,Python 标准库 operator 为我们提供了一个 itemgetter 函数替代我们写的 lambda 函数,且其性能会比使用 lambda 函数略有提升.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
>>>
from
operator
import
itemgetter
>>> l_v1
=
[(
'b'
,
2
),(
'a'
,
1
),(
'c'
,
3
),(
'd'
,
4
)]
>>>
sorted
(l_v1, key
=
itemgetter(
1
))
[(
'a'
,
1
), (
'b'
,
2
), (
'c'
,
3
), (
'd'
,
4
)]
>>> l_v2
=
[
{
'fname'
:
'Brian'
,
'lname'
:
'Jones'
,
'uid'
:
1003
},
{
'fname'
:
'David'
,
'lname'
:
'Beazley'
,
'uid'
:
1002
},
{
'fname'
:
'John'
,
'lname'
:
'Cleese'
,
'uid'
:
1001
},
{
'fname'
:
'Big'
,
'lname'
:
'Jones'
,
'uid'
:
1004
}
]
>>>
sorted
(l_v2, key
=
itemgetter(
'uid'
))
[
{
'lname'
:
'Cleese'
,
'uid'
:
1001
,
'fname'
:
'John'
},
{
'lname'
:
'Beazley'
,
'uid'
:
1002
,
'fname'
:
'David'
},
{
'lname'
:
'Jones'
,
'uid'
:
1003
,
'fname'
:
'Brian'
},
{
'lname'
:
'Jones'
,
'uid'
:
1004
,
'fname'
:
'Big'
}
]
|
以上例子均是返回一个单一的值用于排序关键字,前面说过,关键字 key 接收的函数可以返回任意的可比较对象。例如在 python 中,元组是可以比较的。对元组的比较规则为首先比较元组中第一个位置上的元素,如果相等,在比较第二个位置上的元素,依次类推。回到 l_v2 的例子,假设现在需求变了,我们首先对 lname 对应的值排序,如果 lname 对应的值相等,那么再根据 fname 确定其顺序.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> l_v2
=
[
{
'fname'
:
'Brian'
,
'lname'
:
'Jones'
,
'uid'
:
1003
},
{
'fname'
:
'David'
,
'lname'
:
'Beazley'
,
'uid'
:
1002
},
{
'fname'
:
'John'
,
'lname'
:
'Cleese'
,
'uid'
:
1001
},
{
'fname'
:
'Big'
,
'lname'
:
'Jones'
,
'uid'
:
1004
}
]
>>>
sorted
(l_v2, key
=
lambda
x: (x[
'lname'
], x[
'fname'
]))
[
{
'lname'
:
'Beazley'
,
'uid'
:
1002
,
'fname'
:
'David'
},
{
'lname'
:
'Cleese'
,
'uid'
:
1001
,
'fname'
:
'John'
},
{
'lname'
:
'Jones'
,
'uid'
:
1004
,
'fname'
:
'Big'
},
{
'lname'
:
'Jones'
,
'uid'
:
1003
,
'fname'
:
'Brian'
}
]
|
这个例子中,lambda 函数返回的不再是一个标量值,而是一个元组 (x['lname'], x['fname']) ,根据元组的比较规则,首先根据元组的第一个位置上的元素 x['lname'] 的大小排序,由于列表中有两个字典其 lname 对应的值都为 Jones,因此再根据元组第二个位置的元素 x['fname'] 的值排序,由于 Big 比 Brian 要小(按字母顺序依次比较),所以 Big 排在了前面.
同样使用 itemgetter 函数也是可以的,且性能会略有提升。此外我觉得 itemgetter 比 lambda 更加简洁和可读一点.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> l_v2
=
[
{
'fname'
:
'Brian'
,
'lname'
:
'Jones'
,
'uid'
:
1003
},
{
'fname'
:
'David'
,
'lname'
:
'Beazley'
,
'uid'
:
1002
},
{
'fname'
:
'John'
,
'lname'
:
'Cleese'
,
'uid'
:
1001
},
{
'fname'
:
'Big'
,
'lname'
:
'Jones'
,
'uid'
:
1004
}
]
>>>
sorted
(l_v2, key
=
itemgetter(
'lname'
,
'fname'
))
[
{
'lname'
:
'Beazley'
,
'uid'
:
1002
,
'fname'
:
'David'
},
{
'lname'
:
'Cleese'
,
'uid'
:
1001
,
'fname'
:
'John'
},
{
'lname'
:
'Jones'
,
'uid'
:
1004
,
'fname'
:
'Big'
},
{
'lname'
:
'Jones'
,
'uid'
:
1003
,
'fname'
:
'Brian'
}
]
|
情况三 。
需要排序的元素是一个 Python 对象,我们希望根据其某个属性值来排序。例如一个存放 User 对象的列表如下,根据其 name 属性排序:
1
2
3
4
5
6
7
8
9
|
class
User:
def
__init__(
self
, name):
self
.name
=
name
def
__str__(
self
):
return
'User: %s'
%
self
.name
__repr__
=
__str__
# 为了能够让 User 在解释器中显示为 'User: name' 的格式
user_list
=
[User(
'John'
), User(
'David'
), User(
'Big'
), User(
'Alen'
)]
|
方法与前面的一样,定义一个函数返回 User 的 name 属性的值,把该函数传给 sorted 的 key 参数.
1
2
3
4
|
>>> user_list
=
[User(
'John'
), User(
'David'
), User(
'Big'
), User(
'Alen'
)]
>>>
sorted
(user_list, key
=
lambda
x: x.name)
>>>
sorted
(user_list, key
=
lambda
x: x.name)
[User: Alen, User: Big, User: David, User: John]
|
但是,itemgetter 方法不再起作用,取而代之的是 attrgetter 方法.
1
2
|
>>>
sorted
(user_list, key
=
attrgetter(
'name'
))
[User: Alen, User: Big, User: David, User: John]
|
attrgetter 与 itemgetter 用法完全一致,只是 itemgetter 用于获取某个位置索引或者字典关键字的取值,而 attrgetter 用于获取对象的属性值.
PS:sorted 返回的是原始列表的一个已排序的副本,而原始列表的顺序并没有任何变化。如果你只想就地排序(即排序原始列表本身),则直接调用 list 的 sort 方法即可:list.sort() 。其用法与 sorted 函数一样,只是该函数没有返回值,调用后原始列表已变为一个已排序列表.
对序列中的元素进行分组 。
和排序类似,现想根据列表中元素的某个关键字分组,使关键字相同的元素分到同一组,并可以对分好的组进行进一步处理。例如有如下的一个列表:
1
2
3
4
5
6
7
8
9
10
|
rows
=
[
{
'address'
:
'5412 N CLARK'
,
'date'
:
'07/01/2012'
},
{
'address'
:
'5148 N CLARK'
,
'date'
:
'07/04/2012'
},
{
'address'
:
'5800 E 58TH'
,
'date'
:
'07/02/2012'
},
{
'address'
:
'2122 N CLARK'
,
'date'
:
'07/03/2012'
},
{
'address'
:
'5645 N RAVENSWOOD'
,
'date'
:
'07/02/2012'
},
{
'address'
:
'1060 W ADDISON'
,
'date'
:
'07/02/2012'
},
{
'address'
:
'4801 N BROADWAY'
,
'date'
:
'07/01/2012'
},
{
'address'
:
'1039 W GRANVILLE'
,
'date'
:
'07/04/2012'
},
]
|
列表的元素为字典,现想根据字典的 date 分组,使日期( date )相同的元素分到一个组。Python 的 itertools 模块中的 groupby 函数可以很好地解决该问题。为了使用 groupby 函数,首先需要对列表排序:
1
2
|
>>>
from
operator
import
itemgetter
>>> sorted_rows
=
sorted
(rows, key
=
itemgetter(
'date'
))
|
groupby 也和 sorted 一样有一个 key 关键字参数,其接收一个可调用函数,该函数返回的值被用做分组的关键字,其用法和 sorted 的 key 关键字参数一样 .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
>>>
for
date, items
in
groupby(sorted_rows, key
=
itemgetter(
'date'
)):
print
(date)
for
i
in
items:
print
(
' '
, i)
07
/
01
/
2012
{
'address'
:
'5412 N CLARK'
,
'date'
:
'07/01/2012'
}
{
'address'
:
'4801 N BROADWAY'
,
'date'
:
'07/01/2012'
}
07
/
02
/
2012
{
'address'
:
'5800 E 58TH'
,
'date'
:
'07/02/2012'
}
{
'address'
:
'5645 N RAVENSWOOD'
,
'date'
:
'07/02/2012'
}
{
'address'
:
'1060 W ADDISON'
,
'date'
:
'07/02/2012'
}
07
/
03
/
2012
{
'address'
:
'2122 N CLARK'
,
'date'
:
'07/03/2012'
}
07
/
04
/
2012
{
'address'
:
'5148 N CLARK'
,
'date'
:
'07/04/2012'
}
{
'address'
:
'1039 W GRANVILLE'
,
'date'
:
'07/04/2012'
}
|
可以看到 groupby 返回的值分别是用于分组的关键字对应的值和该组的全部成员。groupby 实际返回一个生成器,通过迭代即可分别对各组进行处理。值得注意的一点是,分组前对列表排序这一步必不可少,否则对于非紧邻的元素即使其值相同也会被分在不同组.
总结 。
以上就是关于python序列进阶篇的全部内容,希望本文的内容对大家学习或者使用python能有所帮助,如果有疑问大家可以留言交流,谢谢大家对我的支持.
最后此篇关于Python序列操作之进阶篇的文章就讲到这里了,如果你想了解更多关于Python序列操作之进阶篇的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在努力做到这一点 在我的操作中从数据库获取对象列表(确定) 在 JSP 上打印(确定) 此列表作为 JSP 中的可编辑表出现。我想修改然后将其提交回同一操作以将其保存在我的数据库中(失败。当我使用
我有以下形式的 Linq to Entities 查询: var x = from a in SomeData where ... some conditions ... select
我有以下查询。 var query = Repository.Query() .Where(p => !p.IsDeleted && p.Article.ArticleSections.Cou
我正在编写一个应用程序包,其中包含一个主类,其中主方法与GUI类分开,GUI类包含一个带有jtabbedpane的jframe,它有两个选项卡,第一个选项卡包含一个jtable,称为jtable1,第
以下代码产生错误 The nested query is not supported. Operation1='Case' Operation2='Collect' 问题是我做错了什么?我该如何解决?
我已经为 HA redis 集群(2 个副本、1 个主节点、3 个哨兵)设置了本地 docker 环境。只有哨兵暴露端口(10021、10022、10023)。 我使用的是 stackexchange
我正在 Desk.com 中构建一个“集成 URL”,它使用 Shopify Liquid 模板过滤器语法。对于开始日期为 7 天前而结束日期为现在的查询,此 URL 需要包含“开始日期”和“结束日期
你一定想过。然而情况却不理想,python中只能使用类似于 i++/i--等操作。 python中的自增操作 下面代码几乎是所有程序员在python中进行自增(减)操作的常用
我需要在每个使用 github 操作的手动构建中显示分支。例如:https://gyazo.com/2131bf83b0df1e2157480e5be842d4fb 我应该显示分支而不是一个。 最佳答
我有一个关于 Perl qr 运算符的问题: #!/usr/bin/perl -w &mysplit("a:b:c", /:/); sub mysplit { my($str, $patt
我已经使用 ArgoUML 创建了一个 ERD(实体关系图),我希望在一个类中创建两个操作,它们都具有 void 返回类型。但是,我只能创建一个返回 void 类型的操作。 例如: 我能够将 book
Github 操作仍处于测试阶段并且很新,但我希望有人可以提供帮助。我认为可以在主分支和拉取请求上运行 github 操作,如下所示: on: pull_request push: b
我正在尝试创建一个 Twilio 工作流来调用电话并记录用户所说的内容。为此,我正在使用 Record,但我不确定要在 action 参数中放置什么。 尽管我知道 Twilio 会发送有关调用该 UR
我不确定这是否可行,但值得一试。我正在使用模板缓冲区来减少使用此算法的延迟渲染器中光体积的过度绘制(当相机位于体积之外时): 使用廉价的着色器,将深度测试设置为 LEQUAL 绘制背面,将它们标记在模
有没有聪明的方法来复制 和 重命名 文件通过 GitHub 操作? 我想将一些自述文件复制到 /docs文件夹(:= 同一个 repo,不是远程的!),它们将根据它们的 frontmatter 重命名
我有一个 .csv 文件,其中第一列包含用户名。它们采用 FirstName LastName 的形式。我想获取 FirstName 并将 LastName 的第一个字符添加到它上面,然后删除空格。然
Sitecore 根据 Sitecore 树中定义的项目名称生成 URL, http://samplewebsite/Pages/Sample Page 但我们的客户有兴趣降低所有 URL(页面/示例
我正在尝试进行一些计算,但是一旦我输入金额,它就会完成。我只是希望通过单击按钮而不是自动发生这种情况。 到目前为止我做了什么: Angular JS - programming-fr
我的公司创建了一种在环境之间移动文件的复杂方法,现在我们希望将某些构建的 JS 文件(已转换和缩小)从一个 github 存储库移动到另一个。使用 github 操作可以实现这一点吗? 最佳答案 最简
在我的代码中,我创建了一个 JSONArray 对象。并向 JSONArray 对象添加了两个 JSONObject。我使用的是 json-simple-1.1.jar。我的代码是 package j
我是一名优秀的程序员,十分优秀!