安卓版 PySyft
扩展 OpenMined 为移动设备带来隐私
什么是 PySyft
“PySyft 是一个用于安全、私人深度学习的 Python 库。PySyft 使用 PyTorch 中的多方计算(MPC) 将私有数据从模型训练中分离出来
PySyft 是露天家族中的主要部分。
什么是 Android 版的 PySyft
PySyft for Android 是让不同平台在 PySyft 环境下协同工作的第一步
PySyft 依靠工人来完成这项工作。目前,这些工作器是用 Python 实现的,并与 PyTorch 上的 PySyft 包装器挂钩
PySyft for Android 扩展了这个系统,允许边缘的移动设备使用不同的框架进行操作。在这个概念验证的例子中,Android 应用程序使用 Nd4J 和 DL4J 来计算来自 PySyft (PyTorch)工作器的操作
应用程序
在联合学习设置中,Android 应用程序位于边缘,保存其数据以进行本地训练
对于 MPC,我们可以让参与者使用不同的操作系统和平台来进行操作
高层架构
该设置有三个主要组件:
- 一个 PySyft worker 实现 WebsocketIOClientWorker 作为门面
- 一个在两个参与者之间转发请求和响应的WebsocketIOServerWorker
- 执行从外观发送的操作的 Android 应用程序
下图显示了在此设置中如何处理驱动程序或执行元发送的命令
这些对象构成了一个组件,通过 SocketIOClientWorker 提供与 PySyft 中任何其他工作器相同的 API。从参与者的角度来看,整个组件只是另一个工人
应用程序的架构
应用程序的架构可以在下图中看到。这是一个基于关注点分离的架构,由遵循干净架构的层来定义。这将允许我们在其他 Java/Kotlin 平台中重用大量工作
通信详细信息
通信是使用 SocketIO 完成的,但是服务器端的工作人员和 Android 应用程序都可以使用其他套接字库
主要的限制是由 PySyft 工作线程的同步特性造成的
- _recv_msg 是同步的,一旦操作被发送到 Android,它不能等待后者的回复,因为它正在通过服务器。这就是信号量在 SocketIO 类中所做的事情
使用中性张量表示
考虑到 Android 不能使用 PyTorch 对象,必须选择一个中性的表示来使数据在双方都可用。幸运的是 PyTorch 和 DL4J 都提供了使用 npy 格式的可能性。虽然这种转换会影响性能,但它向我们保证了双向传输的数据不会被破坏
与 TFLite 团队关于实现 npy 的对话也令人鼓舞,应该不会太难。这项工作也可以用于其他平台(例如,基于 KMath 的平台)
验证性测试(Proof of Concept 的缩写)
这个 PoC 实现了以下 PySyft 操作:发送、删除、获取和添加
使用了以下库:
- DL4J: 这是将处理操作的机器学习框架,尽管对于这个 PoC 来说只有 Nd4J 是必要的。该系统对其他框架是开放的
- msgpack: PySyft 使用它在工人之间移动数据和操作。这也必须在 Android 上实现,尽管如果必要的话可以使用不同的格式
- SocketIO :使用这个库有很强的依赖性,因为它也被代理/服务器使用。
怎么跑?
您必须安装 PySyft。遵循存储库中的说明
一个加密的、保护隐私的深度学习库
github.com](https://github.com/OpenMined/PySyft)
从以下存储库中获取应用程序的代码
通过在 GitHub 上创建一个帐户,为 OpenMined/AndroidWorker 开发做出贡献。
github.com](https://github.com/OpenMined/AndroidWorker)
运行此安装程序需要以下步骤:
- 启动 Android 应用程序
- 启动服务器(socket io _ server _ demo . py展示了如何以一种简单的方式完成这项工作)
- 启动 socketio 客户端
- 驱动程序可以在笔记本上运行。“插座鲍勃”可以作为一个例子
- 连接 socketio 客户端(Bob)
- 连接 Android 应用程序
- 开始用吧!
即将推出
- Kotlin 多平台模块,允许为 JVM 实现的核心在其他环境中使用
- Tensorflow Lite 实施
- KMath 实现
- 非阻塞套接字通信
- 压缩
- 有模型的计划
参考
- https://www.openmined.org/
- https://github.com/OpenMined/PySyft
- https://github.com/OpenMined/AndroidWorker
- https://docs . scipy . org/doc/numpy-1 . 14 . 0/neps/npy-format . html
- https://github.com/msgpack
Pytest 特性,您在(测试)生活中需要的特性
注意:这最初发布在martinheinz . dev
测试你的代码是开发不可或缺的一部分,质量测试可以帮你省去很多麻烦。有很多关于在 Python 中进行测试的指南,特别是关于用 Pytest 进行测试的指南,但是有相当多的特性我很少在任何地方看到提及,但是我经常需要。所以,这里列出了我不能没有的 Pytest 的技巧和特性列表(不久之后你也不能没有)。
异常测试
让我们从简单的开始。您有一个抛出异常的函数,您希望确保它在正确的条件下发生并包含正确的消息:
这里我们可以看到 Pytest 为我们提供的简单的上下文管理器。它允许我们指定应该引发的异常类型以及所述异常的消息。如果块中没有引发异常,则测试失败。当上下文管理器返回具有type
、value
或traceback
等属性的ExceptionInfo
类时,您还可以检查异常的更多属性。
过滤警告
除了异常,让我们看看警告。有时,您会在您使用的库内部的日志中收到大量警告消息。你无法修复它们,它们只会制造不必要的噪音,所以让我们摆脱它们:
这里我们展示了两种方法——在第一种方法中,我们通过在过滤器列表的前面插入一个过滤器,直接忽略指定类别的所有警告。这将导致您的程序忽略这一类别的所有警告,直到它终止,这可能并不总是可取的。对于第二种方法,我们使用上下文管理器,它在退出警告范围后恢复所有警告。我们还指定了record=True
,这样如果需要的话,我们可以检查发出的(忽略的)警告列表。
测试标准输出和标准错误消息
接下来,让我们看看下面的场景:你有一个命令行工具,它有一堆函数,这些函数将消息打印到标准输出,但不返回任何内容。那么,我们如何测试呢?
为了解决这个问题, Pytest 提供了名为capsys
的夹具,它可以很好地捕捉系统输出。要使用它,你只需要把它作为参数添加到你的测试函数中。接下来,在调用被测试的函数之后,您以 tuple - (out, err)
的形式捕获输出,然后您可以在 assert 语句中使用它。
修补对象
有时在测试时,您可能需要替换被测函数中使用的对象,以提供更可预测的数据集,或者避免所述函数访问可能不可用的资源。mock.patch
可以帮上忙:
在第一个例子中,我们可以看到修补函数,然后检查它们被调用的次数和参数。这些补丁也可以以装饰器和上下文管理器的形式堆叠。现在,对于一些更强大的用途:
上面代码片段中的第一个例子非常简单——我们替换了SomeClass
的方法,并让它返回None
。在第二个更实际的例子中,我们通过用 mock 替换requests.get
,并让它返回我们提供合适数据的对象,来避免依赖远程 API/资源。
mock
模块还能为你做更多的事情,其中一些相当疯狂——包括副作用、模仿属性、模仿不存在的属性等等。如果你在编写测试时遇到问题,那么你一定要检查这个模块的文档,因为你很可能在那里找到解决方案。
与conftest.py
共享灯具
如果你写了很多测试,那么在某个时候你会意识到把所有的Pytestfixture 放在一个地方是很好的,你可以从那里导入它们,因此可以在测试文件之间共享。这个可以用conftest.py
解决。
conftest.py
是一个位于测试目录树底部的文件。在这个文件中,你可以存储所有的测试夹具,然后这些夹具会被 Pytest 自动发现,所以你甚至不需要导入它们。
如果您需要在多个测试之间共享数据,这也很有帮助——只需创建返回测试数据的 fixture。
另一个有用的特性是指定 fixture 范围的能力——这在创建非常昂贵的 fixture 时非常重要,例如到数据库的连接(session
范围)和在范围的另一端是在每个测试用例(function
范围)后需要重置的连接。夹具scope
的可能值为:function
、class
、module
、package
和session
。
参数化夹具
我们已经在上面的例子中讨论了设备,所以让我们再深入一点。如果您想通过参数化来创建更多的通用夹具,该怎么办呢?
上面是一个为每个测试准备 SQLite 测试数据库的 fixture 的例子。这个 fixture 接收数据库的路径作为参数。使用request
对象将该路径传递给 fixture,该属性param
是传递给 fixture 的所有参数的 iterable,在本例中只有一个参数——路径。这里,这个 fixture 首先创建数据库文件(也可以填充它——为了清楚起见省略了),然后执行测试,测试完成后,fixture 删除数据库文件。
至于测试本身,我们使用带有 3 个参数的@pytest.mark.parametrize
——第一个是夹具的名称,第二个是夹具的参数值列表,它将成为request.param
,最后是关键字参数indirect=True
,它导致参数值出现在request.param
中。
我们需要做的最后一件事是添加 fixture 作为参数来测试它本身,这样我们就完成了。
有些情况下,跳过一些测试是合理的,无论是因为环境( Linux vs Windows )、互联网连接、资源可用性还是其他原因。那么,我们该怎么做呢?
这是一个非常简单的例子,展示了如何基于某种条件跳过一个有效的测试——在本例中,基于 PostgreSQL 服务器是否在机器上运行。在 Pytest 中还有许多与跳过或预测失败相关的很酷的特性,它们在这里有很好的记录,所以我不会在这里进行更多的详细描述,因为在这里复制和粘贴现有的内容似乎是多余的。
希望这几个小技巧能让你的测试体验变得更加愉快和高效,从而激励你写更多的测试。如果你有任何问题,请随时联系我,如果你有自己的建议或诀窍,请在这里分享。🙂
Python:初学者指南
对编码语言 Python 的介绍
Python 是当今最流行的编程语言之一。它最初由吉多·范·罗苏姆创作,并于 1991 年首次发行。Python 可以用于许多不同的目的,包括创建 web 应用程序、读取和修改文件、连接到数据库系统,以及处理大数据和一般的数据科学。就像许多编程语言一样,Python 也是一个奇特的计算器;它可以轻松地进行数学运算。
>>> 12 + 15 # Addition
27>>> 35 – 17 # Subtraction
18>>> 5 * 5 # Multiplication
25>>> 25 / 5 # Division
5.0>>> 5 ** 2 # Exponentiation (does NOT use ^ like some calculators)
25>>> 10 % 3 # Modular division (or “mod” for short — returns a remainder)
1>>> 10 // 3 # Floor division (or “round down” division)
3
让我们看看 Python 中的一些基本功能,希望在这篇博客结束时,你能更好地理解 Python 是什么,它能做什么,以及它对各地的数据科学家和程序员有多有用。
变量
在我们继续之前,让我们理解并定义什么是变量。一个变量允许我们保存数据,这样我们就可以回调或引用它,而不必重写整个数据。下面是我们保存到s1
、s2
和s3
的三个不同的变量(稍后我们将在博客中讨论为什么这是不好的命名实践,但请耐心等待)。
s1 = 123
s2 = 678.0
s3 = “This is my first string”
s4 = ‘and this is my second string’
如上所述,像我这样命名变量是不好的命名实践,所以让我来帮你理解为什么。在 Python 中,有一些必须遵循的“规则”,以及一些只是好的 Python 实践的“规则”(关于 Python 代码风格指南的更多信息,请参见这里的)。
“强制规则”是:变量名只能由字母、数字、下划线组成(不能有特殊字符);变量名不能以数字开头;最后,你不能用一个内置的 Python 关键字来命名一个变量(例如if
或else
)。
一些“好的 python 式实践”规则是:变量名应该总是是描述性的(我在上面打破的一个规则;不要说出x
或df
);没有大写字母(这些是留给上课用的);变量不应该以下划线开头(这意味着一些特殊的东西,我们不会在这篇博文中涉及);多词变量应该用snake_case
(全部小写用下划线分隔)而不是camelCase
(以大写开头的新词);最后,虽然您可以在内置 Python 函数后命名变量(如print
),但这样做是一个非常糟糕的主意。
除了执行上面的基本数学方程,我们还可以使用保存的变量来执行它们。比如加s1+ s2
会得到 801.0。我们不能将s3
加到s1
或s2
上,因为它们不是两个数字。试图这样做将导致 Python 抛出一个错误,并简要解释为什么这是不可能的。也就是说,你可以把s3
加到s4
上,因为它们都是我们所说的字符串!
Python Logo. Source.
Python 数据类型
现在我们对变量有了更好的理解,让我们看看 Python 中的基本数据类型。在我们看这些之前,我们需要理解“数据”实际上意味着什么。大多数人认为数据是信息的电子表格——这并不太离谱。数据其实只是的信息。Python 中运行和存储的一切都被认为是数据。
当再次学习变量时,让我们参考上面使用的例子(并提醒自己下面是什么)。在这些例子中,我们看到了 Python 中最常见的三种数据类型。
s1 = 123
s2 = 678.0
s3 = “This is my first string”
s4 = ‘and this is my second string’
在上面的第一个变量s1
中,我们看到了所谓的整数——在 Python 中通常被称为int
类型。一个int
是一个没有小数部分的数字——比如我们在上面的数学例子中使用的所有数字。
在第二个变量s2
中,我们看到了所谓的float——在 Python 中称为float
类型。float
是一个有小数部分的数字——即使这个小数部分是一个 0,就像我们上面的例子一样。
最后,我们的第三和第四个变量s3
和s4
被称为字符串——在 Python 中被称为str
类型。一个字符串是我们在 Python 中存储文本数据的方式。字符串就是一组单引号(')或双引号(" ")之间的字符串。Python 最终不在乎我们用什么来创建字符串,只要我们在创建字符串时保持一致。
容器/集合类型
在许多情况下,我们希望将许多值存储到一个变量中,称为容器或集合。这些容器可以容纳任意数量的其他对象。Python 中有许多常见的容器,所以让我们开始吧。
第一个,也可能是最常见的,叫做列表。列表是有序的、可变的、异构的对象集合。澄清一下:有序意味着对象的集合遵循特定的顺序,可变意味着列表可以变化——或者改变,异构意味着您可以在一个列表中混合和匹配任何类型的对象或数据类型(int
、float
或string
)。列表包含在一组方括号[]
中。实例化一个新列表可以通过几种不同的方式来完成,如下所示。
>>> new_list = [] # instantiates an empty list
[]>>> new_list = list() # also instantiates an empty list
[]>>> new_list = ['obj1', 'obj2', 'obj3'] # instantiates a list of strings
['obj1', 'obj2', 'obj3']
比列表更不常见的是所谓的元组。元组是相似的,因为它们是有序的和异构的,然而它们是不同的,因为它们是不可变的——这意味着一旦创建它们就不能变异或改变。元组包含在一组括号内()
。元组比列表稍微快一点,也小一点,所以尽管它们的存在部分是因为它们更有用的时候遗留下来的,但它们仍然有它们的用途。实例化一个新的元组也可以用几种不同的方式来完成。
>>> new_tuple = () # instantiates an empty tuple
()>>> new_tuple = tuple() # also instantiates an empty tuple
()>>> new_tuple = ('obj1', 'obj2', 'obj3') # instantiates a tuple of strings
('obj1', 'obj2', 'obj3')>>> new_tuple = ('obj1',) # tuples containing a single object need a trailing comma so Python knows it is a tuple rather than a grouping operation
('obj1',)
我们还有一套的。集合是无序的、可变的、唯一的对象集合(类似于数学中的传统集合)。可以通过调用set()
函数来创建集合,这将创建一个空集,通过一组花括号{}
传递我们的信息,或者通过传递 iterable 的单个参数,在这种情况下,Python 将返回一个新的集合,其中包含 iterable 中每个唯一元素的单个元素。
>>> new_set = set() # instantiates an empty set
set()>>> new_set = {'A', 'A', 'B', 'C', 'C', 'D'}
{'A', 'B', 'C', 'D'}>>> new_set = set(['A', 'A', 'B', 'C', 'C', 'D'])
{'A', 'B', 'C', 'D'}
最后,我们要讨论的最后一个容器是一个字典。字典是您在 Pythonic 之旅中遇到的最常见的容器类型之一。字典是无序的、可变的键值对。可以认为它们很像一个实际的字典,其中的键是“单词”,值是特定单词的“定义”。字典与其他容器类型非常相似,可以用多种不同的方式进行实例化。
>>> new_dict = {} # instantiates an empty dictionary
{}>>> new_dict = dict() # also instantiates an empty dictionary
{}>>> new_dict = {'a': 1, 'b': 2, 'c': 3}
{'a': 1, 'b': 2, 'c': 3}>>> new_dict = dict(a = 1, b = 2, c = 3)
{'a': 1, 'b': 2, 'c': 3}
如果你不确定你刚刚创建了什么类型的对象,你可以通过调用变量上的type()
函数来检查它,Python 会让你知道你已经创建了什么。
>>> type(new_list)
list>>> type(new_tuple)
tuple>>> type(new_set)
set>>> type(new_dict)
dictAnd thinking back to our variables we created earlier...>>> type(s1)
int>>> type(s2)
float>>> type(s3)
str>>> type(s4)
str
Another Python logo. Source.
至此,我们已经了解了 Python 的一个(非常)简单的定义,什么是变量以及如何实例化变量,Python 中的一些基本数据类型和一些基本容器/集合类型。虽然这并不意味着是一个包罗万象的速成课程,但希望它教会了您足够多的知识,让您能够进入 Python 的世界,学习更多知识,并将其应用到您的世界中。我个人将 Python 用于数据科学,但是正如我上面提到的:Python 的用途几乎是无止境的。如果你有兴趣学习更多关于 Python 如何与数据科学世界相关的知识,可以看看我在 Python 内的 pandas library 上的博客,看看这能有什么帮助。希望你喜欢这本书,下次再见!
python——开发面向未来应用的完美语言
Image by Gerd Altmann from Pixabay
来说说未来证明吧!
如今,技术正日益提高到一个先进的水平。因此,对于用户以及开发者/制造者来说,处理长时间的创建应用程序以保持最新版本的更新变得相当麻烦。
完整的设计范例正在以一种你的应用基于问题的方式来构建计划世界观。包含、排除或更新它们以与时俱进可能是一种简单的、测试性的或几乎难以置信的体验。你有机会选择。
总而言之,构建应用程序的理想方法是什么?这些应用程序很难随着创新的进步而更新,但另一方面,它们可以满足未来可预测的需求。
Python 编程语言统治着其他编程方言,例如 C、C++或 Java。Python 是一种面向对象的高级多世界观编程语言,具有动态亮点。
Photo by Hitesh Choudhary on Unsplash
- 它是由 Guido Van Rossum 设计的,他是一名荷兰软件工程师。它是全世界最受支持的编程方言之一。
- Python 的恶名比近年来任何时候都要多。Python 给出了巨大的亮点,吸引了每个软件工程师的注意。
Python 非常容易阅读和编写;随后,它减少了软件工程师之间的混乱。令人震惊的是,作为最重要的技术组织之一,谷歌将 Python 用于其各种应用程序,并且有一个完全专用的 Python 入口。
为什么 Python 是面向未来的应用?
通常,当我们谈论使用 Python 作为面向未来的应用程序时,它被分为不同的模式。
image source: fingent
使用设计模式
- 设计模式用于构建复杂的项目(通常是一个组合)。
- 它将一篇不可预测的文章的发展与其描述隔离开来。
- 这是最常用的创造性配置设计之一。
- 它敦促工程师们制定明确的区域语言。
- 此外,它能让设计师更快地学习商务用语。
在设计模式的帮助下,开发人员让你的代码更容易测试、维护和获取。
我们可以利用制造商的例子来保证代码串的安全。为了说明,万一我们通过保证所有属性都被公正地使用并且必须通过构造函数来设置,从而使绑定类永久化,那么我们可以利用生成器配置示例来保证绑定条目的条件不能被改变。
- 然后,我们将能够在应用程序中共享 bond 问题,而不会因为 bond 对象而面临任何竞争条件。
- 它给你一个体面的利用熟悉的 API,可以让你更好地理解该领域。
使用模板设计模式
image source: refactoring
模板设计模式是编程应用中最常用的例子之一。
我们可以考虑的最佳例子如下:
- 一个典型的行为规划改进设计。
- 它保证您的程序遵循推荐的行为。
- 如果我们需要实现包含各种进展/指南的计算,那么我们可以利用格式编程配置设计。
计算是指导方针或步骤,应在明确要求下执行,以实现想要的结果。
我们可以利用模板软件设计模式来执行计算。
格式配置示例用于支持清晰的计划和代码重用。它保证了方法被适当地组织执行。外来客人回避的手段。
布局示例保证代码是完美的追求坚实的标准,因为每个类有一个单独的职责,可以有效地尝试。
使用策略设计模式
战略设计模式是获得它的最简单的结构例子之一。它是最流行的社交编程配置设计之一。
客户代码可以在不改变大部分代码的情况下交易程序。使代码易于测试、理解并遵循可靠的标准。
使用装饰设计模式
装饰器设计模式用于在运行时或静态地激活或扩展项目的义务,而不改变其结构。
- 装饰设计模式示例是开闭原则的一个重要工具。
- 装饰设计模式可以用来增加文章的有用性,而不改变文章本身或不同的条目。
- 您可以利用 decorator design 来扩展一个项目,而不需要创建无数的子类。
装饰设计模式是一个选项,与实现遗留的树结构相反。
- 装饰设计模式使我们在每次需要在框架中加入新的有用性时,不必创建大量的类。
- 我们可以看到,使用装饰设计,我们在不制作新的产品或改变现有产品的情况下,为一个产品添加了额外的行为。
- 我们制造了一个混合系统,但没有制造任何新的类。
装饰设计模式是一个选项,与实现遗留的树结构相反。此外,装饰设计模式可以防止代码随着新需求的增加而呈指数级增长。
Image by Johnson Martin from Pixabay
总结
从上面的讨论中,我们已经看到了 Python 作为未来验证应用的完整场景。除此之外,我们还讨论了一个完整的流程,展示了软件工程师生活中的一个关键思想——利用适当的结构设计。具体来说,Python 编程语言被认为是负责构建经得起未来考验的应用程序的语言,因为它简单明了而且流行。
作者简介
Nathan McKinley 是位于美国芝加哥的 Cerdonis Technologies LLC - 移动应用开发公司的业务开发经理,他正在利用最新的技术更新和事实来开发经得起未来考验的移动应用,以便在市场上表现出色。作为一名移动技术领域的业务开发人员,我已经掌握了撰写有价值的技术见解的技能,以及在移动应用程序开发过程中利用这些见解的好处。
Python 和 Google APIs
或者如何让网上的数据变得有用。
Simple structure
在这个简单的指南中,你将学会使用谷歌云平台及其 API 从网络上收集一些数据。要使用 python,你可以在这个网页上运行本文的代码,在线免费,不需要安装任何东西。无论如何,如果你想更深入,成为 python 专家,我们推荐你安装 Anaconda 。
但首先,一些基本的概念,所以我们都在同一点上。你需要知道什么是 API,什么是 JSON。
让我们从更简单的开始:JSON 就是一种在文本中组织信息的方式,这样许多编程语言,特别是 JavaScript 和其他许多语言,都可以阅读和理解这些信息。典型的 JSON 使用 " key": “value” 格式。下面是一个 JSON 对象的例子:
{
'image': 'King.jpg',
'firstname': 'John',
'lastname': 'Snow',
'company': 'Dragons Inc.'
}
...
现在我们知道了,什么是 API?嗯,API 代表应用编程接口。我理解这些词的意思的方式是,当一些(软件)开发者制作了一个非常酷的程序/应用程序时,他们有时会认为其他开发者可能也想使用它,或者至少是它的一些部分,所以他们创建了 API——程序的一部分,你可以与之交互。简言之,API 或多或少等同于程序,但是你可以在脚本中使用它。有许多免费使用的 API,但也有许多其他的不是。
现在要开始使用谷歌 API,你必须去谷歌云平台并创建一个免费账户。这些步骤非常简单,所以我将跳过它们,但是在您完成这些步骤后,当您点击您的 Google 控制台时,您应该会看到类似以下内容:
现在,如果您点击左侧的三栏图标、API 和服务以及库,您将会看到 Google 提供的所有 API。为简单起见,我们将重点关注与谷歌地图相关的内容,但我们鼓励您探索和尝试任何其他引起您注意的内容。
一旦我们点击地图部分右侧的查看全部,我们就可以看到与谷歌地图相关的所有 API,所以让我们使用距离矩阵 API。
确保您启用了 API。如果没有,只需点击启用,你就可以走了。之后,点击文档,因为这里有你学习这个 API 如何工作所需要的所有信息。
一旦进入文档,点击左侧打开开发者指南。请注意,这些步骤对于所有的 API 都是相同的。
现在我们需要两样东西:我们必须构建的 API 键和 url 。你会在左边的三栏图标上找到你的 API 密匙、API&服务、凭证。现在让我们开始构建 url ,这有点复杂。所有的 API 的工作方式大致相同,你构建一个 url 并用你的 API 键发送它来请求一些信息,然后你捕获这些信息。需要构建 url 的方式在 API 的开发人员文档中指定。在我们的例子中,我们的 url 将如下所示:
https://maps.googleapis.com/maps/api/distancematrix/**outputFormat**?**parameters**
其中 outputFormat 需要更改为其中一个选项,要么是 json (推荐的),要么是 xml ,API 接受的参数在下面指定,在我们的例子中是我们想要获得距离的起点和目的地点,表示为latitude,longitude
,最后是指向 Maps API 实例的键参数。通常你必须构建一个 url 的字符串,用一个 & 将参数分开,但幸运的是 python 用一个requests
包覆盖了我们的背部,这个包会自动将参数添加到 url 中。所以如果你去 to Repl 粘贴下面的代码,你会得到这些点之间的距离。确保使用上一步中获得的 API 密钥来更改 API 密钥。
import json
import requestsparams = {
'key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
'origins': '40.398585,-3.683520',
'destinations': '40.419643,-3.688804'
}url ='https://maps.googleapis.com/maps/api/distancematrix/json?'response = requests.get(url,params)
print(response.status_code == 200)print(response.text)
result = json.loads(response.text)
请注意,我们改变了输出格式,在我们的例子中,我们使用了坐标,但是正如文档所指出的,还有其他的可能性。尝试将origins
和destinations
坐标更改到不同的位置,并查看输出。运行代码后,您应该会看到类似下面的内容:
{
"destination_addresses" : [ "Calle de Alfonso XII, 0, 28001 Madrid, Spain" ],
"origin_addresses" : [ "Calle de Alpedrete, 51, 28045 Madrid, Spain" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "3.0 km",
"value" : 3027
},
"duration" : {
"text" : "8 mins",
"value" : 495
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
现在让我们添加一些代码解释:第一部分导入用于获取 API 信息的 python 包,接下来我们定义 url 的参数和 url 本身,之后我们在requests
包中使用get
函数,给它 url 和参数来检索信息。我们还添加了一个检查来验证一切正常(如果代码是 200,它就是)。最后,我们打印得到的信息,并将其转换为 python 字典,这是一个与 JSON 非常相似的 python 对象,但区别在于 python 可以更容易地访问它的键。现在请注意[ ]
和{ }
在输出中的不同用法。这里我们使用方括号为一个键创建一个值列表,并用花括号嵌套那些键。
您可以尝试访问字典中的一个键。只要在控制台result['destination_addresses']
上键入,你就会得到存储在那个键里的信息(值)。
在本指南中,我们使用了 Distance Matrix API,因为它易于使用和理解,但您也可以使用其他工具来获取方向、海拔、地点信息,还有其他与谷歌分析、谷歌云架构甚至机器学习相关的工具!
我希望这篇指南能帮助你理解 API 是多么的简单易用和强大,并给你一些在未来的项目中如何组合它们的想法。如果你有任何想分享的问题或想法,请在评论中告诉我。
Python 和 Oracle 云:加载数据
使用 OCI Python SDK 和自治 DWH API,您可以轻松地为您的数据科学和 ML 工作加载数据
介绍
在 之前的文章 ,中,我探讨了我们如何使用 Python 和流行的开源框架,如 Pandas 和 scikit-learn,来分析用 Oracle 自治数据仓库(ADWC) 存储的数据。在这个简短的故事中,我想向您展示如何使用 OCI Python SDK 轻松加载大数据文件。
自动化“上了类固醇”
云的一大特点是自动化。在云世界中,更容易动态地提供资源(如 VM,甚至数据库)并使用 API 管理它们。
Oracle 云基础设施(OCI) 有许多工具,您可以在其中选择自己喜欢的工具,以自动化一大组任务(我想说:我需要的一切):
- REST API
- OCI CLI
- 软件开发工具包(Software Development Kit)
OCI 命令行界面(CLI)真的很好。但是,如果你想开发你的高度定制的工具,完美地适合你的肩膀,我推荐使用 SDK 。
正如您在文档中看到的,我们有:
- Python SDK
- Java SDK
- Ruby SDK
- Go SDK
既然我们在谈论数据科学和 ML 工程,我毫无疑问会选择 Python 。
有了 OCI Python SDK,你就有了一套完整且易于使用的类,它们都有很好的文档记录,使你能够构建 Python 脚本来自动化你日常数据工作的大部分流程。此外,您甚至可以在 Jupyter 笔记本(或 Jupyter Lab)中使用它。
因此,几天前,我从晚上的任务开始,为我的一个客户构建一些示例,展示如何从平面文件开始在 Oracle ADWC 中加载数据。然后,作为一个不错的副作用,我决定更深入地研究这个主题,并创建了一个脚本来启动/停止 VM,甚至启动/停止我的 ADWC 实例。
你可以在我的 G ithub repo 里面找到这组例子
在这个故事中,我想更详细地解释如何从平面文件开始加载数据。
安装?轻松点。
显然,有文档,但是,如果您使用 PyPi,安装只有一行代码:
pip install oci
它也适用于蟒蛇。
如果你想成为第一批尝试新特性的人,只需查看 OCI Python Github 库。
配置
然后,您需要执行一些配置任务,以确保您的工作环境和 OCI 云之间的安全通信。我会花一些时间在这里澄清,因为我不想让你在这部分浪费宝贵的时间。
首先,您需要创建一个 PEM 格式的 API 签名密钥对。您必须在您的环境(运行 Python 程序的计算机)中保持私有密钥的安全,并将公共密钥存储在您的云配置文件中。当你存储它时,你可以从云用户界面读取指纹。
更多详情可在此处找到:
[## 必需的密钥和 OCIDs
了解使用 Oracle 客户机或您自己构建的客户机时所需的键和 OCIDs。
docs.cloud.oracle.com](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm)
然后,对于每种类型的客户端(对象存储客户端、计算客户端等)。)您需要提供一组(键,值)对,打包成一个字典,以便指定:
- 您的 OCI 用户名
- 用于保护通信的密钥(API 签名密钥)
- 这把钥匙的指纹
- 您的云租户标识符
- OCI 地区
以下是您需要准备的内容示例(匿名):
config = {“user”: “ocid1.user.oc1..XXXXX”,“key_file”: “/Users/lsaetta/Progetti/xxxx/oci_api_key.pem”,“fingerprint”: “YYYYY”,“tenancy”: “ocid1.tenancy.oc1..ZZZZZZ”,“region”: “eu-frankfurt-1”}
对于用户和您的云租户,您需要使用的不是名称,而是标识符 OCID,您可以从 OCI 云控制台复制它。
在云中加载文件
此时,您已经准备好将一组文件作为对象加载到 ObjectStore 中。
这是加载单个文件的代码,我很快会添加注释:
如您所见,您需要:
- 创建客户机,在本例中是 ObjectStorageClient,并将配置字典传递给构造函数
- 以 bucket_name,file_name,file_path 为参数调用方法 put_object
仅此而已。
在 Github 资源库中,您会发现一个处理一组文件的增强版本。
将凭证存储在数据库中
现在,是时候将数据从 ObjectStore 复制到 ADWC 表中了。
首先:我们需要创建一组凭证并将它们存储在 DB 中,以便使 PL/SQL 代码能够访问 ObjectStorage Bucket。
转到 OCI 用户界面,在您的配置文件(右上方的图标和用户设置)中创建一个 AuthToken:
Authentication Token
从 UI 复制身份验证令牌。请记住在创建后立即这样做,否则,您将无法重新阅读它。
其次,使用下面的代码将云凭证存储在 DB 中;该步骤只需执行一次:
import cx_Oracleconnection = cx_Oracle.connect(USER, PWD, 'adwc5_medium')# need to create a cursor
cur = connection.cursor()statement = """
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'DEF_CRED_NAME',
username => 'adwc_user@oracle.com',
password => '<AUTH Token>'
);
END;
"""
cur.execute(statement)
注意:如果您的用户是联邦用户,那么这个名称就是完全限定的名称。它有一个前缀,如:
oracleidentitycloudservice/
并且您必须在 CREATE_CREDENTIAL 调用中指定完全限定的名称。
在 Oracle ADWC 中加载数据
因为我们现在在 ObjectStore 中有了平面文件,所以我们可以使用 PL/SQL 包 DBMS_CLOUD 来加载 ADWC 表中的数据。
好吧,这是 PL/SQL 代码,但不是很复杂,你可以很容易地剪切&粘贴。我们将把这段代码包装在 Python 代码中。
我们设想一个更简单的场景:一个用于平面文件的 Oracle 表,文件的格式与表相同(文件和表字段之间一一对应)
我们必须在数据库中创建表。例如:
CREATE TABLE CHANNELS
(channel_id char(1),
channel_desc varchar2(20),
channel_class varchar2(20)
);
/
然后,我们可以用下面的代码加载该表中一个文件中包含的数据:
import cx_Oracleconnection = cx_Oracle.connect(USER, PWD, 'adwc5_medium')# need to create a cursor
cur = connection.cursor()statement = """
BEGIN
DBMS_CLOUD.COPY_DATA(
table_name =>'CHANNELS1',
credential_name =>'DEF_CRED_NAME',
file_uri_list =>'[https://swiftobjectstorage.eu-frankfurt-1.oraclecloud.com/v1/tenant-name/BUCKET_NAME/channels1.txt'](https://swiftobjectstorage.eu-frankfurt-1.oraclecloud.com/v1/rgsbidatalake5/ADWC5/channels1.txt'),
format => json_object('delimiter' value ',')
);
END;
"""cur.execute(statement)
一个细节:要引用对象,您需要使用 SWIFT-type URL。在上面的例子中你需要改变的是:
- 地区名称(这里是 eu-frankurt-1)
- 你的房客的名字
- 对象存储中存储桶的名称
- 对象的名称(此处:channels1.txt)
正如我们所看到的,DBMS_CLOUD 包拥有所有必需的 API 来:
- 将凭证存储在数据库中
- 从对象存储复制到数据库
它还提供了其他一些不错的特性。例如,您可以使用 Apache Parquet 格式的文件,而不是 CSV。
想检查一下吗?
如果您想检查数据是否真的已经加载,您可以使用下面的代码片段:
import pandas as pd
import cx_Oracleconnection = cx_Oracle.connect(USER, PWD, 'adwc5_medium')channel1 = pd.read_sql("select * from CHANNELS1",
con=connection)# if it is a Notebook
channel1.head()
外部表
数据加载的另一个选项是在数据库中创建一个外部表,引用文件。一旦外部表开始工作,就可以使用 DML 指令将数据加载到数据库中。例如,您可以使用 CTAS:创建表作为选择。
创建外部表的过程是:
DBMS_CLOUD.CREATE_EXTERNAL_TABLE
更多详情 此处 。
结论
作为一名数据科学家,你需要与数据打交道。有时你需要自己装载。有时,您会有一个 DBA 来为您加载。
在本文中,我展示了如何使用 OCI Python SDK 来:
- 将文件加载到对象存储中
- 将数据从对象存储复制到 ADWC 表
此外,我还近距离观察了 OCI Python SDK 的强大功能。有了它,您可以创建高度定制的工具集来自动化您的日常工作。您甚至可以创建自己的 ADWC 实例,或者对其进行扩展(添加内核和存储空间)。
在以后的文章中,我将回到机器学习。差不多到了探索 OML4Py 的时候了。
还有一件事
如果你想找到更多使用 OCI Python SDK 的例子,你可以看一下这里的
Python 和 PostgreSQL:如何像数据科学家一样访问 PostgreSQL 数据库
“The PostgreSQL Pachyderm Whose Trunk Becomes the Python Python” — Image Source: “Python and PostgreSQL without ORM,” Moses Gitau (Jun 5, 2018)
有几个 Python 包可以与 SQL 数据库接口。在过去的几周里,我使用 psycopg2 模块与 PostgreSQL 数据库管理系统进行交互。您可以对从 SQL 查询中获得的数据使用 Python 库。例如,Pandas 库具有本地方法,允许我们直接从 SQL 数据库显示和操作查询结果。在本文中,我将详细介绍设置 psycopg2 和使用这些工具构建查询功能的过程。
第 1 部分:如何设置 Psycopg2
先决条件:在你尝试安装 Python 适配器之前,你必须安装 Postgres ,我在之前的帖子中详细介绍过。
Psycopg 是 Python 编程语言的 PostgreSQL 适配器。这个工具允许我们连接 Python 语言和库的功能,以获取、操作、输入和更新存储在 PostgreSQL 数据库中的数据。在撰写本文时,当前版本是 psycopg2。当我最初搜索这个包时,我被定向到该项目的 PyPI 站点。我很自然地决定使用默认的 pip 包管理系统进行安装,但是没有包括 Psycopg 的众多依赖项。根据文档,“Psycopg 是围绕 libpq PostgreSQL 客户端库的 C 包装器。”在这个标题下,包含了依赖关系。我最初试图安装这些依赖项,遇到了 StackOverflow 和该项目的 GitHub 上的用户抱怨的同样的困难。
谢天谢地,我偶然发现了一个答案,它暗示了自制软件的安装过程。虽然我已经安装了 Postgres 应用程序,但是缺少一个包含一个或多个 psycopg2 依赖项的目录。在终端中,我运行命令brew install postgresql
来安装 PostgreSQL 的自制实现,然后运行命令pip install psycopg2
来重新安装 Python 适配器。在这两个步骤完成后,我能够成功地使用 Psycopg。
第 2 部分:连接到 PostgreSQL 数据库
有几种方法可以连接到 PostgreSQL 数据库,三种方法是通过 PostgresApp/terminal/命令行直接连接,在一个 Python 脚本或文件(即 Jupyter 记事本)中连接,以及通过从初始化或配置文件导入必要的参数来连接。第三个选项最适合您希望用一个.gitignore
文件隐藏您的登录凭证的时候。
你需要一些参数来连接任何数据库。一些常见的参数是主机、端口、用户名和密码。PostgreSQL 数据库既可以存储在您的计算机上(使用 localhost 作为 host 参数的值进行访问),也可以远程存储(使用服务器的IP 地址作为 host 参数的值进行访问)。您还需要一个端口号,它定义了客户端计算机的请求应该发送到的服务器上运行的进程。PostgreSQL 默认的端口是 5432 ,虽然这是可以更改的。如果有安全权限,您可能还需要用户名和密码;这在工作场所很常见,因此用户不会访问或更新他们无权访问的信息。
The attendance scene from “Ferris Bueller’s Day Off” (1986). Ferris Bueller remotely updates his attendance record which is stored in a database on his school’s server. Either Bueller stole the login information of a user who has the necessary permissions to update his record or the server allowed access to any client computer.
(1)直接连接 PostgresApp/Terminal/命令行
PostgreSQL when opened for the first time. Note the plus (+) symbol on the bottom left corner of the image.
PostgresApp 允许您通过使用位于窗口左下角的加号( + )进入创建新服务器菜单,直接连接到本地或远程存储的数据库。您还可以单击可用的数据库,在新的终端窗口中启动 PostgreSQL shell,但必须已经使用了 initialize 或 start 按钮。
您也可以通过命令行或终端访问服务器。如果您打开一个新的终端窗口(如果应用程序正在运行,则在 PostgreSQL shell 之外),您可以键入命令来启动 PostgreSQL,后跟数据库的参数。要启动 PostgreSQL,如果设置了快捷方式,请键入/Applications/Postgres.app/Contents/Versions/12/bin/psql
或psql
。在同一行中,您可以键入额外的参数,如主机-h localhost
(其中 localhost 可以替换为服务器 IP 地址)、端口-p 5432
、用户名-U username
、数据库名称-d database_name
以及密码(如果需要的话)-W password
(您可以省略它,或者键入小写版本-w
以表示没有密码)。终端中完整的连接请求如下所示:
psql -h localhost -p 5432 -U username -W password -d database_name
成功的连接命令将打开 PostgreSQL shell,并指示数据库已被访问。
(2)在一个文件中直接连接
当安全性不成问题时,您可以在一个 Python 脚本或 Jupyter 笔记本中练习连接到本地数据库。首先导入 psycopg2 库,然后使用**。connect()** 方法来传递相关参数。最后,创建一个 cursor 对象来对数据库运行 PostgreSQL 命令。这个过程的代码片段如下:
A sample connection to a PostgreSQL database within one file.
上面的代码片段连接到一个名为“suppliers”的本地数据库,并查询“vendors”表的所有内容。用户名和密码是“postgres”,任何有权访问该脚本的人都可以清楚地看到。如果使用默认的 PostgreSQL 端口 5432,则 port 参数不是必需的,我包含它是为了显示常规格式。在我查询了“vendors”表中的所有数据后,我关闭了光标和连接来释放服务器的带宽资源。
(3)连接配置和初始化文件
在专业环境中,服务器有许多保护措施,包括每个员工的个人用户名和密码。每个用户帐户都将拥有自定义权限,这些权限将决定他们可以访问和更新哪些信息。如果您出于协作目的在 GitHub 上托管这些信息,您会希望通过将它们存储在一个单独的文件中来对您的登录凭证保密。这就是.ini
文件发挥作用的地方。我将跟随 PostgreSQLTutorial.com 的教程学习这种方法。
总体思路是 Python 脚本/Jupyter 笔记本文件将导入初始化文件的凭证。只有保护作者登录凭证的 Python 脚本才会被共享。将有第三个文件以 psycopg2 可以解释的方式解析存储在初始化文件中的参数。database.ini
初始化文件的内容有:
The contents of the file database.ini
初始化文件的参数可以在一个单独的文件中解析,也可以在我们打算用来操作数据的主文件中解析。单独的文件是更好的选择,因为我们不希望每次进行 PostgreSQL 查询时都复制和粘贴大量代码。文件config.py
接收来自初始化文件的数据,并返回一个参数字典,其中键是参数名(上面的蓝色文本),值是实际的参数值(上面的绿色文本):
{‘host’: ‘localhost’, ‘database’: ‘suppliers’, ‘user’: ‘postgres’, ‘password’: ‘postgres’}
config.py
文件改编自PostgreSQLTutorial.com站点,并利用了 Python 的 ConfigParser() 类:
The config.py file that will be imported in the main Python script or Jupyter Notebook. The function takes in the contents of the initialization file and returns a dictionary of parameters.
导入和利用这两个文件的主要 Python 脚本包含在下面的要点中。database.ini
文件将包含在.gitignore
文件中,以保护作者的密码。
第 3 部分:使用 Python 操作 PostgreSQL 数据
一旦连接到 PostgreSQL 数据库,就可以查询分析所需的数据。查询结果可以显示在 Pandas 数据框中,然后可以像 Pandas 中存储的所有数据一样对其进行操作。Pandas 有一些方法,比如[.read_sql_query()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_sql_query.html)
,允许我们通过 psycopg2 连接提取 PostgreSQL 存储的数据。以下 Python 脚本使用database.ini
和config.py
文件连接到“供应商”数据库,查询“供应商”表的内容,并使用函数 create_pandas_table: 在 Pandas 数据框中显示结果
A Python script that connects to a PostgreSQL database with an initialization and configuration file, and utilizes Pandas to query data and create a data frame.
The Pandas data frame with the contents of the “vendors” table.
结论
一旦将数据从 PostgreSQL 数据库导入 Python 脚本或 Jupyter 笔记本,您就能够应用强大的数据科学工具来进行分析并构建机器学习模型。您可以使用单独的初始化、配置和.gitignore
文件来保护您的登录凭证。Pandas 库包含一些方法,允许我们直接从数据库中查询结果。本文中描述的整个过程可以被容器化和共享。
Python 和 R 的数据争论:并排比较 Pandas 和 Tidyverse 代码,并学习加速技巧。
成为双语数据科学家。学习加速代码技巧。用可互操作的 Python 和 R cells 编写双语笔记本。
© Artur/AdobeStock
几年前,你会专门用这两种语言中的一种来编写数据分析程序:Python 或 r。这两种语言都提供了从数据探索到建模的强大功能,并且拥有非常忠实的粉丝。然而,事情已经发生了变化。如今,有一些库,如 reticulate 和 *PypeR、*允许你分别将 Python 代码合并到 R Markdown 和 Jupyter 笔记本中。了解两种语言的基本功能,如数据争论,可以扩展您的编程视野,允许您与使用任一种语言的人一起工作,并创建双语笔记本,充分利用每种语言的优势。在本文中,我们将分别使用 pandas 和 tidyverse 库来讨论 Python 和 R 中的数据争论,以及加速代码的技巧。读完这篇文章后,你会发现 Python 和 R,在许多表达式上非常相似,至少在数据争论方面是如此。所以,你只要额外付出一点努力,就能掌握两种语言的数据角力,成为“超级 R -Pythonista”!
做一个超级——T21——巨蟒(而不仅仅是一个巨蟒!)
双语 R 降价文件
他的文章附有一个 R Markdown 文件,你可以在 github 上找到。 在这个文件中,数据角力操作实现了两次:在 Python 和 R 单元格中,彼此相邻。这可以通过导入 reticulate 库来实现。Python 和 R 单元目前独立工作;在我的下一篇文章中,我将展示 Python 和 R 单元之间的参数传递以及跨语言通信。
R Markdown 文件也可以作为 Python 和 R 数据争论操作的两个独立的备忘单。您也可以下载 R Markdown 文件的编织版本。两种语言的数据争论是在相似的结构上进行的:R 数据帧和 Python 数据帧。具体实现的操作有:
A.创建/读取数据帧。
B.总结。
C.使用索引、名称、逻辑条件、正则表达式选择行、列、元素。将介绍 Python 和 R 中的 filter() 函数。
D.删除-添加行、列。我们将讨论 R 中的 mutate() 函数和 Python 中的 map 。
E.对行/列应用函数,包括 Python 中的 l ambda 函数。
F.加速代码。我们将讨论一些技术,比如并行化和用于代码加速的函数编译。
数据争论操作
在前面提到的 R Markdown 文件中,Python 代码被括在下面的括号中,这些括号定义了一个 Python 单元格:
`{python}
虽然 R 代码包含在这些括号中:
` ` `{r}
这些括号由 RStudio 自动生成,点击插入选项卡并选择您想要的语言。
编程提示:在执行 R Markdown 中的任何 Python 单元之前,执行导入 reticulate 库的 shell。注意,在同一个单元格中,我们指示 RStudio 使用哪个 Python。另外,使用命令 py_config()在 RStudio 控制台中配置 Python 也是一个好主意。
值得注意的是,在这两种语言中,有多种方式来执行操作,其中许多在前面提到的 R Markdown 文件中有所介绍。由于篇幅所限,在本文中,我们将只介绍其中的一部分。让我们开始吧:
从 CSV 文件中读取数据帧
正如我们在下面的要点中看到的,在两种语言中,我们都调用一个读取 csv 文件的函数。在 Python 中,这个函数是通过 pandas 库调用的。 heart.csv 文件来自 Kaggle 和 UCI 库。
在下面的 Python 代码中值得注意的是使用了一个 lambda 函数(一个匿名内联函数)来排除读取 drop_col 列表中定义的列。
**编程提示:**在 R 中定义 read.csv() 函数的编码是一个好主意,如下所示,以确保正确读取所有列名。当我不使用编码时,第一列的名称被读错了。我不需要用 Python 定义编码。
从头开始创建数据框架
正如下面的所示,在这两种语言中,一个数据帧可以从一个低阶结构中创建,分别用于 Python 和 R 的矩阵和数组。
在 R 部分中,存款帧 数据帧包含 3 个人的银行存款(单位:千)。使用 rnorm() 函数生成银行存款,该函数生成 6 个随机数,平均值为 12,标准差为 3。
**编程技巧:**正如你在下面的 R 代码中注意到的,我们导入了 tidyverse 库,这是一个包含很多包的库,比如 dplyr 。我们在 R 代码段中需要的函数只在 dplyr 库中定义。那么为什么要进口 tidyverse,而不是我们刚需的 dplyr 呢?一个原因是未来的可扩展性(我们可能需要使用其他包中的函数)。另一个原因是当我们导入库(dplyr) 时,得到一个警告,它的重要函数 filter() 被另一个库屏蔽了。如果我们导入库(tidyverse) ,就没有这个问题了。
摘要
H 在这里,我们将检查两种类型的汇总:(a)汇总关于数据帧的基本信息的函数。(b)允许对数据切片进行分组和定制洞察的功能。
描述数据帧一般信息的函数
在以下要点中,在 R 部分, head() 函数显示了数据帧的前几行(观察值)。 glimpse() 函数显示观察值的数量、变量(列)以及后者的类型、名称和值。与 glimpse() 功能类似的信息由 str() 功能显示。一个更有用的函数是来自 prettyR 包的 describe() 函数,它显示每个变量的基本统计数据和有效案例数。变量统计信息也由 summary() 函数显示。与 R 类似,在 Python 部分中, head() 函数显示第一行,而 describe() 函数显示每一列的基本统计信息,比如平均值、最小值和最大值。
分组和汇总组内的信息
R 和 Python 都有基于一个变量或一组变量进行分组的函数。如以下要点所示,在 R 中,我们可以使用以 R 为基数的函数 tapply() ,分别计算男性和女性的平均胆固醇。或者,我们可以使用函数 group_by() ,后跟汇总函数,如 count() 、 mean() 或summary _ all()。类似地,如下图所示,在 Python 中,组总结是由函数 groupby() 执行的,后面是总结函数,如 count()。
分组的另一个例子,在 R:
Python 中分组汇总的另一个示例:
基于索引的行、列、元素选择
这里需要注意的一点是,R 中的索引从 1 开始,而 Python 中的索引从 0 开始。在 Python 中,我们使用 iloc 索引器来访问整数位置。
使用名称、正则表达式、逻辑条件进行列/行选择
这里有一些需要注意的亮点:
- 在 R 中使用 % > % 管道操作符,它允许你编写简洁的功能代码。
- 使用 R 中的 select() 函数选择列,使用列名、正则表达式和/或逻辑表达式。例如,在第 7、8 行中,select() 语句用于选择包含字母 m 的所有列,它们的 max() 小于 12。
- 函数 filter() ,这是在 r 中进行选择的另一种方法。下面的函数 filter_all() 允许我们选择满足标准的所有行。
- Python 提供了类似的 filter() 函数供选择。axis 参数指定操作是应用于列还是行。
行/列删除和添加
B elow,值得注意的有以下几点:
- 在 R 中,对列名使用减号操作符来执行列删除。我们也可以使用字符串匹配函数,比如 starts_with() ,如下图所示。其他类似的函数有
ends_with(),matches(),contains()。 - 在 R 中,只需使用列名就可以添加列(下面的列 Brandon )。另一种流行的方法是来自 dplyr 库中的 mutate() 函数。这里,我们使用 mutate() 添加一个列 sumdep ,其中这个新列是两个现有列的总和。请注意与 t ransmute() 函数的区别,它只添加新列(不保留旧列)。如下图所示,使用 mutate() 的一个特别有趣的方法是将它与 group by 结合起来,在组内进行计算。
- 在 Python 部分,值得注意的是添加了一个使用逻辑的列,该逻辑是通过 map() 函数实现的。
对列/行应用函数
BPython 和 R 都提供了 apply() 函数,允许我们根据一个额外的参数在行或列上实现一个函数。例如下面,在 R 中,如果中间的参数是 2,则函数应用于列,而如果是 1,则应用于行。在 Python 中, apply() 函数的决定参数是 axis (0,应用于列,1,应用于行)。下面另一个有趣的花絮是使用一个 lambda 函数将所有元素乘以 5。
加速考虑
在这里,我们将简要讨论三种加速 R 中代码的方法: data.table 、并行化和函数编译。对于 Python,将呈现的加速选项是 modin 。
©Syda Productions/AdobeStock
r:数据表
数据表是数据帧【2】的扩展,其优点有两方面:
(a)对于大文件,加载数据比数据帧快得多。下面是一个例子。我读取一个大文件(66.9MB),使用函数 read.csv(),返回一个数据帧,以及 fread(),返回一个数据表。差异非常显著(例如,对于 data.table,用户+系统时间大约快了 30 倍!)。我使用的数据文件的引用是 references 部分中的[3]。
(b)简洁、紧凑的过滤表达式,其执行速度也相当快。使用数据表进行过滤以及与 dplyr 过滤进行比较的示例如下所示。在这个要点中,我们使用库 dplyr 的 filter() 计算胆固醇> 280 的男性的平均年龄。我们也用数据表计算它,这是用在一行简洁的代码中完成的。
r:并行
在 R 中,并行化是使用并行库[4]实现的,这允许我们的 R 程序利用我们计算机中的所有内核。我们可以使用函数 detectCores() 来找出我们有多少个内核,然后我们可以使用函数 makeCluster() 来创建一个包含这些内核的集群。这显示在下面的要点中。然后,我们可以使用 apply() 系列函数的并行版本来执行各种操作。例如,在下面的要点中, sapply() 函数及其并行版本 parSapply() 用于对大量数字求平方。我们可以看到, parSapply() 的用户+系统时间是 7.95+0.66=8.61,而 plain apply()的用户+系统时间是 11.80+0.03=11.83。
r:函数编译
另一种提高 R 语言运算速度的方法是编译函数。这是通过编译器库及其 cmpfun() 函数【5】实现的。下面的要点显示了这一点,以及并行化、编译在时间消耗方面的比较。我们看到,当我们结合并行化和编译时,实现了最快的用户+系统时间(7.73)。就其本身而言,只实现的并行化比只实现的函数编译(8.87)产生更快的用户+系统时间(8.61)。
结束我们对超速 R 的讨论,值得一提的是库gpuR【6】*。*使用 ViennaCL 库, gpuR 允许在任何 GPU 上并行计算,这与之前的 R 包在后端依赖 NVIDIA CUDA 形成对比。
Python:摩丁
如[7]中所述,modin 是一个数据框架库,具有与 pandas 完全相同的 API,并允许显著加速工作流(在 8 核机器上快 4 倍)。要使用它,我们只需要修改一行代码。而不是:
进口熊猫作为 pd 我们将使用:
导入 modin.pandas 作为 pd
一句忠告。modin 是建立在 Ray 之上的,所以要确保你有正确版本的 Ray。
你可以在我的 github 库中找到一个额外的赠品是另一个双语 R Markdown 文件,它实现了数组创建(1-D 和 2-D)和使用数组的数学函数(点积、特征值等)。)都有 Python 和 r .你也可以下载它的针织版。
感谢阅读!
参考
- Pandey,p .,**从 R vs. Python,到 R 和 Python,**https://towardsdatascience . com/From-R-vs-Python-to-R-and-Python-aa 25 db 33 ce 17
- 数据表简介,https://cran . r-project . org/web/packages/data . table/vignettes/datatable-intro . html
- MITx 和 HarvardX,2014 年,“HMX PC 13 _ DI _ v2 _ 5–14–14 . CSV”, HarvardX-MITx 个人课程 2013 学年 De-Identified 数据集,v 版本 2.0 ,https://doi.org/10.7910/DVN/26147/OCLJIV,哈佛数据世界,V10
- 特雷德韦、并行运行 R 代码、https://www.r-bloggers.com/running-r-code-in-parallel/
- 罗斯,n .快一点!更高!更强!-忙人加速 R 码指南,https://www . R-bloggers . com/faster-higher-stonger-A-Guide-to-Speeding-Up-R-Code-for-Busy-People/
- 包 gpuR ,https://cran.r-project.org/web/packages/gpuR/gpuR.pdf
- Pandey,p .,用 Modin 获得更快的熊猫,甚至在你的笔记本电脑上,https://towards data science . com/Get-faster-pandas-with-Modin-even-on-your-laptops-b 527 a2 eeda 74
Python 和 R——数据科学的明确拥护者
Python 和 R 仍然是数据科学中最顶尖的两种编程语言
数据科学是一个非常广阔的领域,包括几个细分领域,如数据工程、数据准备和转换、数据可视化、机器学习和深度学习。
虽然做数据科学需要几项技能( 数据科学最低要求:开始做数据科学需要知道的 10 项基本技能 ),但数据科学需要的两项最基本的要求是:
A)扎实的数学背景
b)编程技能
本文将讨论从事数据科学所需的基本编程语言。需要的必备数学技能,请看下面: 机器学习必备数学技能 。
数据科学中使用的编程语言
如果你从诸如indeed.com或 **LinkedIn、**等平台上的数据科学家招聘广告中取样,你会对数据科学招聘广告中提到的技术技能有所了解。数据科学家招聘广告中提到的一些技术技能(编程语言)包括:
- Python
- R
- Matlab
- Hadoop
- SAS
- SQL
- 画面
- Excel
- 电源毕
- AWS
- 蔚蓝色
- Java
- 朱丽亚
- Scala
数据科学家招聘广告中提到了各种各样的技能,每个对学习数据科学基础感兴趣的初学者都会很自然地问自己:
应该重点学习什么编程语言?
如果你有兴趣学习数据科学的基础知识,你需要从某个地方开始。不要被数据科学家招聘广告中提到的一系列荒谬的编程语言所淹没。虽然学习尽可能多的数据科学工具很重要,但建议从一两种编程语言开始。一旦你在数据科学方面建立了坚实的背景,你就可以挑战自己,学习不同的编程语言或不同的平台和生产力工具,以增强你的技能。
作为数据科学初学者,你应该关注的编程语言
根据这篇文章( 数据科学家最需要的技术技能 ),当谈到编程语言时,Python 和 R 仍然是数据科学的明确冠军。
作为初学者,可以从一种编程语言开始,比如 Python,然后再学习 R,或者可以同时学习两种语言。
好的一面是,你可以从数据科学培训课程中学到 Python 和 R 的技能。大多数数据科学培训项目通常从编程基础开始。因此,如果要使用 R 来教授数据科学专业,他们通常会从 R 基础或 Python 基础等课程开始,如果该专业是使用 Python 来教授的话。
因此,如果你有一些基本的编程背景,你实际上可以通过在线课程自学数据科学。开始数据科学之旅并不需要 Python 或 R 编程方面的高深知识。您将在整个培训过程中学习和掌握这些语言,完成家庭作业,阅读书籍,以及利用大量在线资源提供 R 和 Python 编程帮助。
如果您对可以让您开始学习 R 或 Python 基本编程课程的数据科学专业感兴趣,这里有两个我最喜欢的数据科学专业,它们将教您如何使用 Python 和 R 学习数据科学(对于那些以前接触过基本编程的人):
(一)数据科学专业证书(HarvardX,通过 edX):https://www.edx.org/professional…
包括以下课程,全部使用 R 教授(您可以免费旁听课程或购买认证证书):
- 数据科学:R 基础;
- 数据科学:可视化;
- 数据科学:概率;
- 数据科学:推理和建模;
- 数据科学:生产力工具;
- 数据科学:扯皮;
- 数据科学:线性回归;
- 数据科学:机器学习;
- 数据科学:顶点
(ii) 应用数据科学与 Python 专业化(密歇根大学,通过 Coursera):https://www.coursera.org/special…
包括以下课程,全部使用 Python 教授(您可以免费旁听大多数课程,有些课程需要购买认证证书):
- Python 中的数据科学导论;
- 应用 Python 绘图、制图和数据表示;
- Python 中的应用机器学习;
- Python 中文本挖掘的应用:
- Python 中的应用社会网络分析。
总之, Python 和 R 仍然是数据科学中最顶尖的两种编程语言。以我个人的经验,我使用 Python 进行机器学习应用,而我发现 R 对于统计分析非常有用。基本上,用 Python 可以做的一切也可以用 R 实现。学习如何用 Python 和 R 来做数据科学是值得的,因为这将有助于增加你获得数据科学家工作的机会,因为这些语言是大多数数据科学招聘广告中提到的前两种语言。
Python 和 WSL
在 Windows 和 Linux 上获得更好的 Python 体验。
我最近写了一篇简短的介绍性文章,介绍优步的 H3 地理空间索引算法。为了说明 H3 背后的思想,我使用了公开可用的 Python API。和大多数 Python 代码库一样,这是以包的形式提供的,包是 Python 代码重用的通用语言。您可以使用专门的工具来安装和管理这些软件包。对于常规的 Python 发行版,这个工具是 PIP,通常工作得很好,尤其是如果你是使用 Windows 机器的而不是。
在过去 12 个月的大部分时间里,我一直在使用高端 MacBook Pro,安装和管理 PIP 软件包已经变得轻而易举。这种体验与我之前使用 Windows 的体验形成了鲜明对比。然后,失败率很高,特别是带有需要在包安装期间编译的 C 或 C++代码的包。对于这些软件包,几乎总是有正确的解决方案:克里斯托夫·高尔克的网页。在这里,您可以找到各种预打包的" wheel "文件,它们在安装过程中不需要使用编译器。别人已经替你做了家务。您下载“ wheel ”文件,并使用您忠实的 PIP 安装它。上面的樱桃是您可以选择的选项,从 Python 版本、处理器类型,甚至编译选项。无处不在的 NumPy 包就是这种情况,它有普通版本和 MKL 版本。我从未能在我的 Mac 电脑上安装支持 MKL 的 NumPy,所以 Windows 用户在这里能得到更好的服务。问题在于像 H3 这样的特色套餐。除非他们出名,否则你很可能在 Christoph 的页面上找不到他们。如果你在那里看不到它们,很可能你在任何地方也找不到它们。
这就是我的经历,在发表了 H3 的文章后,我决定在我的侏罗纪 Windows 10 盒子上试试。我按照指示使用 PIP 安装了 H3 软件包,但是问题马上就出现了。在我的特殊例子中,CMake 工具的明显缺失使得在安装了之后仍然存在。我知道我在做什么,所以我立即放弃了。解决这些问题通常需要安装一个模糊版本的 Microsoft C++编译器,确保它出现在 PATH 变量中,等等。我钦佩那些有技能和耐心配置他们的 Windows 机器来干净地编译这些包的人。不幸的是,我不属于那个群体。
当我正在考虑放弃这个的时候,我记得读过一些关于在 Windows 上运行 Tensorflow 的文章。这篇博客帖子来自斯科特·汉瑟曼,标题是“ 在 Windows 上玩张量流。”这段文字可以追溯到 2016 年,当时 Tensorflow 甚至无法在 Windows PC 上编译。作者是如何设法绕过它的?他用了 WSL。
输入 WSL
WSL 代表“ Windows 子系统 for Linux ,”,它允许您在 Windows 系统中运行 Linux 系统,而无需虚拟机。当斯科特写下他著名的博客文章时,它还处于测试阶段。现在 WSL 功能齐全,并且已经有了工具支持。在我们进入所有这些好东西之前,让我解释一下我是如何让 H3 代码运行的。
首先,您必须启用 WSL ,然后从微软商店安装一个 Linux 发行版。我选择了 Ubuntu 18,但是你可以在读到这篇文章的时候选择任何可用的版本。请理解,你很可能会得到一个操作系统的裸机版本,所以你应该准备安装很多辅助工具,比如 PIP 本身。Ubuntu 18 已经安装了 Python 3.6.7,所以这似乎是正确的选择。
使用命令行工具从 GitHub 下载代码轻而易举。完成后,我试图创建一个虚拟环境。不幸的是,VENV 包不可用,所以我必须安装它。Ubuntu 帮助了我,告诉我应该发出什么命令,我又回到了我的路上。除了意外缺少“轮子”包之外,设置虚拟环境太容易了。在等待老 CPU 咀嚼安装程序列表后,我准备好了。我启动了 Jupyter Lab 命令,得到了一个 URL 作为回答。将 URL 复制到 Windows 浏览器,你瞧!我的浏览器上有一个 Jupyter 笔记本!
WSL 1 与 Windows 共享相同的基础结构。它通过在 Windows 之上创建一个 Linux 翻译层来发挥其魔力。Linux 应用程序使用操作系统的资源,就好像它们运行在真实的 Linux 机器上一样,不管是真实的还是虚拟的。IP 地址是相同的,这就是为什么您可以在 WSL 上启动 web 服务器,并在 Windows 上使用它,而不需要任何网络攻击。
刀架
到目前为止,我很想说你正在体验两个世界的精华。但是有一个问题。你能用 WSL 使用你最喜欢的 IDE 吗?我寻求这个问题的答案,并感到惊喜。
Visual Studio Code 最近发布了一个插件,它允许你在 WSL 盒子上编辑、调试和运行 Python 代码。用户界面仍然在 Windows 上,但是 Python 代码和解释器在 WSL 上。在撰写本文时,该插件仍处于测试阶段,但可以像宣传的那样工作。
PyCharm 也支持基于 WSL 的开发,尽管只是在付费版本上。
不幸的是,没有 CUDA 支持,尽管有计划在未来的版本中加入。对于深度学习项目来说,这将是一个很好的补充。
结论
这是治疗 Windows 疾病的灵丹妙药吗?虽然肯定不是一个完整的解决方案,但微软正朝着正确的方向前进。WSL 的某些方面必须改进,比如 WSL 不运行时对文件系统的远程访问,以及对深度学习人群的 CUDA 支持。无论如何,我想说这为在 Windows 平台上获得更好的数据科学体验打开了一扇门。这应该值得你去做。
笔记
[1]WSL 的第二版将使用一个精简的轻量级虚拟机。
对 WSL 如何工作的描述是我对版本 1 的理解。如果你想更详细地了解这个漂亮软件的工作原理,请参考更权威的资料。
[## joo Paulo Figueira-数据科学家- tb.lx by 戴姆勒卡车和公共汽车| LinkedIn
查看 joo Paulo Figueira 在全球最大的职业社区 LinkedIn 上的个人资料。圣保罗列出了 1 份工作…
www.linkedin.com](https://www.linkedin.com/in/joao-paulo-figueira/)
Python 基础
Python 编程基础
此处涵盖的主题—
- 变量
- 数据类型
- 铅字铸造
- 公式
- 字符串操作
用 Python 向世界问好:
print('Hello, World!')*Output:* Hello, World!
我们用的是什么版本的 Python?
import sys
print(sys.version)*Output:* 3.7.3 (default, Aug 20 2019, 17:04:43)
[GCC 8.3.0]
变量:
我们可以在变量中存储任何值(数字、单词),以便以后使用。例如:
x = 5
print(x)*Output:* 5
这里我们用赋值操作符“=”给变量“x”赋值 5。
所以 x 的值是 5。
x += x
print(x)*Output:* 10
使用x+=x
命令,我们正在执行x+x.
这里,5+5 = 10
。
所以,
x+=x
代表x+x
x-=x
代表x-x
x*=x
代表x*x
x/=x
代表x/x
y = 2 + 3
print(y)*Output:* 5
在这里,我们使用“y”变量在 2 和 3 之间分配了一个求和运算。
x += y
print(x)*Output:* 15
这里我们添加了两个不同的变量‘x’和‘y’。
z = x+y
print(z)*Output:* 20
这里,我们将两个不同变量(’ x ‘,’ y ‘)相加的值存储在一个不同的变量(’ z ')中。
z *= z
print(z)*Output:* 400
Python 中的数据类型:
Python 中主要有 3 种数据类型
- 字,即众所周知的“字符串”
- 布尔型(真或假)
- 数字
数字也有两种类型
- 整数
- 浮动
所以,总的来说有三种数据类型-
- 线
- 布尔代数学体系的
- 整数
- 浮动
整数:-
这里有一些整数的例子。整数可以是负数或正数:
integer_data = 12
type(integer_data)*Output:* int
这告诉我们 12 是一个整型对象。使用type
命令,我们可以看到任何给定输入或输出的数据类型。
浮动:-
浮点数代表实数;它们是整数的超集,但也包括“带小数的数”。当涉及到表示实数的机器时有一些限制,但是浮点数在大多数情况下是一种很好的表示。
float_data = 2.14
type(float_data)*Output:* float
这告诉我们 2.14 是一个浮点类型的对象。
字符串:-
Python 中的字符串可以用单引号、双引号甚至三引号来创建。
string = 'python'
type(string)*Output:* str
这告诉我们‘python’是一个字符串类型的对象。
string_integer = '10'
type(string_integer)*Output:* str
这告诉我们’ 10 '是一个字符串类型的对象。
string_float = '10.01'
type(string_integer)*Output:* str
这告诉我们‘10.01’是一个字符串类型的对象。
布尔:-
布尔方法用于使用标准的真值测试过程返回或转换一个值为布尔值,即真或假。
boolean_true = True
type(boolean_true)*Output:* bool
这告诉我们 True 是一个布尔类型的对象。
boolean_false = False
type(boolean_false)*Output:* bool
这告诉我们 False 是一个布尔类型的对象。
类型转换:
从一种对象类型转换为另一种对象类型的过程。
将整数转换为浮点数:-
print("Integer data before typecasting: ", integer_data)
print("Datatype before typecasting: ", type(integer_data))
integer_data = float(integer_data)
print("Datatype after typecasting: ", type(integer_data))
print("Integer data after typecasting: ",integer_data)*Output:* Integer data before typecasting: 12
Datatype before typecasting: <class 'int'>
Datatype after typecasting: <class 'float'>
Integer data after typecasting: 12.0
之前,我们已经看到 12 是一个整数类型的对象。现在,如果我们写float(12)
,这意味着我们给出了将 12 的数据类型从整数转换为浮点的命令。
所以 12 的数据类型现在是 float。
所以这里最初integer_data
变量的数据类型是int
并且值是 12 &在执行类型转换之后integer_data
的数据类型变成了float
并且值变成了 12.0。
将浮点数转换为整数:
print("Float data before typecasting: ",float_data)
print("Datatype before typecasting: ", type(float_data))
float_data = int(float_data)
print("Datatype after typecasting: ", type(float_data))
print("Float data after typecasting: ",float_data)*Output:* Float data before typecasting: 2.14
Datatype before typecasting: <class 'float'>
Datatype after typecasting: <class 'int'>
Float data after typecasting: 2
在这里我们可以看到,在应用了从浮点到整数的类型转换之后,float_data
变量的值从 2.14 变成了 2。所以我们丢失了一些数据。
因此,在执行从浮点数到整数的类型转换时,我们可能会丢失一些数据。
将字符串转换为数字:
print("String data before typecasting: ", string_integer)
print("Datatype before typecasting: ", type(string_integer))
string_integer = int(string_integer)
print("Datatype after typecasting: ", type(string_integer))
print("String data after typecasting: ",string_integer)*Output:* Float data before typecasting: 10
Datatype before typecasting: <class 'str'>
Datatype after typecasting: <class 'int'>
Float data after typecasting: 10
将布尔值转换为整数:
print("String data before typecasting: " + str(boolean_true))
print("Datatype before typecasting: ", type(boolean_true))
boolean_true = int(boolean_true)
print("Datatype after typecasting: ", type(boolean_true))
print("String data after typecasting: ",boolean_true)*Output:* String data before typecasting: True
Datatype before typecasting: <class 'bool'>
Datatype after typecasting: <class 'int'>
String data after typecasting: 1
在这种情况下,如果布尔值为真,那么它的整数形式将是 1,如果布尔值为假,那么它的整数形式将是 0。
表情:
Python 中的表达式可以包括兼容类型(例如整数和浮点)之间的运算。例如,像将多个数字相加这样的基本算术运算:
执行加法:-
add = 43 + 60 + 16 + 41
print(add)*Output:* 160
执行减法:-
subtract = 50-60
print(subtract)*Output:* -10
执行乘法:-
multiply = 5*5
print(multiply)*Output:* 25
表演部分:-
division_float = 25/5
print(division_float)
type(division_float)*Output:* 5.0
float
这里division
变量的数据类型是 float。
对于 Python 3 中的除法,除法的结果总是以浮点数据类型的形式出现。
division_int = 25//5
print(division_int)
type(division_int)*Output:* 5
int
为了将除法的结果从浮点数转换为整数,我们可以在除法运算时使用//
而不是/
。
执行电源操作:-
power = 5**2
print(power)*Output:* 25
字符串操作:
什么是字符串?
以下示例显示了包含在两个引号内的字符串:
'Michael Jackson'
'1 2 3 4 5 6 '
'@#2_#]&*^%$'
字符串可以由单词、数字和特殊字符组成。
索引:
现在假设我们将一个名为“Michael Jackson”的字符串赋给一个名为“name”的变量。
Name = "Michael Jackson"
索引有助于将字符串视为有序序列。可以使用由数字数组表示的索引来访问序列中的每个元素:
print(Name[0])
print(Name[14])*Output:* M
n
这里我们打印字符串的第一个和最后一个元素。
len("Michael Jackson")*Output:* 15
这里我们使用len
来查找字符串中的字符数。
切片:
我们可以使用切片从一个字符串中获得多个字符,我们可以获得第 0 到第 4 和第 8 到第 12 个元素:
print(Name[0:4])
print(Name[8:12])*Output:* Mich
Jack
步幅:
我们也可以如下输入一个步幅值,“2”表示我们每隔一秒选择一个变量:
print(Name[::2])*Output:* McalJcsn
连接字符串:
我们可以使用加法符号连接或组合字符串,结果是两者组合成一个新字符串:
Statement = Name + "is the best"
print(Statement)*Output:* Michael Jacksonis the best
要复制一个字符串的值,我们只需将该字符串乘以我们想要复制它的次数。在这种情况下,数量是三。结果是一个新字符串,这个新字符串由原始字符串的三个副本组成:
3 * 'Michael Jackson'*Output:* 'Michael JacksonMichael JacksonMichael Jackson'
转义序列:
反斜杠代表转义序列的开始。转义序列表示可能难以输入的字符串。例如,反斜杠“n”代表一个新行。遇到反斜杠“n”后,输出由新行给出:
print(" Michael Jackson \n is the best" )*Output:* Michael Jackson
is the best
类似地,反斜杠“t”代表制表符:
print(" Michael Jackson \t is the best" )*Output:* Michael Jackson is the best
我们可以在字符串前放置一个“r”来显示反斜杠:
print(r"Michael Jackson \ is the best" )*Output:* Michael Jackson \ is the best
操作:
Python 中有许多字符串操作方法可用于操作数据。我们将对数据使用一些基本的字符串操作。
我们用方法upper
试试吧;此方法将小写字符转换为大写字符:
A = "Thriller is the sixth studio album"
print("Before upper:", A)
B = A.upper()
print("After upper:", B)*Output:* Before upper: Thriller is the sixth studio album
After upper: THRILLER IS THE SIXTH STUDIO ALBUM
方法replace
用新的字符串替换字符串的一部分,即子字符串。我们输入想要改变的字符串部分。第二个参数是我们希望用来交换该段的内容,结果是一个段已更改的新字符串:
A = "Michael Jackson is the best"
B = A.replace('Michael', 'Janet')
print(B)*Output:* Janet Jackson is the best
方法find
找到一个子字符串。参数是要查找的子字符串,输出是序列的第一个索引。我们可以找到副弦jack
或者el.
Name = "Michael Jackson"
Name.find('el')*Output:
5*
Python 基础:函数
Source: https://bit.ly/2EhK47P
读完这篇文章你会知道:
- 什么是功能以及如何定义它们
- 什么是参数和自变量
- 如何从函数中返回值
- 如何定义函数文档
- Python 中的范围代表什么
- 什么是关键字参数
- 灵活和默认参数
- 什么是 Python 异常以及如何处理以及如何引发它们
- 断言语句
介绍
功能是一段有组织的可重用代码解决一个特定任务。函数帮助我们保持代码的整洁,并为我们提供代码重用的能力。
内置函数
Python 有几个内置函数,它们总是可用。其中一些功能是 打印 和 最大 。让我们看一些如何使用它们的例子。
- 打印功能接受对象并打印它们
输出:
Python
chess backgammon
- max 函数接受一个可迭代并返回最大的项
输出:
49
我们可以看到,我们只是通过写函数名来调用函数,并传递所需的输入。
用户定义的函数
作为程序员或数据科学家,有时我们需要特定于我们需求的功能。在这些情况下,我们可以定义自己的函数。
要定义函数,我们需要遵循以下规则:
- 使用关键字
**def**
引入一个功能定义 - 编写函数名后跟括号
**()**
和一个冒号**:**
- 在这些括号**(可选)内定义一个参数列表**
- 编写函数体。构成函数体的语句从下一行开始,并且必须是预期的。当函数被调用时,函数体中的代码为 run 。
- 函数体的第一条语句可以是代表函数文档(可选)的字符串文字
- 使用
**return**
关键字将结果传回给调用者**(可选)**
如果你认为有许多步骤,不要担心。我们将看到许多例子,概念将变得非常简单。
定义不带参数的函数
让我们看一个没有可选部分的函数定义的简单例子。我们可以通过键入函数名,后跟括号 ()
来调用函数。当我们调用这个函数时,它将打印当前日期。
输出:
2019-02-19
请注意,这个输出对您来说可能是不同的。输出将是您调用该函数的日期。
定义带参数的函数
我们几乎总是需要函数参数。当我们想要将数据传递到我们的函数中时,就会用到它们。当我们调用一个函数时,我们将参数传递给这个函数。
一个参数示例
输出:
Forgive yourself for your faults and your mistakes and move on. - Les Brown
当我们定义这样的参数时,它是必需的。如果我们不为这个参数传递一个参数值,这会给我们一个错误。
输出:
**--------------------------------------------------------------------**
**TypeError** Traceback (most recent call last)
**<ipython-input-48-f2f093834d71>** in <module>**()**
2 print**(**text**)**
3
**----> 4** print_message**()**
**TypeError**: print_message() missing 1 required positional argument: 'text'
稍后,在这篇博文中,我们将看到如何定义可选参数(带有默认值的参数)。
多参数示例 我们可以添加任意多的参数,我们只需要用逗号将它们隔开。在许多情况下,我们需要不止一个参数。
参数传递的顺序对应于函数定义中参数的顺序。在下面的例子中,我们将 10 作为参数number1
的值,将 5 作为参数number2
的值。
输出:
15
然而,如果我们想将结果保存在变量中,我们不能使用上面的函数定义,因为我们的函数只是打印结果,我们不使用**return**
语句。让我们看看如果我们试图保存结果会发生什么。
输出:
15
None
我们可以看到 sum 被打印出来(因为我们的函数被调用了),但是result
变量的值是None
而不是 15。在下一节中,让我们看看如何返回值。
定义返回结果的函数
我们可以使用**return**
关键字离开当前的函数调用并返回想要的结果。让我们看看如何重新定义函数sum_numbers
来返回总和,而不是打印出来。
输出:
15
我们可以清楚地看到,这次result
变量的值是 15。
定义返回多个值的函数
我们还可以定义一个返回多个值的函数。我们可以通过在函数中构造名为 元组 的对象来实现。Python 中的 tuples 数据类型是一个 不可变的 序列 。这意味着它们可以像列表一样包含多个值。
输出:
2019-02-19
08:23:38.030659
在上面的例子中,我们使用序列解包。我们只是将元组中的值“解包”到date
和time
变量中。
用文档定义函数
在上一个例子中,我们定义了一个函数,它以元组的形式返回当前日期和当前时间。也许很容易理解函数是做什么的。然而,如果这个函数有一个文档不是很好吗?
输出:
2019-02-19
08:26:49.538434
在许多情况下,我们的函数比上面的例子更复杂。在这些情况下,为你的功能准备文档总是更好的。功能文档可包括以下信息:
- 函数参数
- 函数计算
- 返回值/秒
范围
并不是所有我们定义的对象(包括函数)在 Python 代码中都是可访问的。程序的范围代表**,其中变量名或函数名可以被访问**。Python 有 3 种作用域:局部、全局和内置作用域。
局部范围
当我们的对象或函数在函数中定义时,这意味着它有一个局部范围。我们只能在定义这个对象或函数的函数内部使用它。
全球范围
当我们的对象或函数在 Python 代码的主体中定义时,这意味着它具有全局范围。我们可以在任何地方访问这个对象或函数,因为它是全局的。
内置范围
在 Python 中,我们有许多内置于中的函数和类型,它们总是可用的。
附加注释
- 如果我们在函数中使用变量名或函数名**,Python 将首先在局部中搜索该名称,然后在全局中搜索,最后在内置 作用域中搜索。**
- 如果我们在脚本的主体中使用变量或名称**,Python 将首先在全局中搜索该名称,然后在内置** 范围中搜索该名称。
是时候看看几个例子了。
Local scope Example
输出:
15**--------------------------------------------------------------------**
**NameError** Traceback (most recent call last)
**<ipython-input-2-faf6ee9da5b3>** in <module>**()**
4
5 print**(**sum_numbers**(10,** **5))**
**----> 6** print**(**result**)**
**NameError**: name 'result' is not defined
在这个例子中,我们可以看到我们可以在函数中访问result
变量,但是在函数之外我们不能访问它。那是因为**result**
变量有局部作用域,只能在sum_numbers
函数内部访问。
Global vs Local Scope Example
输出:
Hi, Ventsi the sum is 15**--------------------------------------------------------------------**
**NameError** Traceback (most recent call last)
**<ipython-input-1-747761fcaa8f>** in <module>**()**
7
8 print**(**sum_numbers**(10,** **5))**
**----> 9** print**(**result**)**
**NameError**: name 'result' is not defined
在这个例子中,我们可以看到我们可以访问函数中的全局变量****name**
。同样,我们使用了**str()**
内置函数。然而,**result**
变量又有一个局部范围,它不能在sum_numbers
函数之外被访问。**
Local vs Global Scope Example
输出:
15
100
这里,我们全局定义了一个result
变量,然后我们在函数中定义了另一个与同名的变量**。我们可以看到,全局范围的值是 100,因为我们的全局变量有这个值。此外,sum_numbers(10,5)的值是 15,因为局部变量result
的值是在函数内部计算的。**
Change the Value of a Global Variable Inside a Function
输出:
programming
machine learning
当我们想在某个函数中改变一个全局变量的值时,我们可以使用关键字**global**
。****
关键字参数
关键字参数与函数调用相关。当您在函数调用中使用关键字参数时,调用者通过参数名识别参数。
这允许您跳过参数或将它们打乱顺序,因为 Python 解释器能够使用提供的关键字将值与参数匹配。
来源:https://www.tutorialspoint.com/python/python_functions.htm
我们可以使用关键字 arguments 使用参数名称 和 **=**
符号。
Keyword Arguments Example
输出:
**8
8
9**
默认参数
在某些情况下,我们有一个带有多个参数的函数,其中一些参数有一个公共值。我们可以为一些函数参数指定默认参数。在这些情况下,我们可以调用我们的函数,而不用为带有默认参数的参数指定值。在 Python 中要做到这一点,我们可以使用=
符号后跟默认值。****
Default Argument Example
输出:
**81
4
8**
从上面的例子中,我们可以看到power
参数有一个默认值 2 。当我们没有为它指定值时,将使用默认值。然而,正如我们看到的,我们可以传递一个不同的值。
Default Arguments Example
输出:
**The number 2 raised to the power 2 is: 4
8
9**
灵活的论据
有时候,我们想要更多灵活的功能。例如,我们可能想要定义一个函数,它接受的参数比我们在函数中指定的参数多。换句话说,我们可能需要向函数传递任意数量的参数。我们可以在函数定义中使用**特殊语法args 和 kwargs 来实现这一点。*
*参数
这些参数被称为无名称变长参数。
输出:
**<class 'tuple'>
(1, 23, 4, 52, 2, 123)**
我们可以看到args 语法将所有参数作为一个名为 **args**
的元组传递给函数。因此,我们可以对元组数据类型做任何我们能做的事情。*****
输出:
**5
10
15**
输出:
**10.0
18.0
15.75**
***** 克瓦查***
这些参数被称为变长参数。
输出:
**<class 'dict'>
{'age': 24, 'position': 'data analyst'}
<class 'dict'>
{'name': 'Jake', 'email': 'jake@gmail.com', 'position': 'machine learning engineer'}**
我们可以看到,kwargs 语法将所有参数作为一个名为 **kwargs**
的字典传递给了函数。因此,我们可以对 dictionary 数据类型做任何我们能做的事情。**
输出:
**age 24
position data analyst
name Jake
email jake@gmail.com
position machine learning engineer**
其实变量名可以随便,我们只需要在前插入一个星号 ***** 或者两个星号 即可。**
输出:
**10.0
age 24
position data analyst**
调用函数时使用和***
我们已经看到,我们可以在函数定义中使用这种特殊的语法。然而,我们也可以在调用函数时使用它。
输出:
name: Jake
position: data analyst
email: jake@gmail.com
输出:
name: Jake
position: data analyst
email: jake@gmail.com
Python 异常
在许多情况下,当我们错误地使用函数时,它会引发一个异常(错误)。****
例如,我们可以从文档中看到内置函数[int()](https://docs.python.org/3/library/functions.html#int)
的部分内容:“返回一个由数字或字符串 x 构造的整数对象,或者如果没有给定参数,则返回 *0*
”
输出:
6
7**--------------------------------------------------------------------**
**ValueError** Traceback (most recent call last)
**<ipython-input-1-dea319bbd9d9>** in <module>**()**
1 print**(**int**(6.99))**
2 print**(**int**("7"))**
**----> 3** print**(**int**("Hi"))****ValueError**: invalid literal for int() with base 10: 'Hi'
我们可以看到,当我们传递“Hello”字符串作为输入时,引发了 value error。
当 Python 脚本引发异常时,我们的代码必须立即处理异常,否则程序执行将停止**。**
异常处理
有时,我们可能希望在不停止程序执行的情况下处理引发的异常。在 Python 中,我们可以使用 try-except 子句来实现。
**try**
块让我们测试代码块的错误**except**
块让我们处理一个错误
输出:
An exception occured
上面的代码引发了一个 名称错误 ,因为名称numbers
没有定义。当我们没有指定我们正在寻找的异常类型时,except 将处理所有的异常类型。
当然,我们可以写一个 except 块,它是寻找一个特定种类的异常。
输出:
An NameError occured
当我们想为每个被处理的异常执行不同的代码时,我们可以定义尽可能多的,除了块**。**
输出:
A ValueError occured
同样,当我们需要关于异常的更多信息时,我们可以使用语法将它保存到变量中。例如,我们可能希望记录错误消息。
我们还可以添加一个**else**
块,如果没有出现错误,它将被执行。
输出:
Something went wrong
'int' object is not iterable
输出:
[1, 2, 3]
Nothing went wrong
同样,如果我们想执行一些代码而不管try 块是否产生了错误**,我们可以使用**finally**
T16 块而不是**else**
T18 块。**
想象一下,我们在你的工作目录中有一个文件filename.txt
,你试图在其中写一些文本。
输出:
An error occured when writing to the file
出现错误是因为默认情况下,打开的内置函数使用“读取”模式。然而,**finally**
块在两种情况下都关闭文件连接(如果有错误或没有)。在这种情况下,我们使用这个块来确保我们的文件被关闭。
投掷错误
当我们定义自己的函数时,我们可能想要抛出错误并编写更多有意义的错误消息。让我们定义一个函数,如果两个单词是变位词,它将返回。
输出:
True**--------------------------------------------------------------------**
**TypeError** Traceback (most recent call last)
**<ipython-input-61-f1a30da1d38d>** in <module>**()**
7
8 print**(**check_anagrams**("silent",** **"listen"))**
**----> 9** print**(**check_anagrams**("silent",** **5))**
**<ipython-input-61-f1a30da1d38d>** in check_anagrams**(word1, word2)**
4 Returns **True** **if** the word1 **and** word2 are anagrams**,** otherwise returns **False**
5 """
**----> 6 return** sorted**(**word1**)** **==** sorted**(**word2**)**
7
8 print**(**check_anagrams**("silent",** **"listen"))**
**TypeError**: 'int' object is not iterable
在第二次调用函数时,我们错误地使用了它**,为word2
传递了整数 5。在这种情况下引发了 TypeError。我们可以看到这个信息有点混乱。因此,我们可以尝试检查这两个单词是否作为字符串传递,并抛出一个更具描述性的错误消息。我们可以使用**raise**
关键字抛出一个错误。**
输出:
True**--------------------------------------------------------------------**
**TypeError** Traceback (most recent call last)
**<ipython-input-3-afb475aa2f4f>** in <module>**()**
10
11 print**(**check_anagrams**("silent",** **"listen"))**
**---> 12** print**(**check_anagrams**("silent",** **5))**
**<ipython-input-3-afb475aa2f4f>** in check_anagrams**(word1, word2)**
5 """
6 **if** type**(**word1**)** **!=** str **or** type**(**word2**)** **!=** str**:**
**----> 7 raise** TypeError**("The word1 and word2 must be strings")**
8
9 **return** sorted**(**word1**)** **==** sorted**(**word2**)**
**TypeError**: The word1 and word2 must be strings
现在,关于这个问题的信息更加具体了。尝试捕捉更具体的异常,并编写具体而清晰的错误消息。您可以从文档中查看所有异常类型。
断言语句
断言语句是对我们的代码进行完整性检查的一种便捷方式。它们是布尔表达式**,检查条件是否返回True
或False
。如果一个条件返回True
,程序将转到下一行代码。否则,将引发一个错误并停止程序执行。**
我们可以把断言语句看作是“如果不抛出”语句**。**
在当前实现中,内置变量
__debug__
在正常情况下是True
,当请求优化时是False
来源:https://docs . python . org/3/reference/simple _ stmts . html # the-assert-statement
输出:
True**--------------------------------------------------------------------**
**AssertionError** Traceback (most recent call last)
**<ipython-input-68-e5a7f4b2ffc2>** in <module>**()**
10
11 print**(**check_anagrams**("silent",** **"listen"))**
**---> 12** print**(**check_anagrams**("silent",** **5))**
**<ipython-input-68-e5a7f4b2ffc2>** in check_anagrams**(word1, word2)**
5 """
6 **assert** type**(**word1**)** **==** str
**----> 7 assert** type**(**word2**)** **==** str
8
9 **return** sorted**(**word1**)** **==** sorted**(**word2**)**
**AssertionError**:
嗯,但是没有错误信息。如果我们想给这个 AssertionError 添加一个消息该怎么办?我们可以传递它,用逗号分隔,就在我们的表达式之后。
输出:
True**--------------------------------------------------------------------**
**AssertionError** Traceback (most recent call last)
**<ipython-input-66-5f2e42abf116>** in <module>**()**
10
11 print**(**check_anagrams**("silent",** **"listen"))**
**---> 12** print**(**check_anagrams**("silent",** **5))**
**<ipython-input-66-5f2e42abf116>** in check_anagrams**(word1, word2)**
5 """
6 **assert** type**(**word1**)** **==** str**,** **"The word1 must be a string"**
**----> 7 assert** type**(**word2**)** **==** str**,** **"The word2 must be a string"**
8
9 **return** sorted**(**word1**)** **==** sorted**(**word2**)**
**AssertionError**: The word2 must be a string
类型提示
Python 是一种动态类型语言。当我们定义变量、函数、类等的时候。我们不需要指定数据类型**。这让我们可以更快地编写代码。**
然而,从 Python 版本开始,我们能够在函数定义中添加类型提示**。我们可以说出参数的预期数据类型以及函数返回的数据类型。**
输出:
Hello Ventsi**--------------------------------------------------------------------TypeError** Traceback (most recent call last)
**<ipython-input-28-b1c33d5121c9>** in <module>**()**
1 print**(**greeting**("Ventsi"))**
**----> 2** print**(**greeting**(42))**
**<ipython-input-1-311aff60a9bd>** in greeting**(name)**
1 **def** greeting**(**name**:** str**)** **->** str**:**
**----> 2 return** **'Hello '** **+** name
**TypeError**: must be str, not int
我们也可以定义类型别名。
输出:
[2.0, -8.4, 10.8]
你可以在这里找到更多信息。
传递可变对象和不可变对象
当我们将 可变对象 传递给我们的函数时,我们必须小心。函数调用中传递的参数使用的是对象引用** ,而不是对象的值。所以,请记住,有些函数可以改变被传递对象的值。**
某些对象的值可以改变。值可以改变的对象 是 据说是 可变*;一旦被创建,其值不变的对象称为*。******
输出:
***Before calling the function: ['this is test sentence', 'I love Python', 'positive thinking is nice!']
After calling the function: ['This is test sentence', 'I love python', 'Positive thinking is nice!']***
我们可以看到,在调用我们的函数之后,我们已经更改了sentences
列表的内容。
如果我们想将结果保存在一个不同的变量中,我们可以在我们的函数中拷贝列表,对拷贝版本进行大写并返回。这样,我们不会改变sentences
列表本身(在某些情况下,这是您想要的)。
输出:
***Before calling the function: ['this is test sentence', 'I love Python', 'positive thinking is nice!']
After calling the function: ['this is test sentence', 'I love Python', 'positive thinking is nice!']
Capitalized sentences (result of the function): ['This is test sentence', 'I love python', 'Positive thinking is nice!']***
摘要
- 功能是一段有组织的可重用代码解决一个特定任务*。*****
- 我们可以添加任意多的参数,我们只需要用逗号*分隔它们。*******
- 当我们调用一个函数时,我们将参数传递给这个函数。
- 我们可以使用
**return**
关键字从函数中返回一个结果 - 我们可以定义一个函数返回多个值构造名为 元组 的对象****
- 函数体的第一条语句可以是代表函数文档(可选)的字符串文字****
- Python 有 3 种类型的作用域 : 局部,全局和内置作用域。****
- 当我们在函数调用中使用关键字参数时,调用者通过参数名识别参数。这允许您跳过参数或将它们打乱顺序*。*****
- 我们可以为一些函数参数指定默认参数****
- 当我们想要有灵活的参数时,我们可以使用特殊语法*args* 和 kwargs 。***
- 我们可以使用 try-except 子句来处理引发的异常。****
- 我们可以用
**raise**
关键字到抛出一个错误。**** - 断言语句是一种方便的方式来检查我们的代码。
- 当我们将可变对象传递给我们的函数时,我们必须小心,它们的值可以被改变。****
- 附加说明:当我们编写自己的函数时,我们必须小心不要覆盖某些包名或内置函数名*。*****
时事通讯
如果你想在我发表新的博客文章时得到通知,你可以订阅我的时事通讯。
商务化人际关系网
这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。
最后的话
谢谢你的阅读。我希望你喜欢这篇文章。如果你喜欢,请按住拍手键,分享给你的朋友。我很高兴听到你的反馈。如果你想写一篇关于λ函数的博文,请告诉我。如果你有什么问题,尽管问。😉
资源:
- https://camp . data camp . com/courses/python-data-science-toolbox-part-1/
- https://www.geeksforgeeks.org/args-kwargs-python/
- https://www.tutorialspoint.com/python/python_functions.htm
- https://www . salty crane . com/blog/2008/01/how-to-use-args-and-kwargs-in-python/
- https://stack overflow . com/questions/2052390/manually-raising-throwing-a-exception-in-python
- https://www.tutorialspoint.com/python/python_exceptions.htm
- https://www.w3schools.com/python/python_try_except.asp
- https://docs . python . org/3/library/exceptions . html # exception-hierarchy
- https://docs.python.org/3/tutorial/controlflow.html
- *****【https://docs.python.org/3/reference/simple_stmts.html *****
- https://docs . python . org/3/library/functions . html #内置函数
- https://docs.python.org/3/reference/simple_stmts.html
Python 基础:元组
Source: https://www.quora.com/Can-you-suggest-some-good-books-websites-for-learning-Python-for-a-layman
读完这篇博客后,你会知道:
- Python 中的元组数据类型是什么
- 如何初始化元组
- 如何迭代元组
- 元组上的常见序列运算
- 什么是元组解包
- 元组和列表有什么区别
介绍
元组是不可变序列,通常用于存储异构数据的集合(例如由
[enumerate()](https://docs.python.org/3/library/functions.html#enumerate)
内置产生的 2 元组)。
序列是可迭代中很常见的类型。内置序列类型的一些例子有 列表 、 字符串 和 元组 。它们使用整数索引支持高效的元素访问,并定义了一个返回序列长度的方法。
值可以改变的对象被称为可变的。对象一旦被创建,其值就不可改变称为不可变**。**
如果你想知道更多关于 Python 中序列和不可变对象的细节,你可以看看我以前的博文:
元组看起来类似于列表。它们可以包含多个值。列表和元组的主要区别在于元组是不可变的,而列表是可变的。
元组初始化
在 Python 中,我们可以用几种方式初始化元组
- 用一对括号来表示一个空元组 :
**()**
- 为具有一个值 :
**a,**
或**(a,)**
的元组使用尾随逗号 - 用逗号分隔项目 :
**a, b, c**
或**(a, b, c)**
- 使用 tuple() 内置 :
**tuple()**
或**tuple(iterable)**
括号是可选的,除非在空元组的情况下,或者当需要它们来避免语法歧义时。例如,f(a, b)
是一个带有两个参数的函数调用,而f((a, b))
是一个带有一个作为两个元素的元组传递的参数的函数调用。
初始化空元组
输出:
<class 'tuple'>
<class 'tuple'>
()
()
用单个值初始化元组
输出:
<class 'tuple'>
<class 'tuple'>
('Python',)
('Data Science',)
初始化具有多个值的元组
输出:
<class 'tuple'>
<class 'tuple'>
(1, 2, 3)
(1, 2, 3)
从 Iterables 初始化元组
输出:
<class 'tuple'>
('Python', 'Maths', 'Machine Learning')
迭代元组
我们已经知道元组是序列数据类型,我们可以迭代序列,因为它们是可迭代的。
输出:
Pineapple
orange
banana
apple
列举
Python 中的[**enumerate(iterable, start=0)**](https://docs.python.org/3/library/functions.html#enumerate)
内置函数返回迭代器。当我们迭代这个迭代器时,它返回一个包含计数(从 0 开始)和通过迭代**iterable**
获得的值的元组。
输出:
0 Pineapple
1 orange
2 banana
3 apple
0 pandas
1 scikit-learn
2 seaborn
常见顺序操作
在 Python 中,我们有一些常见的序列操作,它们被大多数序列类型支持,包括可变的和不可变的。
该表列出了按优先级升序排序的序列操作。表中,
***s***
***t***
为同类型序列,***n***
,***i***
,***j***
,***k***
为整数,***x***
为满足***s***
任意类型和值限制的任意对象。****
in
和not in
操作与比较操作具有相同的优先级。+
(连接)和*
(重复)运算与相应的数字运算具有相同的优先级。
Source: https://docs.python.org/3/library/stdtypes.html#typesseq-common
让我们看看如何对元组进行这些操作。
在,不在
输出:
True
False
False
True
串联
输出:
('Python', 'Web Development', 'Machine Learning', 'Communication', 'Courtesy', 'Flexibility', 'Integrity')
增加
输出:
(['Communication', 'Courtesy'], ['Communication', 'Courtesy'], ['Communication', 'Courtesy'])
这相当于给自己加了三次soft_skills
。但是,要小心! **soft_skills**
中的项不复制,被多次引用。让我们看看,如果我们向元组的第一个列表添加值,会发生什么。****
输出:
(['Communication', 'Courtesy'], ['Communication', 'Courtesy'], ['Communication', 'Courtesy'])
(['Communication', 'Courtesy', 'Responsibility'], ['Communication', 'Courtesy', 'Responsibility'], ['Communication', 'Courtesy', 'Responsibility'])
新添加的值被添加到三个列表中,因为它们引用同一个对象。
索引
输出:
Communication
Responsibility
是的,在 Python 中我们可以使用负索引(我们可以使用-1
作为索引来获取最后一个元素)。当我们使用负指数时,应用此公式计算实际指数:len(sequence) + index
。
在我们的例子中,长度是 5,所以我们得到索引5 — 1 = 4
处的项目,这就是责任项目。**
限幅
我们可以使用切片来选择序列对象中的一系列项目。语法是sliceable[start_index:end_index:step]
。
start_index
是切片的起始索引,该索引处的元素将包含在结果中,默认值为0
。end_index
是切片的结束索引,此索引处的元素将不包括在结果中。默认值是len(sequence)
。step
是指标增加的数量,
默认为1
。如果我们为步长设置一个负值,我们将向后移动。
输出:
**('Courtesy', 'Flexibility', 'Integrity')
('Communication', 'Courtesy', 'Flexibility', 'Integrity')
('Communication', 'Courtesy', 'Flexibility', 'Integrity', 'Responsibility')
('Communication', 'Flexibility', 'Responsibility')
('Responsibility', 'Integrity', 'Flexibility', 'Courtesy', 'Communication')**
最小值、最大值和长度
我们可以使用min()
、max()
和len()
内置函数来获得一个序列的最大值、最小值和长度。
输出:
**5
Communication
Responsibility
11
7
90**
索引和计数
我们已经为元组提供了索引和计数方法。我们可以使用第一个来标识给定值的索引,使用第二个来标识这个值在我们的元组中出现了多少次。
输出:
**1**--------------------------------------------------------------------**
**ValueError** Traceback (most recent call last)
**<ipython-input-21-f2447af847ce>** in <module>**()**
3
4 numbers **=** **(10,** **22,** **53,** **53,** **8,** **9,** **11,** **45,** **90,** **7,** **26)**
**----> 5** print**(**numbers**.**index**(100))**
**ValueError**: tuple.index(x): x not in tuple**
我们可以看到,如果我们传递一个不在元组中的值,我们将得到一个ValueError
。
输出:
**1
2
0**
如果我们传递一个在我们的元组中不存在的值,计数方法将返回 0。这一次没有错误。
元组解包
我们还可以将元组中的值“解包”到变量中。此外,更通用的方法称为序列解包,因此这将适用于任何序列。我们已经看到了枚举内置函数的例子。
输出:
**10
20
30**
请注意,解包元组时,左侧变量的数量应该等于元组中值的数量。否则,我们会得到一个错误。
输出:
****--------------------------------------------------------------------**
**ValueError** Traceback (most recent call last)
**<ipython-input-45-282b018b9602>** in <module>**()**
**----> 1** a**,** b **=** **(10,** **20,** **30)**
**ValueError**: too many values to unpack (expected 2)**
输出:
****--------------------------------------------------------------------**
**ValueError** Traceback (most recent call last)
**<ipython-input-43-c91a3d9d3fc4>** in <module>**()**
**----> 1** a**,** b**,**c**,**d **=** **(10,** **20,** **30)**
**ValueError**: not enough values to unpack (expected 4, got 3)**
元组与列表
如前所述,列表和元组之间的主要区别在于元组是不可变的,而列表是可变的。
重要注意事项 :
如果可变对象被改变,包含对可变对象的引用的不可变容器的值可以被改变。当我们谈论容器的可变性时,只有被包含对象的身份是隐含的。然而,如果我们的不可变容器只包含不可变的数据类型,它的值就不能改变。参见这篇博文中的例子。****
与列表不同,元组没有append()
、insert()
、remove()
、pop()
、extend()
等方法,因为它们具有不可变的性质。
输出:
**['Flexibility', 'Courtesy', 'Flexibility', 'Integrity', 'Responsibility']**--------------------------------------------------------------------**
**TypeError** Traceback (most recent call last)
**<ipython-input-47-5d2973b1f2b4>** in <module>**()**
4
5 tuple_skills **=** **("Communication",** **"Courtesy",** **"Flexibility",** **"Integrity",** **"Responsibility")**
**----> 6** tuple_skills**[0]** **=** **"Flexibility"**
**TypeError**: 'tuple' object does not support item assignment**
文档中的附加注释
尽管元组可能看起来类似于列表,但它们通常用于不同的情况和不同的目的。元组是不可变的,并且通常包含通过解包或索引(或者甚至在
[namedtuples](https://docs.python.org/3.7/library/collections.html#collections.namedtuple)
的情况下通过属性)访问的异构元素序列。列表是可变的,它们的元素通常是同构的,通过遍历列表来访问。
来源:https://docs . python . org/3.7/tutorial/data structures . html # tuple-and-sequences
何时使用元组
- 元组比列表快。如果你需要一组常量值,而你所要做的就是遍历它,那么使用元组而不是列表。
输出:
**0.034131127635760095
0.11737610517116082**
timeit
库允许我们以秒为单位测量经过的时间。我们可以清楚地看到元组初始化比列表初始化快。
- 仅包含不可变值的元组可以用作字典的键,而列表则不能。
输出:
**Introducton**--------------------------------------------------------------------**
**TypeError** Traceback (most recent call last)
**<ipython-input-5-c18ababebf4d>** in <module>**()**
2 print**(**book**[(1,** **10)])**
3
**----> 4** book **=** **{[1,** **10]:** **"Introducton",** **[11,** **15]:** **"Notation and Definitions",** **[16,** **30]:** **"Fundamental Algorithms"}**
**TypeError**: unhashable type: 'list'**
- 如果我们的元组只包含不可变的对象,我们可以使用它们来确保我们的数据不会被改变。
摘要
- 元组是不可变序列,通常用于存储异构数据的集合(例如由
[*enumerate()*](https://docs.python.org/3/library/functions.html#enumerate)
内置产生的 2 元组)。 - 列表和元组的主要区别在于元组是不可变的,而列表是可变的。
- 我们可以使用一对括号
**()**
和来初始化一个元组,括号内的值用逗号隔开。**** - 我们可以使用tuple(iterable)内置的函数来初始化一个 tuple。
- 我们可以使用一个简单的 for 循环对元组进行迭代。
- 我们可以对元组进行常见的序列操作,比如索引、切片、拼接、乘法,获取 min 、 max 值等等。****
- 我们可以从元组中解包值
- 当你需要一组常量值并且你所要做的就是遍历它时,使用元组而不是列表。****
时事通讯
如果你想在我发表新的博客文章时得到通知,你可以订阅我的时事通讯。
商务化人际关系网
这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。
最后的话
谢谢你的阅读。我希望你喜欢这篇文章。如果你喜欢,请按住拍手键,分享给你的朋友。我很高兴听到你的反馈。如果你有什么问题,尽管问。😉
资源
- https://www . data camp . com/community/tutorials/python-tuples-tutorial
- https://www.tutorialspoint.com/python/python_tuples.htm
- https://stack overflow . com/questions/1708510/python-list-vs-tuple-when-to-use-each
- https://docs . python . org/3/tutorial/data structures . html #元组和序列
- https://docs.python.org/3/library/stdtypes.html#tuples
- https://docs . python . org/3.7/library/stdtypes . html # common-sequence-operations