飞速搞定数据分析与处理-day2-Python入门

2023-08-07 13:10:50 浏览数 (1)

数据类型

对象

Python 中,一切皆对象(object)。数字、字符串、函数,以及我们会在本章中见到的其他所有东西,它们都是对象。

变量

在 Python 中,变量(variable)是通过等号给对象赋予的一个名字。

代码语言:javascript复制
In [1]: a = 3 
 b = 4 
 a   b 
Out[1]: 7
函数

现在你只需知道如何调用内置的函数,比如前面的示例中用到的 print 函数。要调用一个函数,需要在函数名后跟上一对圆括号,并在圆括号中提供参数,和数学记法几乎一模一样:

代码语言:javascript复制
function_name(argument1, argument2, ...)
属性和方法

在谈到对象时,变量被称作属性(attribute)1 ,函数被称作方法(method)。你可以通过属性来访问对象的数据,而方法可以用来执行某种操作。你可以通过点号来访问属性和方法,比如 myobject.attribute 和 myobject.method()。

数值类型

int 和 float 分别表示整数(integer)和浮点数(flfloating-point number)。通过内置的 type函数可以获得指定对象的类型:

代码语言:javascript复制
In [3]: type(4)
Out[3]: int
In [4]: type(4.4)
Out[4]: float

Excel 单元格永远保存的是浮点数当你从 Excel 单元格读取数字的时候,可能需要先把 float 转换为 int,然后才能把它传给一个需要整型参数的函数。原因是即使 Excel 显示的是整数,但在背后它总是以浮点数形式存储。

算术运算符

对数字进行运算需要用到像加号和减号这类算术运算符。除了求幂运算符,其他运算符都和 Excel 是类似的。

代码语言:javascript复制
In [9]: 3   4 # 加
Out[9]: 7
In [10]: 3 - 4 # 减
Out[10]: -1
In [11]: 3 / 4 # 除
Out[11]: 0.75
In [12]: 3 * 4 # 乘
Out[12]: 12
In [13]: 3**4 # 求幂(Excel用的是3^4的形式)
Out[13]: 81
In [14]: 3 * (3   4) # 使用圆括号
Out[14]: 21

布尔值

在 Python 中,布尔类型只有 True 和 False 两种取值。

代码语言:javascript复制
In [17]: 3 == 4 # 相等(Excel中是3=4)
Out[17]: False
In [18]: 3 != 4 # 不相等 (Excel中是3<>4)
Out[18]: True
In [19]: 3 < 4 # 小于,用>表示大于
Out[19]: True
In [20]: 3 <= 4 # 小于等于,用>=表示大于等于
Out[20]: True
In [21]: # 可以把逻辑表达式串联起来,
 # 等价于VBA中的10<12和12<17,
 # 以及Excel公式中的=AND(10<12, 12<17)
 10 < 12 < 17
Out[21]: True
In [22]: not True #“非”运算符
Out[22]: False
In [23]: False and True #“与”运算符
Out[23]: False
In [24]: False or True #“或”运算符
Out[24]: True

每个 Python 对象都可以被视作 True 或 False。大部分的对象会被视作 True,但 None(参见“None”)、False、0 或空数据类型 [ 比如空字符串(下一节中会讲到字符串)] 会被视作 False。

None 是一个内置的常量,按照官方文档的说法,它代表“没有值”(the absence of a value)。如果一个函数没有显式地返回值,那么它实际上返回的就是 None。在第三部分和第四部分中我们会看到,None 可以用来表示 Excel 中的空单元格。

以防万一,可以用 bool 构造器来检查一个对象是 True 还是 False

代码语言:javascript复制
In [25]: bool(2)
Out[25]: True
In [26]: bool(0)
Out[26]: False
In [27]: bool("some text") # 稍后会讲到字符串
Out[27]: True
In [28]: bool("")
Out[28]: False
In [29]: bool(None)
Out[29]: False

字符串

你可以用 来拼接字符串,或者用 * 来重复字符串的内容。当字符串中包含变量的值时,通常可以使用 f 字符串(f-string,格式化字符串字面量,formatted string literal 的缩写)来处理。

代码语言:javascript复制
In [33]: # 注意Python如何在一行中为多个变量赋予多个值
 first_adjective, second_adjective = "free", "open source"
 f"Python is {first_adjective} and {second_adjective}."
Out[33]: 'Python is free and open source.'

索引和切片

索引

Python 的索引从 0 开始,意思就是说序列的第一个元素通过 0 来引用。负索引从 -1 开始,你可以用负索引从序列末端引用元素。

代码语言:javascript复制
In [36]: language = "PYTHON"
In [37]: language[0]
Out[37]: 'P'
In [38]: language[1]
Out[38]: 'Y'
In [39]: language[-1]
Out[39]: 'N'
In [40]: language[-2]
Out[40]: 'O'

切片

Python 使用的是左闭右开区间,意思是切片区间包含 start,但不包含 stop。如果省略了start 或者 stop,则切片会分别包含从头开始或者从末尾开始的所有元素。step 决定了切片的方向和步长。如果令步长为 2,那么切片就会从左到右每两个元素取一个值;如果令步长为 -3,则切片会从右到左每 3 个元素取一个值。默认步长为 1

代码语言:javascript复制
In [41]: language[:3] # 同language[0:3]
Out[41]: 'PYT'
In [42]: language[1:3]
Out[42]: 'YT'
In [43]: language[-3:] # 同language[-3:6]
Out[43]: 'HON'
In [44]: language[-3:-1]
Out[44]: 'HO'
In [45]: language[::2] # 每两个元素取一个
Out[45]: 'PTO'
In [46]: language[-1:-4:-1] # 负步长从右到左
Out[46]: 'NOH'

数据结构

列表

列表(list)可以存储不同数据类型的多个对象。列表用途广泛,你可以随时使用它。创建列表的语法如下:

代码语言:javascript复制
[element1, element2, ...]

列表也是对象,也可以包含其他列表作为元素。我称之为嵌套列表(nested list)

代码语言:javascript复制
In [50]: nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

如果把这种嵌套列表写成多行,你就会发现列表可以很好地表示矩阵和工作表单元格。注意,这些方括号会隐式地让代码跨行(参见“跨行”)。通过索引和切片,你可以获得想要的任何元素。

代码语言:javascript复制
In [51]: cells = [[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]
In [52]: cells[1] # 第二行
Out[52]: [4, 5, 6]
In [53]: cells[1][1:] # 第二行的第二列和第三列
Out[53]: [5, 6]

你可以更改列表中的元素

代码语言:javascript复制
In [56]: users = ["Linda", "Brian"]
In [57]: users.append("Jennifer") # 最常用的操作是向列表末尾追加元素
 users
Out[57]: ['Linda', 'Brian', 'Jennifer']
In [58]: users.insert(0, "Kim") # 在索引0处插入"Kim"
 users
Out[58]: ['Kim', 'Linda', 'Brian', 'Jennifer']

要删除一个元素,可以使用 pop 或者 del。pop 是一个方法,而 del 是一种 Python 语句

代码语言:javascript复制
In [59]: users.pop() # 在默认情况下,移除并返回最后一个元素
Out[59]: 'Jennifer'
In [60]: users
Out[60]: ['Kim', 'Linda', 'Brian']
In [61]: del users[0] # del会移除指定索引处的元素

还可以对列表进行以下操作

代码语言:javascript复制
In [62]: len(users) # 长度
Out[62]: 2
In [63]: "Linda" in users # 检查users是否包含"Linda"
Out[63]: True
In [64]: print(sorted(users)) # 返回新的排好序的列表
 print(users) # 原列表保持不变
['Brian', 'Linda']
['Linda', 'Brian']
In [65]: users.sort() # 对原列表进行排序
 users
Out[65]: ['Brian', 'Linda']

注意,也可以把 len 和 in 用在字符串上

代码语言:javascript复制
In [66]: len("Python")
Out[66]: 6
In [67]: "free" in "Python is free and open source."
Out[67]: True

字典

字典(dictionary)是键到值的映射。你会经常遇到键 – 值对。创建字典最简单的方法如下

代码语言:javascript复制
{key1: value1, key2: value2, ...}

列表可以通过索引(如位置)来访问元素,字典则是通过键来访问元素。

代码语言:javascript复制
 "GBPUSD": 1.2454,
 "AUDUSD": 0.6161}
In [69]: exchange_rates["EURUSD"] # 访问EURUSD的汇率
Out[69]: 1.1152

下面的代码展示了如何修改既存的值以及添加新的键 – 值对

代码语言:javascript复制
In [70]: exchange_rates["EURUSD"] = 1.2 # 修改已经存在的值
 exchange_rates
Out[70]: {'EURUSD': 1.2, 'GBPUSD': 1.2454, 'AUDUSD': 0.6161}
In [71]: exchange_rates["CADUSD"] = 0.714 # 添加新的键–值对
 exchange_rates
Out[71]: {'EURUSD': 1.2, 'GBPUSD': 1.2454, 'AUDUSD': 0.6161, 'CADUSD': 0.714}  

合并两个或多个字典的最简单的办法是将字典解包(unpack)后再合并到一个新的字典中。在字典前加上两个星号就可以进行解包。如果第二个字典包含第一个字典中的键,那么第一个字典中对应的值会被覆盖。通过观察 GBPUSD 汇率的变化,可以了解到发生了什么

代码语言:javascript复制
In [72]: {**exchange_rates, **{"SGDUSD": 0.7004, "GBPUSD": 1.2222}}
Out[72]: {'EURUSD': 1.2,
 'GBPUSD': 1.2222,
 'AUDUSD': 0.6161,
 'CADUSD': 0.714,
 'SGDUSD': 0.7004}

Python 3.9 引入了管道符号作为专门的字典合并运算符。上面的表达式可以简化成如下

代码语言:javascript复制
exchange_rates | {"SGDUSD": 0.7004, "GBPUSD": 1.2222}

很多对象可以用作键,下面就是用整数作为键的例子

代码语言:javascript复制
In [73]: currencies = {1: "EUR", 2: "USD", 3: "AUD"}
In [74]: currencies[1]
Out[74]: 'EUR'

get 方法可以在键不存在时返回一个默认值

代码语言:javascript复制
In [75]: # currencies[100]会引发异常
 # 除了100,还可以尝试任何不存在的键
 currencies.get(100, "N/A")
Out[75]: 'N/A'

元组

元组(tuple)和列表类似,只不过它们是不可变的(immutable):一旦被创建,它们的元素就无法被修改。虽然很多时候元组和列表可以互换使用,但对于那些在整个程序中都不会发生改变的集合来说,元组是不二之选。元组是通过多个被逗号分隔的值创建的

代码语言:javascript复制
mytuple = element1, element2, ...

使用圆括号通常更易于阅读

代码语言:javascript复制
In [76]: currencies = ("EUR", "GBP", "AUD")

可以使用访问数组的方法来访问元组,只是不能修改元组的元素。拼接元组会在“暗地里”创建一个新的元组,然后再把新元组绑定到你的变量上

代码语言:javascript复制
In [77]: currencies[0] # 访问第一个元素
Out[77]: 'EUR'
In [78]: # 拼接元组会返回一个新元组
 currencies   ("SGD",)
Out[78]: ('EUR', 'GBP', 'AUD', 'SGD')

集合

集合(set)是一种没有重复元素的集合(collection) 。你自然可以把集合用于集合论的运算中,但在实践中它们经常被用于列表去重或者元组去重。使用花括号创建集合

代码语言:javascript复制
{element1, element2, ...}

要对列表或者元组进行去重,可以像下面这样使用 set 构造器

代码语言:javascript复制
In [79]: set(["USD", "USD", "SGD", "EUR", "USD", "EUR"])
Out[79]: {'EUR', 'SGD', 'USD'}

除此之外,还可以进行像交集和并集之类的集合论运算

代码语言:javascript复制
In [80]: portfolio1 = {"USD", "EUR", "SGD", "CHF"}
 portfolio2 = {"EUR", "SGD", "CAD"}
In [81]: # 同portfolio2.union(portfolio1)
 portfolio1.union(portfolio2)
Out[81]: {'CAD', 'CHF', 'EUR', 'SGD', 'USD'}
In [82]: # 同portfolio2.intersection(portfolio1)
 portfolio1.intersection(portfolio2)

控制流

代码块和pass语句

代码块(code block)界定了一段源代码,这段代码会用于一些特定的目的。例如,可以使用代码块来界定循环的主体部分,它也构成了一个函数的定义。

代码语言:javascript复制
if condition:
 pass # Do nothing

代码块的前一行总是会以冒号结尾。一旦某一行没有被缩进,代码块就自然结束了。因此你需要使用 pass 语句来创建一个什么都不做的假代码块。

if语句和条件表达式

条件表达式(conditional expression)或者三元运算符(ternary operator)可以让你以一种更紧凑的形式编写 if/else 语句

代码语言:javascript复制
In [88]: is_important = False
 print("important") if is_important else print("not important")
not important

for循环和while循环

for 循环会对一个序列 [ 比如列表、元组、字符串(记住,字符串就是字符的序列)] 进行迭代。

代码语言:javascript复制
In [89]: currencies = ["USD", "GBP", "AUD"]
 for currency in currencies:
 print(currency)
USD 
GBP
AUD

items 方法可以以元组的形式同时获得键和对应的值

代码语言:javascript复制
In [96]: for currency_pair, exchange_rate in exchange_rates.items():
 print(currency_pair, exchange_rate)
EURUSD 1.1152
GBPUSD 1.2454
AUDUSD 0.6161

break 语句可以跳出循环

代码语言:javascript复制
In [97]: for i in range(15):
 if i == 2:
 break 
 else:
 print(i)
0
1

可以使用 continue 语句跳过本轮循环的剩余部分。

代码语言:javascript复制
In [98]: for i in range(4):
 if i == 2:
 continue
 else:
 print(i)
0 
1
3

列表、字典和集合推导式

列表、字典和集合推导式在技术上是一种创建对应数据结构的方法,不过很多时候人们用它们来代替 for 循环——这也是为什么我要在这里介绍推导式。

假设有如下的货币名称对,你想把美元在后面的元素挑出来。你可能会写下面这样一个 for 循环

代码语言:javascript复制
In [101]: currency_pairs = ["USDJPY", "USDGBP", "USDCHF", "USDCAD", "AUDUSD", "NZDUSD"]
In [102]: usd_quote = []
         for pair in currency_pairs:
             if pair[3:] == "USD":
                 usd_quote.append(pair[:3])
         usd_quote
Out[102]: ['AUD', 'NZD']

这种情况用列表推导式(list comprehension)会更简单。列表推导式是一种更简洁的列表创建方法。你可以通过下面的例子体会它的语法,这行代码和前面的 for 循环完全等效

代码语言:javascript复制
In [103]: [pair[:3] for pair in currency_pairs if pair[3:] == "USD"]
Out[103]: ['AUD', 'NZD']

如果没有限制条件,则可以直接省略 if 部分。如果要交换前后两种货币,那么可以这样做

代码语言:javascript复制
In [104]: [pair[3:]   pair[:3] for pair in currency_pairs]
Out[104]: ['JPYUSD', 'GBPUSD', 'CHFUSD', 'CADUSD', 'USDAUD', 'USDNZD']

字典也有字典推导式

代码语言:javascript复制
In [105]: exchange_rates = {"EURUSD": 1.1152,
 "GBPUSD": 1.2454,
 "AUDUSD": 0.6161}
 {k: v * 100 for (k, v) in exchange_rates.items()}
Out[105]: {'EURUSD': 111.52, 'GBPUSD': 124.54, 'AUDUSD': 61.61}

集合也有集合推导式

代码语言:javascript复制
In [106]: {s   "USD" for s in ["EUR", "GBP", "EUR", "NZD", "NZD"]}
Out[106]: {'EURUSD', 'GBPUSD', 'NZDUSD'}

组织代码

函数

函数是所有编程语言中最重要的构造,它们可以让你在程序的任何地方重用同样的代码。

代码语言:javascript复制
def function_name(required_argument, optional_argument=default_value, ...):
 return value1, value2, ...

调用函数要调用一个函数,可以在函数名后加上一对圆括号,并在其中给出参数。

位置参数:如果将一个值作为位置参数传递,那么这个值会被传递给对应位置上的参数。

关键字参数:以 arg_name=value 这种形式传递的参数,就是关键字参数(keyword argument)。关键字参数的好处是可以以任意顺序传递参数,并且对于读者来说更加直观易懂。

模块和import语句

当你为大型项目编写代码时,在一定的时候会需要将代码分成不同的文件,从而保持一种可维护的结构。正如第 2 章所展示的那样,Python 文件的扩展名为 .py,通常我们会把主要的文件称作脚本(script)。如果你想让你的主脚本获得来自其他文件的概念,则需要先导入(import)那个功能。

模块只会被导入一次,如果再一次运行 import temperature 单元格,你会注意到 print 函数不会输出任何内容。

不要让你的脚本和既存的包重名

一个常见的错误根源是给你的 Python 文件取一个和既存的包同样的名字。如果你要创建一个测试 pandas 功能的文件,那么不要将其命名为 pandas.py,因为这会造成冲突。

datetime类

要实例化 datetime 对象,需要像下面这样调用对应的类

代码语言:javascript复制
import datetime as dt
dt.datetime(year, month, day, hour, minute, second, microsecond, timezone)

PEP 8:Python风格指南

➊ 在文件顶部用文档字符串(docstring)解释这个脚本或者模块做了些什么。文档字符串是一种特殊的字符串,它用 3 个引号引用。除了作为代码的文档,它还可以用来编写跨越多行的字符串。如果你的字符串中有很多双引号或单引号,那么也可以用文档字符串来避免转义。我们会在第 11 章中看到,编写跨越多行的 SQL 查询时,文档字符串也很好用。

➋ 所有的导入语句都应该放在文件顶部,一行一个导入。从标准库导入的内容放在前面,然后是第三方包,最后是自己编写的模块。不过这个例子中只用到了标准库。

➌ 用大写字母和下划线表示常量。每行的长度不超过 79 个字符。尽可能地利用圆括号、方括号或花括号隐式跨行。

➍ 类、函数和其他代码之间用两个空行隔开。

➎ 尽管很多类像 datetime 一样使用小写字母命名,但是你自己编写的类也应该使用首字母大写的名称(CapitalizedWords)。

➏ 行内注释应该和代码间隔至少两个空格。代码块应该用 4 个空格缩进。

➐ 在能够提高可读性的情况下,函数和参数应该使用小写字母和下划线命名。不要在参数名和默认值之间使用空格。

➑ 函数的文档字符串应当列出函数参数并解释其意义。

➒ 冒号前后不要使用空格。

➓ 可以在算术运算符前后使用空格。如果同时使用了优先级不同的运算符,则应当考虑在优先级最低的运算符前后添加空格

PEP 8和VS Code

在使用 VS Code 时,确保代码严格遵循 PEP 8 的最简单方法是使用代码检查器(linter)。

0 人点赞