本节是第五讲的第三小节,上节为大家介绍了Python语言的特点,共有8大特点(要素),帮助大家快速了解Python语言。本节主要为大家介绍Python语言的数字类型包括(整型、布尔型、浮点型、复数型、十进制型)。
标识符与关键字(Identifiers and keywords)
有效的Python标识符是任意长度的非空字符序列,其中包括一个“引导字符”以及0个或多个“后续字符”。Python标识符必须符合两条规则,并遵循某些约定。
第一条规则是关于引导字符与后续字符的。只要是Unicode编码的字母,都可以充当引导字符,包括ASCII字母("a"、"b" ... "z", "A"、 "B"、...、"Z”)、下划线以及大多数非英文语言的字母。后续字符可以是任意引导字符,或任意非空格字符,包括Unicode编码中认为是数字的任意字符,比如("0"、“1”、...、 "9"),或者是加泰罗尼亚字符”•“。标识符是大小写敏感的,因此,TAXRATE、Taxrate、TaxRate、 taxRate与taxrate是5个不同的标识符。
第二条规则是Python标识符不能与Python关键字同名,因此,不能使用表中的这些关键字作为标识符的名称。
Python的关键字
and
continue
except
global
lambda
pass
while
as
def
False
if
None
raise
with
assert
del
finally
import
nonlocal
return
yield
break
elif
for
in
not
True
class
else
from
is
or
try
第一条约定是:不要使用Python预定义的标识符名对自定义的标识符进行命名, 要避免使用Python内置数据类型(比如int、 float、list、str与tuple)的名称,也不要使用Python内置函数名与异常名作为标识符名。 读者可能会困惑如何判断自己对标识符的命名是否在上面需要避免的范围之内, Python有一个内置的名为dir()的函数,该函数可以返回对象属性列表。不带参数调用该函数时,将返回Python内置属性列表。
第二条约定是:关于下划线(_)的使用,名的开头和结尾都使用下划线的情况(_) 应该避免使用,这是因为Python定义了各种特殊方法与变量,使用的就是这样的名称。单一的下划线本身也可以当作一个标识符,在不关心迭代针对的具体数据项时,有些程序员喜欢在for...in循环中使用。
for _ in (0, 1,2, 3, 4, 5):
print("Hello")
判断是否是有效标识符的最简单方法是在交互式的Python解释器或IDLE的 Python Shell中对其进行赋值操作,下面给出几个实例:
>>> stretch-factor = 1
SyntaxError: cannot assign to operator
>>> 2miles = 2
SyntaxError: invalid syntax
>>> str = 3 # Legal but BAD
使用无效的标识符时,会产生一个SyntaxError异常。第一个赋值操作失败的原因在于,不是一个Unicode字母、数字或下划线。第二个赋值操作失败是 因为引导字符不是Unicode字母或下划线,而数字只能充当后续字符。如果标识符是有效的,就不会有异常产生——即便标识符是内置的数据类型、异常或函数的名称, 因此,第三个赋值操作可以工作,尽管并不建议这样做。
Integral 类型(整型数)
Python提供了两种内置的Integral类型,即int(integer)与bool整数与布尔型值都是固定的,但由于Python提供了增强的赋值操作符,使得这一约束极少导致实际问题。在布尔表达式中,0与False表示False,其他任意整数与true都表示true。在数字表达式中,True表示1, False表示0。这意味着,有些看起来很怪异的表达式也是有效的。 例如,我们可以使用表达式i+= True来对整型变量i进行递增操作,当然,最自然的方法还是i+=1。
整数(int)
整数的大小只受限于机器的内存大小,因此,包含几百个数字的整数可以很容易地创建与操纵——尽管在速度上会比处理那些可以由处理器自然表示的整数要慢。
默认情况下,整数字面值(literals)采用的是十进制,但在方便的时候也可以使用其他进制:
>>> 14600926 # decimal
14600926
>>> 0b110111101100101011011110 # binary
14600926
>>> 0o67545336 # octal
14600926
>>> 0xDECADE # hexadecimal
14600926
二进制数以0b引导,八进制数以0o引导,十六进制数则以0x引导,大写字母也可以使用。
所有常见的数学函数与操作符都可用于整数,如表所示。有些功能由内置函数提供,比如abs()函数,abs(i)可以返回整数i的绝对值;有些功能由int操作符提供, 比如,i+j返回整数i与整数j的和。
数值型操作符与函数
x + y
将数x与数y相加
x ** y
计算x的y次幕,参见pow()函数
x - y
从x减去y
abs(x)
返回x的绝对值
x * y
将x与y相乘
divmod(x, y)
以二元组的形式返回x除以y所得的商和余数(两个整数)
x / y
用x除以y,总是产生一个浮点值(如果x或y是复数就产生一个复数)
pow(x, y)
计算x的y次幕,与操作符**等同
x // y
用x除以y,舍弃小数部分,使得结果总是整数,参见round()函数
pow(x, y, z)
(x**y)%z的另一种写法
x % y
用x除以y取模(余数)
round(x, n)
返回浮点数X四舍五入后得到的相应整数(n小数点位数)
所有二元数学操作符(+、-、/、//、%与**)都有相应的增强版赋值操作符(+=、 -=、/=、//=、%=与**=),这里,x op=y在运算逻辑上与x = x op y是等价的。
对象的创建可以通过给变量赋字面意义上的值,比如x=17,或者将相关的数据类型作为函数进行调用,比如x=int(17)。有些对象(比如,类型为decimal.Decimal)只能通过数据类型创建,这是因为这些对象不能用字面意义表示。使用数据类型创建对象时,有3种用例。
第一种情况是,不使用参数调用数据类型函数,这种情况下,对象会被赋值为一个默认值,比如,x=int()会创建一个值为0的整数。所有内置的数据类型都可以作为函数并不带任何参数进行调用。
第二种情况是,使用一个参数调用数据类型函数。如果给定的参数是同样的数据类型,就将创建一个新对象,新对象是原始对象的一个浅拷贝(shallow copy)。如果给定的参数不是同样的数据类型,就会尝试进行转换。下表展示了 int类型时的这种用法。如果给定参数支持到给定数据类型的转换,但是转换失败,就会产生一个 ValueError异常,否则返回给定类型的对象。如果给定参数不知道到给定数据类型的转换,就会产生一个TypeError异常。
第三种情况是,给定两个或多个参数---但不是所有数据类型都支持,而对支持这一情况的数据类型,参数类型以及内涵都是变化的。对于int类型,允许给定两个参数,其中第一个参数是一个表示整数的字符串,第二个参数则是字符串表示的base。 比如,int("A4", 16)会创建一个值为164的整数。
bin(i) #返回整数i的二进制表示(字符串),比如bin(1980) = '0b11110111100'
hex(i) #返回i的十六进制表示(字符串),比如hex(1980) = '0x7bc'
oct(i) #返回i的八进制表示(字符串),比如oct(1980) = '0o3674'
int(x) #将对象x转换为整数,失败时会产生ValueError异常,如果x的数据类型不知道到整数的转换,就会产生TypeError异常;如果x是一个浮点数,就会截取其整数部分
int(s, base) #将字符串s转换为整数,失败时会产生ValueError异常。如果给定了可选的基参数,那么应该为2 到36之间的整数
布尔型(bool)
有两个内置的布尔型对象:True与False。与所有其他的Python数据类型类似,布尔数据类型也可以当作函数进行调用 ——不指定参数时将返回False,给定的是布尔型参数时,会返回该参数的一个拷贝, 给定的是其他类型的参数时,则会尝试将其转换为布尔数据类型。所有内置的数据类型与标准库提供的数据类型都可以转换为一个布尔型值,为自定义数据类型提供布尔型转换也很容易。下面给出了两个布尔型赋值操作以及两个布尔表达式:
>>> t = bool(True)
>>> f = False
>>> t and f
False
>>> t and True
True
前面已经讲过,Python提供了 3个逻辑操作符:and、or与not。and与or都使用 “短路"逻辑,并返回决定其结果的操作数,not则总是返回True或False。
习惯于使用老版本Python的程序员有时会使用1与0,而非True与False,这种用法几乎总是可以正常工作的,但是建议在需要布尔型值的时候,新代码中还是使用内置的布尔型对象。
浮点类型(Floating-Point Types)
Python提供了 3种浮点值:内置的float与complex类型,以及来自标准库的 decimal.Decimal类型,这3种数据类型都是固定的。float类型存放双精度的浮点数, 具体取值范围则依赖于构建Python的C 编译器,由于精度受限,对其进行相等性比较并不可靠。float类型的数值要使用小数点或使用指数表示,比如, 0.0、4.、5.7、-2.5、-2e9、8.9e-4 等。
>>> 0.0, 5.4, -2.5, 8.9e-4
(0.0, 5.4, -2.5 ,0.00089)
如果我们确实需要高精度,那么可以使用来自decimal模块的decimal.Decimal数。 这种类型在计算时,可以达到我们指定的精度(默认情况下,到小数点后28位),并且可以准确地表示循环小数,比如0.1,但在处理速度上比通常的float要慢很多。由于准确性的优势,decimal.Decimal数适合于财政计算。
Python支持混合模式的算术运算,比如使用int与float运算,生成float数;使用 float与complex运算,生成complex结果。由于decimal.Decimal是混合精度的,只能用于其他decimal.Decimal数或int,在与int混合运算时,会生成decimal.Decimal 结果。如果使用不兼容的数据类型进行运算,会产生TypeError异常。
浮点数(Floating-Point Numbers)
所有数值型操作与函数都可以与float 一起使用,包括增强版的赋值运算符。float数据类型可以作为函数调用——不指定参数时返回0.0,指定的是float型参数时返回该参数的一个拷贝,指定其他任意类型的参数时都尝试将其转换为float。用于转换时,可以给定一个字符串参数,或者使用简单的十进制表示,或者使用指数表示。 在进行涉及float的计算时,可能会生成NaN (“不是一个数字”)或“无穷”。遗憾的是,这种行为并不是在所有实现中都一致,可能会由于系统底层数学库的不同而不同。
下面给出一个简单函数,该函数用于比较float是否相等(按机器所能提供的最大精度):
def equal_float(a, b):
return abs(a - b)<= sys.float_info.epsilon
>>>sys.float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
为了实现上述函数,需要导入sys模块。sys.float_info对象有很多属性,sys.float_ info.epsilon是机器可以区分出的两个浮点数的最小区别。Python的float通常会提供至多17个数字的精度。
如果在IDLE中输入sys.float_info,就可以显示其所有属性,包括机器可以表示的浮点数的最小值与最大值,输入help(sys.float_info)会显示关于sys.float_info对象的某些信息。
Help on float_info object:
class float_info(builtins.tuple)
| float_info(iterable=(), /) ......
使用int()函数,可以将浮点数转换为整数——返回其整数部分,舍弃其小数部分; 或者使用round()函数,该函数将对小数部分四舍五入;或者使用math.floor()函数,或 math.ceil()函数——该函数可以将浮点数转换为最近邻的整数。如果浮点数的小数部分为0, float.is_integer(x)方法将返回True,浮点数的小数表示可以使用float.as_integer_ratio()方法获取,比如,给定浮点数x = 2.75,则调用 x.as_integer_ratio()将返回(11,4)(返回一对整数,其比率正好等于原浮点数并且分母为正数)。使用float()函数,可以将整数转换为浮点数。
使用float.hex()方法,可以将浮点数以十六进制形式表示为字符串,相反的转换可以使float.fromhex()实现。比如:
s = 14.25.hex() # str s == '0x1.c800000000000p+3'
f = float.fromhex(s) # float f == 14.25
t = f.hex() # str t == '0x1.c800000000000p+3'
>>> import math
>>> math.pi * (5 ** 2) # 78.53981633974483
>>> math.hypot(5, 12) #13.0
>>> math.modf(13.732) #(0.7319999999999993, 13.0)
math模块的函数与常量
math.ceil(x)
返回大于或等于x的最小整数,比如,math.ceil(5.4) = 6
math.floor(x)
返回小于或等于x的最小整数,比如,math.floor(5.4) = 5
math.fabs(x)
返回|x|,即浮点数x的绝对值
math.fsum(i)
对iterable i中的值进行求和(浮点数)
math.modf(x)
以float的形式返回x的小数与整数部分
math.hypot(x, y)
返回√(x²+y²)
math.pow(x, y)
返回x^y(浮点值)
复数(Complex Numbers)
复数这种数据类型是固定的,其中存放的是一对浮点数,一个表示实数部分,另 一个表示虚数部分。Literal复数在书写上使用+或-符号将实数部分与虚数部分(其后 跟随一个字母j)连接在一起,共同构成复数。比如下面这些实例:3.5+2j、0.5j、4+0j、 -l-3.7j等。注意,如果实数部分为0,就可以忽略。
复数的两个部分都以属性名的形式存在,分别为real与imag,例如:
>>>z =-89.5+2.125j
>>> z.real, z.imag
(-89.5, 2.125)
math模块中的函数不能处理复数,这是一个慎重的设计决策,可以确保在有些情况下,math模块的用户得到的是异常,而不是得到一个复数。
要使用复数,可以先导入cmath模块,该模块提供了 math模块中大多数三角函数 与对数函数的复数版,也包括一些复数特定的函数,比如cmath.phase()、cmath.polar() 与cmath.rect(),还包括cmath.pi、 cmath.e等常量,这些常量与math模块中对应对象包含同样的浮点值。
十进制数字(Decimal Numbers)
有些情况下,我们更需要的是完全的准确性,即便要付出速度降低的代价。decimal模块可以提供固定的十进制数,其精度可以由我们自己指定。 涉及Decimals的计算要比浮点数的计算慢,但这是否需要关注要依赖于具体的应用程序。
要创建Decimal,必须先导入decimal模块,例如:
>>> import decimal
>>> a = decimal.Decimal(9876)
>>> b = decimal.Decimal("54321.012345678987654321")
>>> a + b
Decimal('64197.01 2345678987654321')
十进制数是使用decimal.Decimal()函数创建的,该函数可以接受一个整数或字符串作为参数---但不能以浮点数作为参数,因为浮点数不够精确,decimals则很精确。 如果使用字符串作为参数,就可以使用简单的十进制数表示或指数表示。除提供了准确性外,decimal.Decimals的精确表述方式意味着可以可靠地进行相等性比较。
从Python 3.1开始,使用decimal.Decimal.from_float()函数将floats转换为十进制数成为可能,该函数以一个float型数作为参数,并返回与该float数值最为接近的 decimal.Decimal。
math模块与cmath模块不适于处理decimal.Decimals,但是math模块提供的一些函数可以作为decimal.Decimal的方法使用,比如,要计算e^x (x是一个浮点数),可以使用math.exp(x),但如果x是一个decimal.Decimal,就需要使用x.exp()。
有些情况下,浮点数与decimal.Decimals在精度上的差别会变得很明显:
>>> 23 / 1.05
21.904761904761905
>>> print(23 / 1.05)
21.9047619048
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')
尽管使用decimal.Decimal的除法操作要比使用浮点数的精确得多,这一场景(32 位机器上)下,区别只在fifteenth decimal place才表现出来。在很多情况下,这种差别并不是很大的问题。
另一个需要注意的是上面实例中最后两行,这里第一次展示了打印对象时的一些幕后格式化操作。在使用decimal.Decimal(23)/decimal.Decimal("1.05")的结果作为参数调用print()函数时,打印的是bare number—其输出为字符串形式。如果只是简单地输入该表达式,就会得到一个decimal.Decimal输出,此时的输出是表象形式。所有 Python对象都有两种输出形式。字符串形式在设计目标上是为了更易于阅读,表象形式(Representational form)在设计目标上则是生成备用的输出信息,这种输出信息作为Python解释器的输入时会重新产生所代表的对象。
以上内容部分摘自视频课程05后端编程Python-3数字类型,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。