Python 02 | 快速入门之变量与数据类型

Introduction

之前的几次更新中我们对第三方库NumPy进行了较为系统的学习,并且将其与地球科学应用进行了一定程度的联系。

正式迈向地球科学应用之前,我们还需要进修PandasMatplotlib。它们分别用于数据帧(DataFrame,或者可以理解为表格)处理和可视化,以便我们快速地处理时间序列和对多个变量进行分析等。

但在我准备按照上次的预告准备开始Pandas时,发现如果把Python基本语法再往后延就会造成很多的麻烦。

一种显而易见的状况就是,我们使用Excel表格通常需要一个列名加以区分每列的内容是什么。那么在Python中,当我们创建一个DataFrame,同时指定其列名。很常用的一种方式就是使用字典,但是如果我们没有提出字典的概念就会很尴尬。就需要像之前用的列表一样,需要花一些篇幅去拓展,导致整个体系很臃肿。

所以,这里就打算先花上两期快速引入Python基本语法,为后续内容扫除障碍。今天就从Python的变量与数据类型说起,下一次我们简要介绍控制流和函数。掌握了这些内容,便可满足基本的Python程序设计。

变量与赋值

变量是Python中最基本的单元,用于储存数据(任何类型内容都可以赋值给指定的变量名)。我们任何需要计算机完成的操作都需要将对应的计算内容赋值给变量,计算才能进行。

值得一提的是,与CFortran等语言不同,Python不需要首先声明变量的数据类型,而是能自动识别变量的类型。(这种方式当然简化了编程语言的学习,不需要考虑诸如内存控制等诸多细节问题,但同时也一定程度造成了Python速度逊于其他语言。)

赋值

所谓赋值,就是使用赋值符号=将右侧的值赋给左侧的变量。

由于Python是动态语言,变量类型可以随时改变,赋值时不需要声明变量的数据类型。

因此,当我们进行赋值时,变量同时也创建出来。

temperature = 15
wind_direction = 'N'
city = 'Peking (北京)'
msg = 'Hello World!'

print(temperature)
print(wind_direction)
print(city)
print(msg)
15
N
Peking (北京)
Hello World!

上面我们简单地进行了几个赋值操作,可以看到无论是数字字符(单个字母)、字符串(单词或句子等),变量均可以接受。

实际上,无论是我们前面提到的列表,或是接下来将讲到的字典、元组等,甚至是后续我们直接将ShapefileNetCDF栅格读取为一个变量均是可以的。

变量组成了Python程序设计的零件。

数据类型之数据个体

上面给变量赋值的操作中,我们用到了几种Python内置的原生数据类型。那么它们具体包含哪些主要内容,我们一起来看一看。

数值型

既然我们的电脑叫做计算机,自然跟计算相关了。因此,最首要的就是我们的数值类型。主要包括:整数int、浮点数float、复数complex

下面我们来看看怎么表示它们:

int_var = 10
float_var = 3.14
complex_var = 2 + 3j
sci_var = 3.14e10                   # 使用科学计数法表示的浮点数,3.14 * 10^10
sci_var2 = 3.14e-3                  # 3.14 * 10^-3

print(int_var, type(int_var))
print(float_var, type(float_var))
print(complex_var, type(complex_var))
print(sci_var, type(sci_var))
print(sci_var2, type(sci_var2))
10 <class 'int'>
3.14 <class 'float'>
(2+3j) <class 'complex'>
31400000000.0 <class 'float'>
0.00314 <class 'float'>

这里我们用到了Python的内置函数type()来识别变量的数据类型,它可以广泛地应用于各种场景,以确保数据类型满足我们的要求。

既然我们创建出了数字,自然要计算了。以下就是Python内置的基本计算方法:

a = 10
b = 3
c = a + b
d = a - b
e = a * b
f = a / b
g = a ** b              # 乘方
h = a // b              # 整除
i = a % b               # 取余

print(a, b, c, d, e, f, g, h, i)
10 3 13 7 30 3.3333333333333335 1000 3 1

细心的朋友可能发现了,以上计算实际上有一处是不正确的。那就是10/3的结果应当是1/3,是一个无限循环小数,但上面的结果最后一位却是5,这显然是存在精度误差的。

这种情况是由于浮点型精度溢出导致的,因为计算机仅能存储有限位数的小数。一般而言,这种误差不至于于影响我们的总体结果,因此可以忽略不计。

此外,Python中的计算符还可以使用一种特殊写法。该写法类似于我们前文中提到的浅拷贝后计算,由于共享内存地址,运行速度略快于上面的写法:

a = 10

a += 1
print(a)

a -= 2
print(a)

a *= 3
print(a)

a /= 4
print(a)

a **= 2
print(a)

a //= 3
print(a)

a %= 5
print(a)
11
9
27
6.75
45.5625
15.0
0.0

字符型

讲完了数值型,接下来自然我们需要知道那一堆数字对应的实际意义。用另一堆数字作为代号来表征含义而代替文字未免过于抽象,所以这里我们引入了字符型。

city = 'プリンストン'
province = '新泽西州'
nation = "U.S."

print("I come from", city, "in", province, "of", nation)
I come from プリンストン in 新泽西州 of U.S.

可以看到,Python能接受丰富的字符类型。

这里我们混用了''""两种引号,在Python中它们没有任何区别,可以随意使用。需要注意与其他语言中的用法区分,如Julia""表示字符串,而''仅表示字符。

字符串由多个字符组成,因此可以对字符串进行各种操作,如拼接、切片、索引等。

looong_string = "This is a very looooong string that is used to demonstrate the use of Python's string manipulation functions!"

# 索引/切片
print(looong_string[0])
print(looong_string[-1])
print(looong_string[10:23])
print(looong_string[-10:])
print(looong_string[::-1], '\n')

# 大小写转换
print(looong_string.upper())                # 全部大写
print(looong_string.lower())                # 全部小写
print(looong_string.capitalize())           # 首字母大写
print(looong_string.title(), '\n')          # 每个单词的首字母大写

# 字符串拼接
print("Hello World! " + looong_string + '\nActually, a very looooong string.\n')

# 字符串替换
print(looong_string.replace('looooong', 'long'), '\n')

# 字符串分割
print(looong_string.split(' '))             # 以空格分割为列表
print(looong_string.split(' ', 2))          # 以空格分割为列表,只分割2次

# 字符串统计
print(looong_string.count('o'))             # 统计字符o出现的次数
print(looong_string.find('string'))         # 找出子字符串string的位置
print(looong_string.rfind('string'))        # 找出子字符串string的位置,从右边开始查找
T
!
very looooong
functions!
!snoitcnuf noitalupinam gnirts s'nohtyP fo esu eht etartsnomed ot desu si taht gnirts gnoooool yrev a si sihT 

THIS IS A VERY LOOOOONG STRING THAT IS USED TO DEMONSTRATE THE USE OF PYTHON'S STRING MANIPULATION FUNCTIONS!
this is a very looooong string that is used to demonstrate the use of python's string manipulation functions!
This is a very looooong string that is used to demonstrate the use of python's string manipulation functions!
This Is A Very Looooong String That Is Used To Demonstrate The Use Of Python'S String Manipulation Functions! 

Hello World! This is a very looooong string that is used to demonstrate the use of Python's string manipulation functions!
Actually, a very looooong string.

This is a very long string that is used to demonstrate the use of Python's string manipulation functions! 

['This', 'is', 'a', 'very', 'looooong', 'string', 'that', 'is', 'used', 'to', 'demonstrate', 'the', 'use', 'of', "Python's", 'string', 'manipulation', 'functions!']
['This', 'is', "a very looooong string that is used to demonstrate the use of Python's string manipulation functions!"]
11
24
79

布尔型

很多时候我们并不局限于基本的数字运算,逻辑运算也是其中很重要的内容。于是,判断不同变量间的关系便需要使用到布尔型数据。

print(3 == 3.0)                                         # 使用==判断是否相等
print(3 != 3.1)                                         # 使用!=判断是否不等
print('a' in 'apple')                                   # 使用in判断是否包含
print('a' not in 'apple')                               # 使用not in判断是否不包含
print(True == 1)                                        # 特殊用法,True和1相等
print(False == 0)                                       # 特殊用法,False和0相等
print(9 > 8 > 7)                                        # 链式比较
print(9 > 8 < 7)                                        # 链式比较
print('a' in 'apple' and 'e' in 'banana')               # 使用and判断多个条件是否都成立
print('a' in 'apple' or 'e' in 'banana')                # 使用or判断多个条件是否有成立

# 可用于判断字符串首尾内容
looong_string = "This is a very looooong string that is used to demonstrate the use of Python's string manipulation functions!"
print(looong_string.startswith('This'))                 # 判断字符串是否以This开头
print(looong_string.endswith('functions!'))             # 判断字符串是否以functions!结尾
True
True
True
False
True
True
True
False
False
True
True
True

数据类型转换

基于以上数据类型,我们可以非常容易地在它们之间互相转换。

a = 10.5
print(a, type(a))

b = int(a)
print(b, type(b))

c = str(a)
print(c, type(c))
10.5 <class 'float'>
10 <class 'int'>
10.5 <class 'str'>

数据类型之数据容器

上面我们介绍的数据类型均为单个值(仅有字符串有所不同,若由多个字符组成可使用切片和索引提取部分内容),而由多个这样的值组成整体,便形成了数据集群。

我们把可以存放多个值的这些数组类型暂且称为数据容器吧。

原生Python中内置数据容器主要为以下四种:列表、元组、集合、字典。

列表 (List)

列表是可以存储多个值的有序集合,可以包含任意类型的数据,使用[]表示。我们在第一期就提到了它,并且已经使用了很多次。

我们通过一个代码块对它简单回顾:

ls = [1, 'Alice', 3.14, True, '上海', 'プリンストン']

# 索引/切片
print(ls)
print(ls[1])
print(ls[-3])
print(ls[1:3])
print(ls[::2])
print(ls[::-1])
print(ls[-2:], '\n')

# 赋值修改
ls[1] = 'Iris'
print(ls)

# 追加
ls.append('Antarctica')
print(ls)
[1, 'Alice', 3.14, True, '上海', 'プリンストン']
Alice
True
['Alice', 3.14]
[1, 3.14, '上海']
['プリンストン', '上海', True, 3.14, 'Alice', 1]
['上海', 'プリンストン'] 

[1, 'Iris', 3.14, True, '上海', 'プリンストン']
[1, 'Iris', 3.14, True, '上海', 'プリンストン', 'Antarctica']

以上是我们已经很熟悉的列表操作,下面我们再补充几个列表用法。

ls = [1, 'Iris', 3.14, True, '上海', 'プリンストン', 'Antarctica']

print(len(ls))                       # 列表长度

print('Iris' in ls)                  # 判断'Iris'是否在列表中

ls.pop()                             # 删除最后一个元素
print(ls)

ls.pop(2)                            # 删除索引为2的元素
print(ls)

ls.remove('上海')                    # 删除值为'上海'的元素
print(ls)

ls.insert(2, 'Neptune')              # 在索引为2的位置插入'Neptune'元素
print(ls)

print(ls.index('Neptune'))           # 查找值为'Neptune'的元素的索引

ls.reverse()                         # 反转列表
print(ls)

ls0 = [2, 4, 6, 8, 10]
ls.extend(ls0)                       # 合并列表
print(ls)

ls1 = ls + ls0                       # 同上
print(ls1)

ls0.sort()                           # 排序列表
print(ls0)

ls0.sort(reverse=True)               # 反向排序列表
print(ls0)

ls.clear()                           # 清空列表
print(ls)
7
True
[1, 'Iris', 3.14, True, '上海', 'プリンストン']
[1, 'Iris', True, '上海', 'プリンストン']
[1, 'Iris', True, 'プリンストン']
[1, 'Iris', 'Neptune', True, 'プリンストン']
2
['プリンストン', True, 'Neptune', 'Iris', 1]
['プリンストン', True, 'Neptune', 'Iris', 1, 2, 4, 6, 8, 10]
['プリンストン', True, 'Neptune', 'Iris', 1, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10]
[2, 4, 6, 8, 10]
[10, 8, 6, 4, 2]
[]

元组 (Tuple)

元组,简而言之,它与列表其他特性几乎一致,唯一区别在于它的不可变性,意味着它一旦创建出来将不可像数组一样使用赋值进行修改。

因此,元组很适合用来储存我们建模中用到的常数,以免不小心修改。它的符号使用()

tp = (1, 'Iris', 3.14, True, '上海', 'プリンストン', 'Antarctica')

# 索引/切片
print(tp[1])
print(tp[1:3])
print(tp[-3:])

print(tp.index('Iris'))        # 索引元素位置
print(len(tp))                 # 元组长度

tp[1] = 'Setosa'                # 使用赋值语句修改元组元素不可用
Iris
('Iris', 3.14)
('上海', 'プリンストン', 'Antarctica')
1
7



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In[75], line 11
      8 print(tp.index('Iris'))        # 索引元素位置
      9 print(len(tp))                 # 元组长度
---> 11 tp[1] = 'Setosa'                # 使用赋值语句修改元组元素不可用


TypeError: 'tuple' object does not support item assignment

集合 (Set)

集合与数学中的概念类似,表示的是一组无序且唯一的元素。其符号使用{}

set1 = {1, 2, 3, 4, 5}

set1.add(6)                       # 添加元素
print(set1)

set1.remove(2)                    # 删除元素
print(set1)

print(2 in set1)                  # 判断元素是否存在

set1[0]                           # 由于集合是无序的,因此无法通过索引访问元素

{1, 2, 3, 4, 5, 6}
{1, 3, 4, 5, 6}
False



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In[83], line 11
      7 print(set1)
      9 print(2 in set1)                  # 判断元素是否存在
---> 11 set1[0]                           # 由于集合是无序的,因此无法通过索引访问元素


TypeError: 'set' object is not subscriptable

集合的主要用法也与数学中一致,主要用于求取并集、交集、差集、对称差集等。

set0 = {1, 2, 3, 4, 5}
set1 = {4, 5, 6, 7, 8}

set2 = set0.union(set1)                                 # 并集
print(set2)

set3 = set0.intersection(set1)                          # 交集
print(set3)

set4 = set0.difference(set1)                            # 差集
print(set4)

set5 = set0.symmetric_difference(set1)                   # 对称差集
print(set5)
{1, 2, 3, 4, 5, 6, 7, 8}
{4, 5}
{1, 2, 3}
{1, 2, 3, 6, 7, 8}

此外,集合可以直接使用set()函数创建。由于集合的值是唯一的,我们可以拓展一种非设计者本意的邪用法,使用它来求取唯一值(去重):

ls = [1, 3, 1, 0, 2, 4, 1, 5, 6, 2, 3, 4, 5, 6, 7, 8, 9, 10]

set0 = set(ls)
print(set0)
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

字典 (Dictionary)

字典是Python中的一种无序的键值对集合,用于存储键和与其关联的值。我们可以按它的字面意思理解,《新华字典》中每个拼音对应了很多字。我们可以将拼音认为是键,字则是值。

于是,我们知道以下规律:字典的键是唯一的(每个拼音在目录中只出现一次),值却是可以任意长度的(一个拼音可以对应多个字)。

字典的创建使用{},并使用:分隔键和值。

continent_info = {'name': 'Europe', 
               'population': 73000000, 
               'area': 102e4, 
               'abbreviation': 'EU', 
               'capital': 'Brussels', 
               'language': ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'],
               'bigcity': ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm']
               }

print(continent_info)
{'name': 'Europe', 'population': 73000000, 'area': 1020000.0, 'abbreviation': 'EU', 'capital': 'Brussels', 'language': ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'], 'bigcity': ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm']}

于是,我们可以根据键名索引、添加、删除、修改对应的值:

print(continent_info.keys())                           # 使用keys()方法获取所有键
print(continent_info.values())                         # 使用values()方法获取所有值

print(continent_info['name'])                          # 使用键索引值
print(continent_info['bigcity'][4])                    # 从多个值中继续索引

del continent_info['area']                              # 使用del删除键值对
print(continent_info)

continent_info.pop('population')                       # 使用pop删除键值对
print(continent_info)

continent_info['area'] = 102e4                           # 直接赋值添加键值对
print(continent_info)

continent_info.update({'population': 732000000, 'Chinese name': '欧洲'})          # 使用update更新键值对
print(continent_info)

print('capital' in continent_info)                      # 使用in判断键是否存在
dict_keys(['name', 'population', 'area', 'abbreviation', 'capital', 'language', 'bigcity'])
dict_values(['Europe', 73000000, 1020000.0, 'EU', 'Brussels', ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'], ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm']])
Europe
Zurich
{'name': 'Europe', 'population': 73000000, 'abbreviation': 'EU', 'capital': 'Brussels', 'language': ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'], 'bigcity': ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm']}
{'name': 'Europe', 'abbreviation': 'EU', 'capital': 'Brussels', 'language': ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'], 'bigcity': ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm']}
{'name': 'Europe', 'abbreviation': 'EU', 'capital': 'Brussels', 'language': ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'], 'bigcity': ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm'], 'area': 1020000.0}
{'name': 'Europe', 'abbreviation': 'EU', 'capital': 'Brussels', 'language': ['English', 'French', 'German', 'Italian', 'Spanish', 'Portuguese', 'Romanian', 'Turkish', 'Russian'], 'bigcity': ['Paris', 'London', 'Berlin', 'Rome', 'Zurich', 'Moscow', 'Vienna', 'Barcelona', 'Istanbul', 'Oslo', 'Stockholm'], 'area': 1020000.0, 'population': 732000000, 'Chinese name': '欧洲'}
True

此外,字典也存在上一期中提到的数组拷贝的问题。默认为浅拷贝,这将导致修改字典的值也会影响原字典。

# 浅拷贝
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = dict1
dict2['d'] = 4

print(dict1)
print(dict2, '\n')

# 深拷贝
dict2 = dict1.copy()
dict2['e'] = 5

print(dict1)
print(dict2)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
{'a': 1, 'b': 2, 'c': 3, 'd': 4} 

{'a': 1, 'b': 2, 'c': 3, 'd': 4}
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

后记

以上就是本期的内容,主要对Python的基本语法进行了一些介绍。毫无疑问,对于有一定编程基础的朋友来说,这些东西比起C语言之类的,可以说是简单了许多。而且它跟MATLAB、R等语言也存在很多相似之处,很适合多赛道选手无缝切换。

问题反而在于内容容量过多,纷繁复杂。但只是需要一些时间消化,依然是一门很适合快速入门的程序语言。说到底还是多写吧,尽可能把重复性工作使用代码解决,既提高了效率,也进阶了技能。

那么我们下期再继续聊Python的控制流和函数,这个才是我们实现批处理的核心。

下期再见!

Manuscript: RitasCake
Proof: Philero; RitasCake

获取更多资讯,欢迎订阅微信公众号:Westerlies

跳转和鲸社区,云端运行本文案例。

关注我们,阅读原文跳转和鲸社区

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值