阅读本文大概需要 10 分钟

前言

语言是人类最重要的交际工具,世界上有成千上万种语言,至今无法统计出具体的数字,但无论怎样,本质上语言所起到的作用,就是将人类想要表达意思,通过某种 双方可以理解的语法翻译出来。而计算机语言也是如此,本质上就是一种翻译语言。

英语之所以能成为世界通用语言,抛开西方资本扩张时期,全球范围内建立殖民地以外,其很大一部分原因是因为它简单,不需要复杂的语法,人们很快就能学会。

这点可能会有人反驳:英语能这么流行还不是因为在那个时期,殖民者强迫人们去说英语。学过一点历史的人知道,当年成吉思汗横扫全球,版图横跨欧亚非。照你这么说,现在全世界都应该说中国话,都按中国人的习惯来,现在老外见面打招呼应该是 ”可吃饭了?“,你见过?

而 Python 恰巧在计算机语言中就是一门简单的语言。

Python 中的数据类型

任何一门语言,都是由最基本的数据来构成的,而 Python 中的数据类型分为两类——固定类型,可变类型。这里只讲固定类型。

标识符与关键字

在了解固定类型之前,我们得先知道一些变量的命名规则和一些约定。

创建一个数据时,我们要么将其赋值于一个变量(对象引用),要么直接引用( Python 中进行赋值操作时,其实就是一个对象引用对内存中存放数据的对象进行引用)。而为这个对象引用赋予的名称就叫做标识符,也就是人口相传的变量。

Python 的标识符命名必须符合两条规则,并遵循某些约定。

1. 两条规则

<1> 变量必须由字母数字下划线' _ '组成,且开头必须是字母下划线

<2> 变量不能与关键字重名。

2. 约定

<1> 不要使用 Python 中已经预定义的标识符。

<2> 避免使用开头和结尾都使用' _ '(下划线)的命名方式。

Python 中所有关键字

 >>> import keyword
 >>> keyword.kwlist
 ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 
  'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 
  'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 
  'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

固定类型

固定类型也叫不可变类型,即已经在内存中存放的数据,只能引用,无法修改。

在一些函数中,你可能会看到函数修改了数据的假象,如

>>> num = 10
>>> def change():
...     num = 100
...     print('num = %d'%num)
... 
>>> change()
num = 100

看似修改了num的值,其实并没有!

>>> num = 10
>>> def change():
...     num = 100
...     print('num = %d'%num)
... 
>>> change()
num = 100
>>> num
10

可以看到num的值并没有被修改!

如果你看了上一篇文章,可以很容易就发现其中涉及到的 ‘全局变量’ 和 ‘局部变量’ 问题,其实就是对象引用问题。这个后面会单独写一篇文章说明。

Python 怎么实现对象不可变呢?

在 Python 中只要对象是可哈希的,那么它就是不可变对象。相反,则是可变对象。

那么哈希又是什么呢?

实际上这里的哈希,是一个函数hash(),它只能对唯一确定的’数’进行运算,并返回一个绝对不相同的数,而对象的id正好符合这一性质,它会根据给定的对象的id,返回一个唯一的hash值。

>>> a = 100
>>> hash(a)
100

而 Python 中所有对象自身都有一个__hash__方法,该方法会算出自身idhash值。

>>> a = 100
>>> a.__hash__()
100

通过比较对对象使用hash()函数计算出来的hash值,和对象自身__hash__方法计算出来的hash值,来确定是否是同一个对象,也就是固定类型里面的不可变对象。

而由于可变类型里的对象的id是不断变化的,故没法进行hash运算,它们叫做可变对象。

>>> b = [1,2]
>>> id(b)
46772808
>>> id([1,2])
46771976

>>> hash(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

并且HASH在计算同一个值时,所得到的hash值是相同的!

又因为所有尝试通过调用不可变对象的 ‘方法’,或函数,来改变不可变对象的值,其返回的都是一个新的对象,原对象并没有被改变。这样实现了不可变对象永远不可变!

了解了固定类型的本质后,就可以介绍有哪几种数据类型是固定类型了。

固定类型只有 5 种,整型 int,浮点型 float,字符型 str,元组 tuple,和集合里的 forzenset

常用的是前四种,介于字符串涉及的内容很多,决定和元组一起放到下一篇。

1. 整型-int

整数的大小仅取决于机器的内存大小,也就是说没有所谓无穷大概念,没有 99999 后面跟着无穷无尽个 9999 这种说法,当你的内存很小时,你要取一个 99 的 n 次方,计算机就会返回一个 MerryError ,告诉你:你想多了。。。整数默认采用十进制。

<1> 整型计算

常用数学函数与操作符都可用于整型,如加减乘( +,—,\* ),

>>> a = 100
>>> b = 200
>>> a + b
300

计算机里的除法其实并不是简单的数学除法,它根据数学除法的定义,将除法分为两个部分,普通意义上的除法/,和取模%,即取余数。

>>> a = 8
>>> b = 5
>>> a / b
1.6

>>> a % b
3

需要注意的是 Python 中的除法,返回的并不是一个整型,而是一个浮点型。

>>> a = 2
>>> b = 1
>>> a / b
2.0

如果一定要在除法运算中,得到一个整型,可以通过截除运算//,舍弃小数部分,向下取整

>>> a = -3 
>>> b = 2
>>> a // b # 结果应该是 -1.5,但由于截除运算是向下取整,故为 -2
-2

<2> 整型转换

在进行赋值运算过程中,经常会遇到需要将某个其他类型的对象转换成整型的情况,如l = int('1'),就是将一个字符型的'1'转换成整型1。这种情况称为数据类型转换。

在数据类型转换当中,一般有三种情况:

Ⅰ. 数据类型函数没有参数时,如 i = int()

>>> i = int()
>>> i 
0   
>>> type(i)
<class 'int'>

这里会返回一个默认值 0,所有数据类型函数如 float(),str()等,都可以不带参数进行调用。

Ⅱ. 数据类型函数含有参数时,当参数类型和数据类型函数一致时,如

>>> i = int(2)
>>> i
2
>>> type(i)
<class 'int'>

# 这里会将`int`类型的对象`2` 赋值给 i。
# 实际上是创建了一个新对象,新对象是原始对象的浅拷贝,暂且不说。

当参数类型与数据类型函数不一致时,此时会尝试数据转换,如

>>> i = '2'
>>> type(i)
<class 'str'>
>>> j = int(i)
>>> j
2
>>> type(j)
<class 'int'>

当参数支持给定的数据类型转换,但转换失败,会返回一个 ValueError异常,如

>>> i = int('')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''

当参数不支持给定的数据类型转换,会返回一个 TyprError 异常,如

i = int([])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

Ⅲ. 数据类型函数含有两个或多个参数时(并不是所有数据类型函数都支持),如

>>> i = int('100',2)
>>> i
4
>>> type(2)
<class 'int'>

# 意思是将 2 进制下的 '100' 转换为整型 4,整型默认为 10 进制。

常用的整数计算

语法意义
x | y表示将 x 和 y 转换成 2 进制并进行位运算,如 `2
x & y表示将 x 和 y 转换成 2 进制并进行位运算,如 2 & 3,其结果为 2
x ^ y表示将 x 和 y 转换成 2 进制并进行异或位运算,如 2 ^ 3,其结果为 1
x << y表示将 x 转换成 2 进制并向左移动 y 位(即在后面补 0),如 2 << 3,其结果为 16
x >> y表示将 x 转换成 2 进制并向右移动 y 位(即在前面补 0),如 2 >> 3,其结果为 0
~ 2表示将 x 转换成 2 进制并对每一位进行取反操作(即 1 变为 0 ,0 变成 1),如 ~ 2,其结果为 1
abs(x)表示取 x 的绝对值,如 abs(-2),其结果为 2
divmod(x,y)表示以二元祖的形式返回 x / y 所得的商和余数(返回的是两个整型),如 divmod(5,2),其结果为 (2,1)
pow(x,y)表示取 x 的 y 次幂,如 pow(2,3),其结果为 8
x ** y表示 x 的 y 次幂,等同于 pow(x,y),如 2 ** 2,其结果为 4
pow(x,y,z)表示 (x ** y) % 2,如 pow(2,3,3),其结果为 2

<2> 浮点型-float

Python 提供三种浮点型,内置的float,complex和标准库里面的decimal.Decimal,浮点值的精度范围取决于构建 Python 的C(或C#Java)编译器,计算机总是将浮点值以近似值存储!

所有语言在表示浮点数时都存在精确度问题,所以当对两个浮点数进行相等性比较时,并不可靠。

>>> 666e-666 is 0.0
True 

# 这里的 e 表示幂,也就是 666 的 -666 次方。

在整型转换中总是返回整数部分,而舍弃小数部分,但有的时候我们需要对小数部分进行操作,即对浮点值进行相关操作。

常用的浮点型操作函数

语法意义
round(x,y)表示将浮点值 x 的小数部分四舍五入,并保留 y 位小数。如 round(2.756,2),其返回的值为 2.77,默认返回整型
ceil(x)表示将浮点值 x 向上转化,返回的是整型。如from math import ceil ceil(2.4),其返回值为3
floor(x)表示将浮点值 x 向下转化,返回的是整型,如from math import ceil floor(2.4),其返回值为2
x.hex()表示将浮点值 x 转化为以 16 进制表示的字符串。如2.4.hex(),其返回值为'0x1.3333333333333p+1'(用 p 来表示幂,因为 e 是一个有效的 16 进制数)
float.fromhex(x)表示将 16 进制的 x 转化为浮点型。如x = 2.4.hex() s = float.fromhex(x),其返回值为2.4

与整型转换类似,浮点型也可以进行数据类型转化( float() ),不提供参数情况下,返回默认值 0.0。

介于浮点型很多方法和整型类似,这里不作过多赘述。

结语

不同数据类型里,有着很多相关的函数、方法,初学 Python 的同学,其实并不需要每个都深究,只需要掌握几个常用的即可,当你遇到的时候,再去搜一些相关博客,或者上官网都可以。

当然最好的方法还是直接在 IDE 里面通过help 查询,help 就是程序员在设计 Python 时,为 Python 里面的每个函数写的注释。所以想要知道一个函数有什么作用,最好的方法就是直接查看他的注释,也就是使用help查看。

help函数可以说是整个 Python 里面最重要的函数都不为过!

推荐阅读
Python 中的八大关键要素

您的一次关注就足以让我感动!

更多推荐

Python 中的固定类型