Python 数据分析(PYDA)第三版(一)(2)

简介: Python 数据分析(PYDA)第三版(一)

Python 数据分析(PYDA)第三版(一)(1)https://developer.aliyun.com/article/1482368


内省

在变量前或后使用问号(?)将显示有关对象的一些常规信息:

In [1]: b = [1, 2, 3]
In [2]: b?
Type:        list
String form: [1, 2, 3]
Length:      3
Docstring:
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
In [3]: print?
Docstring:
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:  a file-like object (stream); defaults to the current sys.stdout.
sep:   string inserted between values, default a space.
end:   string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
Type:      builtin_function_or_method

这被称为对象内省。如果对象是函数或实例方法,则如果定义了文档字符串,它也将显示出来。假设我们编写了以下函数(您可以在 IPython 或 Jupyter 中重现):

def add_numbers(a, b):
 """
 Add two numbers together
 Returns
 -------
 the_sum : type of arguments
 """
 return a + b

然后使用?显示文档字符串:

In [6]: add_numbers?
Signature: add_numbers(a, b)
Docstring:
Add two numbers together
Returns
-------
the_sum : type of arguments
File:      <ipython-input-9-6a548a216e27>
Type:      function

?还有一个最终的用途,就是在 IPython 命名空间中进行搜索,类似于标准的 Unix 或 Windows 命令行。与通配符(*)结合的一系列字符将显示所有与通配符表达式匹配的名称。例如,我们可以获取包含load的顶级 NumPy 命名空间中的所有函数列表:

In [9]: import numpy as np
In [10]: np.*load*?
np.__loader__
np.load
np.loads
np.loadtxt

2.3 Python 语言基础

在本节中,我将为您概述基本的 Python 编程概念和语言机制。在下一章中,我将更详细地介绍 Python 数据结构、函数和其他内置工具。

语言语义

Python 语言设计的一个重要特点是其对可读性、简单性和明确性的强调。有些人甚至将其比作“可执行的伪代码”。

缩进,而不是大括号

Python 使用空格(制表符或空格)来结构化代码,而不是像 R、C++、Java 和 Perl 等许多其他语言那样使用大括号。考虑一个排序算法中的for循环:

for x in array:
 if x < pivot:
 less.append(x)
 else:
 greater.append(x)

冒号表示缩进代码块的开始,之后所有代码都必须缩进相同的量,直到块的结束。

无论你喜欢还是讨厌,对于 Python 程序员来说,有意义的空白是一个事实。虽然一开始可能会感到陌生,但希望你能逐渐习惯它。

注意

我强烈建议使用四个空格作为默认缩进,并用四个空格替换制表符。许多文本编辑器都有一个设置,可以自动将制表符替换为空格(请这样做!)。IPython 和 Jupyter 笔记本会在冒号后的新行自动插入四个空格,并用四个空格替换制表符。

正如你现在所看到的,Python 语句也不需要以分号结尾。但是,分号可以用来在单行上分隔多个语句:

a = 5; b = 6; c = 7

在一行上放置多个语句通常在 Python 中是不鼓励的,因为这可能会使代码变得不太可读。

一切都是对象

Python 语言的一个重要特点是其对象模型的一致性。每个数字、字符串、数据结构、函数、类、模块等都存在于 Python 解释器中的自己的“盒子”中,这被称为Python 对象。每个对象都有一个关联的类型(例如整数字符串函数)和内部数据。实际上,这使得语言非常灵活,因为即使函数也可以像任何其他对象一样对待。

注释

由井号(井号)#引导的任何文本都会被 Python 解释器忽略。这通常用于向代码添加注释。有时您可能还想排除某些代码块而不删除它们。一种解决方案是注释掉代码:

results = []
for line in file_handle:
 # keep the empty lines for now
 # if len(line) == 0:
 #   continue
 results.append(line.replace("foo", "bar"))

注释也可以出现在执行代码的行之后。虽然一些程序员更喜欢将注释放在特定代码行之前的行中,但有时这样做也是有用的:

print("Reached this line")  # Simple status report
函数和对象方法调用

使用括号调用函数并传递零个或多个参数,可选地将返回的值赋给一个变量:

result = f(x, y, z)
g()

Python 中几乎每个对象都有附加的函数,称为方法,这些函数可以访问对象的内部内容。您可以使用以下语法调用它们:

obj.some_method(x, y, z

函数可以接受位置关键字参数:

result = f(a, b, c, d=5, e="foo")

我们稍后会更详细地看一下这个。

变量和参数传递

在 Python 中赋值变量(或名称)时,您正在创建对等号右侧显示的对象的引用。在实际操作中,考虑一个整数列表:

In [8]: a = [1, 2, 3]

假设我们将a赋给一个新变量b

In [9]: b = a
In [10]: b
Out[10]: [1, 2, 3]

在一些语言中,对b的赋值将导致数据[1, 2, 3]被复制。在 Python 中,ab实际上现在指向同一个对象,即原始列表[1, 2, 3](请参见图 2.5 的模拟)。您可以通过向a附加一个元素,然后检查b来证明这一点:

In [11]: a.append(4)
In [12]: b
Out[12]: [1, 2, 3, 4]

图 2.5:同一对象的两个引用

了解 Python 中引用的语义以及何时、如何以及为什么数据被复制,在处理 Python 中的大型数据集时尤为重要。

注意

赋值也被称为绑定,因为我们正在将一个名称绑定到一个对象。已经分配的变量名称有时可能被称为绑定变量。

当您将对象作为参数传递给函数时,将创建新的本地变量引用原始对象,而不进行任何复制。如果在函数内部将一个新对象绑定到一个变量,那么它不会覆盖函数外部(“父范围”)具有相同名称的变量。因此,可以更改可变参数的内部。假设我们有以下函数:

In [13]: def append_element(some_list, element):
 ....:     some_list.append(element)

然后我们有:

In [14]: data = [1, 2, 3]
In [15]: append_element(data, 4)
In [16]: data
Out[16]: [1, 2, 3, 4]
动态引用,强类型

Python 中的变量没有与之关联的固有类型;通过赋值,变量可以引用不同类型的对象。以下情况没有问题:

In [17]: a = 5
In [18]: type(a)
Out[18]: int
In [19]: a = "foo"
In [20]: type(a)
Out[20]: str

变量是特定命名空间内对象的名称;类型信息存储在对象本身中。一些观察者可能匆忙得出结论,认为 Python 不是一种“类型化语言”。这是不正确的;考虑这个例子:

In [21]: "5" + 5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-7fe5aa79f268> in <module>
----> 1 "5" + 5
TypeError: can only concatenate str (not "int") to str

在某些语言中,字符串'5'可能会被隐式转换(或转换)为整数,从而得到 10。在其他语言中,整数5可能会被转换为字符串,从而得到连接的字符串'55'。在 Python 中,不允许这种隐式转换。在这方面,我们说 Python 是一种强类型语言,这意味着每个对象都有一个特定的类型(或),隐式转换只会在某些允许的情况下发生,例如:

In [22]: a = 4.5
In [23]: b = 2
# String formatting, to be visited later
In [24]: print(f"a is {type(a)}, b is {type(b)}")
a is <class 'float'>, b is <class 'int'>
In [25]: a / b
Out[25]: 2.25

在这里,即使b是一个整数,它也会被隐式转换为浮点数进行除法运算。

了解对象的类型很重要,能够编写能够处理许多不同类型输入的函数也很有用。您可以使用isinstance函数检查对象是否是特定类型的实例:

In [26]: a = 5
In [27]: isinstance(a, int)
Out[27]: True

如果要检查对象的类型是否在元组中存在,isinstance可以接受一个类型元组:

In [28]: a = 5; b = 4.5
In [29]: isinstance(a, (int, float))
Out[29]: True
In [30]: isinstance(b, (int, float))
Out[30]: True
属性和方法

Python 中的对象通常具有属性(存储在对象“内部”的其他 Python 对象)和方法(与对象关联的函数,可以访问对象的内部数据)。它们都可以通过语法访问:

In [1]: a = "foo"
In [2]: a.<Press Tab>
capitalize() index()        isspace()      removesuffix()  startswith()
casefold()   isprintable()  istitle()      replace()       strip()
center()     isalnum()      isupper()      rfind()         swapcase()
count()      isalpha()      join()         rindex()        title()
encode()     isascii()      ljust()        rjust()         translate()
endswith()   isdecimal()    lower()        rpartition()
expandtabs() isdigit()      lstrip()       rsplit()
find()       isidentifier() maketrans()    rstrip()
format()     islower()      partition()    split()
format_map() isnumeric()    removeprefix() splitlines()

属性和方法也可以通过getattr函数按名称访问:

In [32]: getattr(a, "split")
Out[32]: <function str.split(sep=None, maxsplit=-1)>

虽然我们在本书中不会广泛使用getattr函数和相关函数hasattrsetattr,但它们可以非常有效地用于编写通用的可重用代码。

鸭子类型

通常,您可能不关心对象的类型,而只关心它是否具有某些方法或行为。这有时被称为鸭子类型,源自谚语“如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子。”例如,如果对象实现了迭代器协议,则可以验证该对象是否可迭代。对于许多对象,这意味着它具有一个__iter__“魔术方法”,尽管检查的另一种更好的方法是尝试使用iter函数:

In [33]: def isiterable(obj):
 ....:     try:
 ....:         iter(obj)
 ....:         return True
 ....:     except TypeError: # not iterable
 ....:         return False

对于字符串以及大多数 Python 集合类型,此函数将返回True

In [34]: isiterable("a string")
Out[34]: True
In [35]: isiterable([1, 2, 3])
Out[35]: True
In [36]: isiterable(5)
Out[36]: False
导入

在 Python 中,模块只是一个包含 Python 代码的扩展名为*.py*的文件。假设我们有以下模块:

# some_module.py
PI = 3.14159
def f(x):
 return x + 2
def g(a, b):
 return a + b

如果我们想要从同一目录中的另一个文件中访问some_module.py中定义的变量和函数,我们可以这样做:

import some_module
result = some_module.f(5)
pi = some_module.PI

或者:

from some_module import g, PI
result = g(5, PI)

通过使用as关键字,您可以为导入指定不同的变量名称:

import some_module as sm
from some_module import PI as pi, g as gf
r1 = sm.f(pi)
r2 = gf(6, pi)
二进制运算符和比较

大多数二进制数学运算和比较使用其他编程语言中常用的数学语法:

In [37]: 5 - 7
Out[37]: -2
In [38]: 12 + 21.5
Out[38]: 33.5
In [39]: 5 <= 2
Out[39]: False

查看表 2.1 以获取所有可用的二进制运算符。

表 2.1:二进制运算符

操作 描述
a + b ab相加
a - b a中减去b
a * b a乘以b
a / b a除以b
a // b 通过b进行地板除法,去除任何小数余数
a ** b a提升到b次方
a & b 如果ab都为True,则为True;对于整数,取位AND
`a b`
a ^ b 对于布尔值,如果abTrue,但不是两者都为True;对于整数,取位异或
a == b 如果a等于b,则为True
a != b 如果a不等于b,则为True
a < b,a <= b 如果a小于(小于或等于)b,则为True
a > b, a >= b 如果a大于(大于或等于)b,则为True
a is b 如果ab引用相同的 Python 对象,则为True
a is not b 如果ab引用不同的 Python 对象,则为True

要检查两个变量是否引用同一对象,请使用is关键字。使用is not来检查两个对象是否不相同:

In [40]: a = [1, 2, 3]
In [41]: b = a
In [42]: c = list(a)
In [43]: a is b
Out[43]: True
In [44]: a is not c
Out[44]: True

由于list函数始终创建一个新的 Python 列表(即一个副本),我们可以确保ca不同。与==运算符不同,使用is不同,因为在这种情况下我们有:

In [45]: a == c
Out[45]: True

isis not的常见用法是检查变量是否为None,因为None只有一个实例:

In [46]: a = None
In [47]: a is None
Out[47]: True
可变和不可变对象

Python 中的许多对象,如列表、字典、NumPy 数组和大多数用户定义的类型(类),都是可变的。这意味着它们包含的对象或值可以被修改:

In [48]: a_list = ["foo", 2, [4, 5]]
In [49]: a_list[2] = (3, 4)
In [50]: a_list
Out[50]: ['foo', 2, (3, 4)]

其他,如字符串和元组,是不可变的,这意味着它们的内部数据不能被更改:

In [51]: a_tuple = (3, 5, (4, 5))
In [52]: a_tuple[1] = "four"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-52-cd2a018a7529> in <module>
----> 1 a_tuple[1] = "four"
TypeError: 'tuple' object does not support item assignment

请记住,仅因为您可以改变对象并不意味着您总是应该这样做。这些操作被称为副作用。例如,在编写函数时,任何副作用都应明确地在函数的文档或注释中向用户传达。如果可能的话,我建议尽量避免副作用并偏爱不可变性,即使可能涉及可变对象。

标量类型

Python 具有一小组内置类型,用于处理数字数据、字符串、布尔(TrueFalse)值以及日期和时间。这些“单值”类型有时被称为标量类型,我们在本书中将它们称为标量。请参阅表 2.2 以获取主要标量类型的列表。日期和时间处理将单独讨论,因为这些由标准库中的datetime模块提供。

表 2.2:标准 Python 标量类型

类型 描述
None Python 的“null”值(只存在一个None对象的实例)
str 字符串类型;保存 Unicode 字符串
bytes 原始二进制数据
float 双精度浮点数(请注意没有单独的double类型)
bool 布尔值TrueFalse
int 任意精度整数
数字类型

数字的主要 Python 类型是intfloatint可以存储任意大的数字:

In [53]: ival = 17239871
In [54]: ival ** 6
Out[54]: 26254519291092456596965462913230729701102721

浮点数用 Python 的float类型表示。在底层,每个都是双精度值。它们也可以用科学计数法表示:

In [55]: fval = 7.243
In [56]: fval2 = 6.78e-5

整数除法如果结果不是整数,将始终产生一个浮点数:

In [57]: 3 / 2
Out[57]: 1.5

要获得 C 风格的整数除法(如果结果不是整数,则丢弃小数部分),请使用地板除法运算符//

In [58]: 3 // 2
Out[58]: 1
字符串

许多人使用 Python 是因为其内置的字符串处理功能。您可以使用单引号'或双引号"(通常更喜欢双引号)编写字符串字面值

a = 'one way of writing a string'
b = "another way"

Python 字符串类型是str

对于带有换行符的多行字符串,可以使用三引号,即'''"""

c = """
This is a longer string that
spans multiple lines
"""

这个字符串c实际上包含四行文本可能会让您感到惊讶;在"""之后和lines之后的换行符包含在字符串中。我们可以使用c上的count方法来计算换行符的数量:

In [60]: c.count("\n")
Out[60]: 3

Python 字符串是不可变的;您不能修改一个字符串:

In [61]: a = "this is a string"
In [62]: a[10] = "f"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-62-3b2d95f10db4> in <module>
----> 1 a[10] = "f"
TypeError: 'str' object does not support item assignment

要解释此错误消息,请从下往上阅读。我们尝试用字母"f"替换位置 10 处的字符(“项”),但对于字符串对象来说,这是不允许的。如果我们需要修改一个字符串,我们必须使用一个创建新字符串的函数或方法,比如字符串replace方法:

In [63]: b = a.replace("string", "longer string")
In [64]: b
Out[64]: 'this is a longer string'

此操作后,变量a保持不变:

In [65]: a
Out[65]: 'this is a string'

许多 Python 对象可以使用str函数转换为字符串:

In [66]: a = 5.6
In [67]: s = str(a)
In [68]: print(s)
5.6

字符串是 Unicode 字符序列,因此可以像其他序列(如列表和元组)一样对待:

In [69]: s = "python"
In [70]: list(s)
Out[70]: ['p', 'y', 't', 'h', 'o', 'n']
In [71]: s[:3]
Out[71]: 'pyt'

s[:3]语法称为切片,对于许多种类的 Python 序列都有实现。稍后将更详细地解释这一点,因为它在本书中被广泛使用。

反斜杠字符\是一个转义字符,意味着它用于指定特殊字符,如换行符\n或 Unicode 字符。要编写带有反斜杠的字符串字面值,您需要对其进行转义:

In [72]: s = "12\\34"
In [73]: print(s)
12\34

如果您有一个带有许多反斜杠且没有特殊字符的字符串,您可能会觉得有点烦人。幸运的是,您可以在字符串的前导引号前加上r,这意味着应该按原样解释字符:

In [74]: s = r"this\has\no\special\characters"
In [75]: s
Out[75]: 'this\\has\\no\\special\\characters'

r代表原始

将两个字符串相加会将它们连接在一起并生成一个新字符串:

In [76]: a = "this is the first half "
In [77]: b = "and this is the second half"
In [78]: a + b
Out[78]: 'this is the first half and this is the second half'

字符串模板或格式化是另一个重要主题。随着 Python 3 的出现,进行此操作的方式数量已经扩展,这里我将简要描述其中一个主要接口的机制。字符串对象具有一个format方法,可用于将格式化参数替换为字符串中,生成一个新字符串:

In [79]: template = "{0:.2f}  {1:s} are worth US${2:d}"

在这个字符串中:

  • {0:.2f}表示将第一个参数格式化为带有两位小数的浮点数。
  • {1:s}表示将第二个参数格式化为字符串。
  • {2:d}表示将第三个参数格式化为精确整数。

要为这些格式参数替换参数,我们将一系列参数传递给format方法:

In [80]: template.format(88.46, "Argentine Pesos", 1)
Out[80]: '88.46 Argentine Pesos are worth US$1'

Python 3.6 引入了一个名为f-strings(即格式化字符串字面值)的新功能,可以使创建格式化字符串更加方便。要创建 f-string,只需在字符串字面值之前立即写入字符f。在字符串中,用大括号括起 Python 表达式,以将表达式的值替换为格式化字符串中的值:

In [81]: amount = 10
In [82]: rate = 88.46
In [83]: currency = "Pesos"
In [84]: result = f"{amount}  {currency} is worth US${amount / rate}"

格式说明符可以在每个表达式后添加,使用与上面字符串模板相同的语法:

In [85]: f"{amount}  {currency} is worth US${amount / rate:.2f}"
Out[85]: '10 Pesos is worth US$0.11'

字符串格式化是一个深入的主题;有多种方法和大量选项和调整可用于控制结果字符串中的值的格式。要了解更多,请参阅官方 Python 文档

字节和 Unicode

在现代 Python(即 Python 3.0 及更高版本)中,Unicode 已成为一流的字符串类型,以实现更一致地处理 ASCII 和非 ASCII 文本。在旧版本的 Python 中,字符串都是字节,没有任何明确的 Unicode 编码。您可以假设您知道字符编码来转换为 Unicode。这里是一个带有非 ASCII 字符的示例 Unicode 字符串:

In [86]: val = "español"
In [87]: val
Out[87]: 'español'

我们可以使用encode方法将此 Unicode 字符串转换为其 UTF-8 字节表示:

In [88]: val_utf8 = val.encode("utf-8")
In [89]: val_utf8
Out[89]: b'espa\xc3\xb1ol'
In [90]: type(val_utf8)
Out[90]: bytes

假设您知道bytes对象的 Unicode 编码,您可以使用decode方法返回:

In [91]: val_utf8.decode("utf-8")
Out[91]: 'español'

现在最好使用 UTF-8 进行任何编码,但出于历史原因,您可能会遇到各种不同编码的数据:

In [92]: val.encode("latin1")
Out[92]: b'espa\xf1ol'
In [93]: val.encode("utf-16")
Out[93]: b'\xff\xfee\x00s\x00p\x00a\x00\xf1\x00o\x00l\x00'
In [94]: val.encode("utf-16le")
Out[94]: b'e\x00s\x00p\x00a\x00\xf1\x00o\x00l\x00'

在处理文件时,最常见的是遇到bytes对象,其中不希望将所有数据隐式解码为 Unicode 字符串。

布尔值

Python 中的两个布尔值分别写为TrueFalse。比较和其他条件表达式的结果要么为True,要么为False。布尔值可以使用andor关键字组合:

In [95]: True and True
Out[95]: True
In [96]: False or True
Out[96]: True

当转换为数字时,False变为0True变为1

In [97]: int(False)
Out[97]: 0
In [98]: int(True)
Out[98]: 1

关键字not可以将布尔值从True翻转为False,反之亦然:

In [99]: a = True
In [100]: b = False
In [101]: not a
Out[101]: False
In [102]: not b
Out[102]: True
类型转换

strboolintfloat类型也是可以用来将值转换为这些类型的函数:

In [103]: s = "3.14159"
In [104]: fval = float(s)
In [105]: type(fval)
Out[105]: float
In [106]: int(fval)
Out[106]: 3
In [107]: bool(fval)
Out[107]: True
In [108]: bool(0)
Out[108]: False

请注意,大多数非零值在转换为bool时会变为True

None

None是 Python 的空值类型:

In [109]: a = None
In [110]: a is None
Out[110]: True
In [111]: b = 5
In [112]: b is not None
Out[112]: True

None也是函数参数的常见默认值:

def add_and_maybe_multiply(a, b, c=None):
 result = a + b
 if c is not None:
 result = result * c
 return result
日期和时间

内置的 Python datetime模块提供了datetimedatetime类型。datetime类型结合了datetime中存储的信息,是最常用的类型:

In [113]: from datetime import datetime, date, time
In [114]: dt = datetime(2011, 10, 29, 20, 30, 21)
In [115]: dt.day
Out[115]: 29
In [116]: dt.minute
Out[116]: 30

给定一个datetime实例,您可以通过在具有相同名称的datetime上调用方法来提取等效的datetime对象:

In [117]: dt.date()
Out[117]: datetime.date(2011, 10, 29)
In [118]: dt.time()
Out[118]: datetime.time(20, 30, 21)

strftime方法将datetime格式化为字符串:

In [119]: dt.strftime("%Y-%m-%d %H:%M")
Out[119]: '2011-10-29 20:30'

字符串可以使用strptime函数转换(解析)为datetime对象:

In [120]: datetime.strptime("20091031", "%Y%m%d")
Out[120]: datetime.datetime(2009, 10, 31, 0, 0)

查看表 11.2 以获取完整的格式规范列表。

当您聚合或以其他方式对时间序列数据进行分组时,偶尔会有必要替换一系列datetime的时间字段,例如,将minutesecond字段替换为零:

In [121]: dt_hour = dt.replace(minute=0, second=0)
In [122]: dt_hour
Out[122]: datetime.datetime(2011, 10, 29, 20, 0)

由于datetime.datetime是不可变类型,这些方法总是会产生新对象。因此,在前面的例子中,dt不会被replace修改:

In [123]: dt
Out[123]: datetime.datetime(2011, 10, 29, 20, 30, 21)

两个datetime对象的差产生一个datetime.timedelta类型:

In [124]: dt2 = datetime(2011, 11, 15, 22, 30)
In [125]: delta = dt2 - dt
In [126]: delta
Out[126]: datetime.timedelta(days=17, seconds=7179)
In [127]: type(delta)
Out[127]: datetime.timedelta

输出timedelta(17, 7179)表示timedelta编码了 17 天和 7179 秒的偏移量。

timedelta添加到datetime会产生一个新的偏移datetime

In [128]: dt
Out[128]: datetime.datetime(2011, 10, 29, 20, 30, 21)
In [129]: dt + delta
Out[129]: datetime.datetime(2011, 11, 15, 22, 30)

控制流

Python 有几个内置关键字用于条件逻辑、循环和其他标准控制流概念,这些概念在其他编程语言中也可以找到。

if、elif 和 else

if语句是最为人熟知的控制流语句类型之一。它检查一个条件,如果为True,则评估后面的代码块:

x = -5
if x < 0:
 print("It's negative")

if语句后面可以选择跟随一个或多个elif代码块和一个全捕获的else代码块,如果所有条件都为False

if x < 0:
 print("It's negative")
elif x == 0:
 print("Equal to zero")
elif 0 < x < 5:
 print("Positive but smaller than 5")
else:
 print("Positive and larger than or equal to 5")

如果任何条件为True,则不会继续执行任何elifelse代码块。使用andor的复合条件,条件从左到右进行评估并会短路:

In [130]: a = 5; b = 7
In [131]: c = 8; d = 4
In [132]: if a < b or c > d:
 .....:     print("Made it")
Made it

在这个例子中,比较c > d永远不会被评估,因为第一个比较是True

也可以链接比较:

In [133]: 4 > 3 > 2 > 1
Out[133]: True
for 循环

for循环用于遍历集合(如列表或元组)或迭代器。for循环的标准语法是:

for value in collection:
 # do something with value

您可以使用continue关键字将for循环推进到下一个迭代,跳过代码块的其余部分。考虑这段代码,它对列表中的整数求和并跳过None值:

sequence = [1, 2, None, 4, None, 5]
total = 0
for value in sequence:
 if value is None:
 continue
 total += value

可以使用break关键字完全退出for循环。这段代码将列表元素求和,直到达到 5 为止:

sequence = [1, 2, 0, 4, 6, 5, 2, 1]
total_until_5 = 0
for value in sequence:
 if value == 5:
 break
 total_until_5 += value

break关键字仅终止最内层的for循环;任何外部的for循环将继续运行:

In [134]: for i in range(4):
 .....:     for j in range(4):
 .....:         if j > i:
 .....:             break
 .....:         print((i, j))
 .....:
(0, 0)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
(2, 2)
(3, 0)
(3, 1)
(3, 2)
(3, 3)

正如我们将在更详细地看到的,如果集合或迭代器中的元素是序列(例如元组或列表),它们可以方便地在for循环语句中解包为变量:

for a, b, c in iterator:
 # do something
while 循环

while循环指定一个条件和一个要执行的代码块,直到条件评估为False或循环被显式地使用break结束为止:

x = 256
total = 0
while x > 0:
 if total > 500:
 break
 total += x
 x = x // 2
pass

pass是 Python 中的“空操作”(或“什么也不做”)语句。它可以在不需要执行任何操作的代码块中使用(或作为尚未实现的代码的占位符);它仅仅是因为 Python 使用空格来分隔代码块:

if x < 0:
 print("negative!")
elif x == 0:
 # TODO: put something smart here
 pass
else:
 print("positive!")
范围

range函数生成一系列均匀间隔的整数:

In [135]: range(10)
Out[135]: range(0, 10)
In [136]: list(range(10))
Out[136]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

可以给定起始点、终点和步长(可以是负数):

In [137]: list(range(0, 20, 2))
Out[137]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
In [138]: list(range(5, 0, -1))
Out[138]: [5, 4, 3, 2, 1]

正如您所看到的,range 生成的整数是直到但不包括终点的。range 的一个常见用途是通过索引迭代序列:

In [139]: seq = [1, 2, 3, 4]
In [140]: for i in range(len(seq)):
 .....:     print(f"element {i}: {seq[i]}")
element 0: 1
element 1: 2
element 2: 3
element 3: 4

虽然您可以使用list等函数将range生成的所有整数存储在其他数据结构中,但通常默认的迭代器形式会是您想要的。这段代码将从 0 到 99,999 之间是 3 或 5 的倍数的所有数字相加:

In [141]: total = 0
In [142]: for i in range(100_000):
 .....:     # % is the modulo operator
 .....:     if i % 3 == 0 or i % 5 == 0:
 .....:         total += i
In [143]: print(total)
2333316668

虽然生成的范围可以任意大,但在任何给定时间内的内存使用可能非常小。

2.4 结论

本章简要介绍了一些基本的 Python 语言概念以及 IPython 和 Jupyter 编程环境。在下一章中,我将讨论许多内置数据类型、函数和输入输出工具,这些内容将在本书的其余部分中持续使用。


Python 数据分析(PYDA)第三版(一)(3)https://developer.aliyun.com/article/1482369

相关文章
|
1天前
|
SQL 数据可视化 数据挖掘
2024年8个Python高效数据分析的技巧。,2024年最新Python基础面试题2024
2024年8个Python高效数据分析的技巧。,2024年最新Python基础面试题2024
2024年8个Python高效数据分析的技巧。,2024年最新Python基础面试题2024
|
1天前
|
数据采集 SQL 数据挖掘
2024年8个Python高效数据分析的技巧_python 数据分析 效率,2024年最新阿里社招p7面试几轮
2024年8个Python高效数据分析的技巧_python 数据分析 效率,2024年最新阿里社招p7面试几轮
|
4天前
|
机器学习/深度学习 数据挖掘 Python
Python数据分析 | 泰坦尼克逻辑回归(下)
Python数据分析 | 泰坦尼克逻辑回归
8 1
|
4天前
|
机器学习/深度学习 数据挖掘 BI
Python数据分析 | 泰坦尼克逻辑回归(上)
Python数据分析 | 泰坦尼克逻辑回归
18 0
|
4天前
|
数据采集 数据挖掘 Python
Python数据分析 | 线性回归
Python数据分析 | 线性回归
15 1
|
4天前
|
机器学习/深度学习 数据采集 自然语言处理
10个 Python 小技巧,覆盖了90%的数据分析需求!_countries_lat_lon
10个 Python 小技巧,覆盖了90%的数据分析需求!_countries_lat_lon
|
4天前
|
数据采集 人工智能 数据挖掘
「一行分析」利用12000条招聘数据分析Python学习方向和就业方向
「一行分析」利用12000条招聘数据分析Python学习方向和就业方向
|
6天前
|
数据采集 数据可视化 数据挖掘
利用Python和Pandas库优化数据分析流程
在当今数据驱动的时代,数据分析已成为企业和个人决策的重要依据。Python作为一种强大且易于上手的编程语言,配合Pandas这一功能丰富的数据处理库,极大地简化了数据分析的流程。本文将探讨如何利用Python和Pandas库进行高效的数据清洗、转换、聚合以及可视化,从而优化数据分析的流程,提高数据分析的效率和准确性。
|
6天前
|
SQL 数据采集 数据挖掘
构建高效的Python数据处理流水线:使用Pandas和NumPy优化数据分析任务
在数据科学和分析领域,Python一直是最受欢迎的编程语言之一。本文将介绍如何通过使用Pandas和NumPy库构建高效的数据处理流水线,从而加速数据分析任务的执行。我们将讨论如何优化数据加载、清洗、转换和分析的过程,以及如何利用这些库中的强大功能来提高代码的性能和可维护性。
|
6天前
|
数据可视化 数据挖掘 BI
【Python】—— pandas 数据分析
【Python】—— pandas 数据分析
21 1