内置类型补充
下面是对Python解释器中内置的标准类型的一个补充。
Python的主要内置类型有数字、序列、映射、类、实例以及异常。
真值验证
任何对象都可以作为if或while的条件来做真值验证,以下情况均为假:
- None
- False
- 数字零,类似0,0.0,0j等
- 任意空序列,类似”,(),[]
- 任意空映射,类似{}
- 用户自定义类的实例,如果类定义了__bool__()或____len__()方法,当该方法返回数字0或布尔值False时
除了上述这些情况,其余情况都默认为True,因此许多不同类型的对象总为真值。
布尔运算符
下表是由优先级降序排列:
操作 | 结果 | 对应说明 |
---|---|---|
x or y | if x is false,then y,else x | 1 |
x and y | if x is false,then x,else y | 2 |
not x | if x is false,then true,else false | 3 |
1. or是一个短路操作符,如果x符合条件则不再判断y
2. and也是一个短路操作符,如果x不符合条件,则不再判断y
3. not在布尔运算符中优先级最高,但布尔运算符对比其他运算符优先级较低。所以,not a==b被解释为not (a==b),而a == not b 是一种语法错误。
比较运算符
Python中共有8种比较运算符,且都处在同一优先级。比较运算符可以做链式比较,例如:x < y <= z 等同于x
数字运算符
数字类型主要有三种:整型,浮点数和复数类型。布尔值是整数类型的一个子类型。整型为无限精度,浮点型类似C语言中的双精度。而精度一般是有所用机器的系统决定的,可通过sys.float_info
来查看浮点的精度范围。复数类型有一个实数部分和一个虚数部分,两部分都为浮点类型,假设变量z为一个复数,可以通过z.real
和z.imag
来得到实数和虚数部分。标准库还包括其他的数字类型,fractions
保存有理数,decimal
保存用户自定义精度的浮点数。
Python支持不同数字类型的混合运算:当一个二进制操作符运算不同数字类型的运算数时,“窄”类型的操作数会被转换成另一种类型后进行运算,宽窄等级如下:整型<浮点型<复数类型。两个不同类型的数字对比也遵循如上规则。int()、float()、complex()等构造器可以用来构建对应的数字类型。
除了复数之外的所有数字类型都支持如下操作符,这些操作符是以优先级从小到大排列的。所有数字运算符都要比比较运算符优先级高。
操作符 | 结果 | 对应说明 |
---|---|---|
x + y | x和y之和 | |
x - y | x减y之差 | |
x * y | x乘以y | |
x / y | x除以y | |
x // y | x除以y取模 | 说明1 |
x % y | x除以y取余数 | 说明2 |
-x | x取反 | |
+x | x不变 | |
abs(x) | x绝对值 | |
int(x) | 将x转换为整数类型 | 说明3、说明6 |
float(x) | 将x转换为浮点类型 | 说明4、说明6 |
complex(re, im) | 转换为复数类型,其中re为实数部分,im为虚数部分,im默认为0 | 说明6 |
c.conjugate() | 数字c的复数类型 | |
divmod(x, y) | (x // y, x % y)组成的元组 | 说明2 |
pow(x, y) | x的y次方幂 | 说明5 |
x ** y | x的y次方幂 | 说明5 |
说明:
- 与除法相关,结果会倾向于较小的那个整数:1 // 2 返回0,(-1) // 2 返回-1,1 // (-2) 返回-1,(-1) // (-2) 返回0。
- 这种运算不适用于复数。
- 将浮点型转换为整型的小数部分取舍类似于C语言;可以参考math模块中的floor()和ceil()函数。
- float可以接受字符串参数如“nan”和“inf“以及一个设置前缀的位置参数”+“或”-“来表示NaN的正负极限。
- Python定义了pow(0, 0)以及0 ** 0的值为1.
- 接收0-9数字以及任何Unicode对等量。
所有实数类型可以进行如下操作:
操作 | 结果 |
---|---|
math.trunc(x) | 结果截断至整数 |
round(x[, n]) | 保存到小数点后n位数,n默认为0 |
math.floor(x) | 结果取到整数,会取最小整数,例如:1.111和1.999结果都为1 |
math.ceil(x) | 结果取到整数,会取最大整数,例如:1.111和1.999结果都为2 |
比特运算
整数支持一种只对比特串有效的操作。整数转换为二进制,负数被转换为自身的补码。
这种二进制的按位操作的优先级低于数字运算,但高于对比运算。一元操作符~的优先级同其他一元数字运算一致(例如+和-)。
以下是比特运算符,以优先级从低到高排序:
操作 | 结果 | 举例 |
---|---|---|
x | y | x和y按位或操作 | 4|2=6,100|010 中,只要一位上有一个值为1,则结果中此位值为1,所以本例结果为110,十进制6 |
x ^ y | x和y按位异或操作 | 4^2,100^010,对应位相加,返回结果为110,二进制为 |
x & y | x和y按位与操作 | 4&2,100&010,只有某位的值都为1时,此位值才是1,其余情况都为0,因此本例结果为000,二进制0 |
x << y | x按位左移n位 | 4<<2=16, 100左移两位为10000,结果为16 |
x >> y | x按位右移n位 | 4>>2=1, 100左移两位为1, 结果为1 |
~x | x按位反转 | ~4=-5,-(100+1) =-5,此运算符为一元运算符,运算规则为~x=-(x+1) |
说明:
- 按位左移和右移的位数不能为负数,否则会引发ValueError异常;
- 按位左移运算等价于乘以pow(2, n),且不做溢出检测;
- 按位右移运算等价于除以pow(2, n),且不做溢出检测。
整型的其他方法
int.bit_length()
返回一个整数的二进制位数。
>>> n = -37 >>> bin(n) '-0b100101' >>> n.bit_length() 6
相当于:
def bit_length(self): s = bin(self) # binary representation: bin(-37) --> '-0b100101' s = s.lstrip('-0b') # remove leading zeros and minus sign return len(s) # len('100101') --> 6
int.to_bytes(length, byteorder, *, signed=False)
返回一个表示整数的字节数组。
>>> (1024).to_bytes(2, byteorder='big') b'\x04\x00' >>> (1024).to_bytes(10, byteorder='big') b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' >>> (-1024).to_bytes(10, byteorder='big', signed=True) b'\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00' >>> x = 1000 >>> x.to_bytes((x.bit_length() // 8) + 1, byteorder='little') b'\xe8\x03'
int.from_bytes(bytes, byteorder, *, signed=False)
类方法,返回字节数组所表示的整数。
>>> int.from_bytes(b'\x00\x10', byteorder='big') 16 >>> int.from_bytes(b'\x00\x10', byteorder='little') 4096 >>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=True) -1024 >>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=False) 64512 >>> int.from_bytes([255, 0, 0], byteorder='big') 16711680
浮点型的其他方法
float.as_integer_ratio()
返回一个由两个整数组成的元组,元组的第一个元素除以第二个元素的值为该浮点数。
>>> a=1.234 >>> a.as_integer_ratio() (694680242521899, 562949953421312) >>> 694680242521899/562949953421312 1.234
如果是无限循环小数,则抛出OverflowError异常。而对于NaN则会抛出ValueError异常。
float.is_integer()
>>> (-2.0).is_integer() True >>> (3.2).is_integer() False
float.hex()
返回表示该浮点数的十六进制字符串。对于有限浮点数,这种表示方法总是以0x开头,并以p结尾。
float.fromhex(s)
类方法,返回十六进制字符所表示的浮点数。
>>> float.fromhex('0x3.a7p10') 3740.0 >>> float.hex(3740.0) '0x1.d380000000000p+11'
数字对比其实就是对比两者的哈希值,哈希值一致,则两个数相等。
import sys, math
def hash_fraction(m, n):
"""Compute the hash of a rational number m / n.
Assumes m and n are integers, with n positive.
Equivalent to hash(fractions.Fraction(m, n)).
"""
P = sys.hash_info.modulus
# Remove common factors of P. (Unnecessary if m and n already coprime.)
while m % P == n % P == 0:
m, n = m // P, n // P
if n % P == 0:
hash_ = sys.hash_info.inf
else:
# Fermat's Little Theorem: pow(n, P-1, P) is 1, so
# pow(n, P-2, P) gives the inverse of n modulo P.
hash_ = (abs(m) % P) * pow(n, P - 2, P) % P
if m < 0:
hash_ = -hash_
if hash_ == -1:
hash_ = -2
return hash_
def hash_float(x):
"""Compute the hash of a float x."""
if math.isnan(x):
return sys.hash_info.nan
elif math.isinf(x):
return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
else:
return hash_fraction(*x.as_integer_ratio())
def hash_complex(z):
"""Compute the hash of a complex number z."""
hash_ = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag)
# do a signed reduction modulo 2**sys.hash_info.width
M = 2**(sys.hash_info.width - 1)
hash_ = (hash_ & (M - 1)) - (hash & M)
if hash_ == -1:
hash_ == -2
return hash_
序列类型—str,bytes,bytearray,list,tuple,range
序列通常有如下通用操作:
操作 | 结果 | 说明 |
---|---|---|
x in s | 当x属于s时返回True,否则返回False | 1 |
x not in s | 当x不属于s时返回True,否则返回False | 1 |
s + t | 返回序列x和t按顺序拼接的结果 | 6 |
s*n, n*s | 将s做n次浅拷贝并拼接后返回 | 2 |
s[i] | 返回索引为i的元素,索引从0开始 | 3 |
s[i:j] | 返回索引从i到j-1的切片 | 3,4 |
s[i:j:k] | 返回索引从i到j,步长为k的切片 | 3,5 |
len(s) | 返回序列的长度 | |
min(s) | 返回序列最小元素 | |
max(s) | 返回序列最大元素 | |
s.index(i) | 返回序列中首个元素为i的索引值 | |
s.count(i) | 返回序列中i元素出现的次数 |
序列类型支持对比,两个序列相同的条件是,长度相同、每个元素相同、序列类型相同。
说明:
当序列为字符串时,in和not in操作类似检测是否为子字符串;
当n的值小于0时,将一律当做0处理,这种情况下会返回空序列。需要注意的是此时为浅拷贝:
>>> lists = [[]] * 3 >>> lists [[], [], []] >>> lists[0].append(3) >>> lists [[3], [3], [3]]
如果想要得到不同的结果,可以参考下列操作:
>>> lists = [[] for i in range(3)] >>> lists[0].append(3) >>> lists[1].append(5) >>> lists[2].append(7) >>> lists [[3], [5], [7]]
如果i或j是复数,则索引是从后往前算:len(s) + i 或len(s) + j来替换该负值。但-0依然是0。
如果i或者j比len(s)大,则会替换为len(s)。如果i缺失或者为None,则会替换为0;如果j缺失或者为None,则会替换为len(s)。如果i大于等于j,则切片为空。
从i到j,步长为k的切片,其元素索引为i,i+k,i+2*k,…直到达到或超过j的值,但永不包含j。如果i或j大于len(s),则替换为len(s);如果i缺失或为None,则替换为0;如果j缺失或为None,则替换为len(s)。如果k缺失,取默认值1。
CPython解释器细节:如果s和t都为字符串,有些Python解释器例如CPython可以写成这种格式:s = s + t或s += t。为了增强解释器兼容性,这种情况最好使用字符串内置方法
str.join([s, t])
。
字符串格式化操作
这里的字符串格式化方式可能在未来弃用,请关注版本更新信息
字符串对象有一个特殊的内置操作符:%,用来做字符串格式化。
当格式化一个值的时候,将被格式化的内容放到操作符%后:
>>> a = "Nemo"
>>> b = "hello %s" % a
>>> b
'hello Nemo'
当格式化多个值时,各个值按照位置关系,通过元组传入到字符串中:
>>> a = "hello"
>>> b = "Nemo"
>>> c = "%s %s" % (a, b)
>>> c
'hello Nemo'
当格式化内容存在字典时:
>>> print('%(language)s has %(number)03d quote types.' %
... {'language': "Python", "number": 2})
其中%后跟着的字母为占位符,不同占位符所支持格式化的类型不同:
占位符 | 说明 |
---|---|
‘d’ | 整数 |
‘i’ | 整数 |
‘o’ | 八进制数 |
‘u’ | 废弃类型,和’d’差不多 |
‘x’ | 十六进制(小写) |
‘X’ | 十六进制(大写) |
‘e’ | 浮点数指数格式(小写) |
‘E’ | 浮点数指数格式(大写) |
‘f’ | 浮点数十进制格式(小写) |
‘F’ | 浮点数十进制格式(大写) |
‘g’ | 浮点数格式。当指数级别小于-4或更低精度时使用指数格式(小写),否则使用十进制格式 |
‘G’ | 浮点数格式。当指数级别小于-4或更低精度时使用指数格式(大写),否则使用十进制格式 |
‘c’ | 单个字母(可以是整数或单个字母) |
‘r’ | 字符(使用repr()方法来转换任意Python对象) |
’s’ | 字符(使用str()方法来转换任意Python对象) |
‘a’ | 字符(使用ascii()方法来转换任意Python对象) |
‘%’ | 如果没有传入任何参数,则结果中显示原字符’%’ |
range类型
range类型是属于不可变序列,通常用于循环操作。使用range的好处是,不论range长度多少,它都占用等量的内存。
range对象支持索引操作、容器操作、迭代操作、len()函数,以及:
range.count(x)
返回range对象中x元素存在的个数。
range.index(x)
返回range对象中s[i] == x 的索引值i。如果x不在range对象中,则抛出ValueError异常。
可变序列
列表和bytearray属于可变序列,字符串和元组属于不可变序列。可变序列支持对序列中的元素更改,不可变序列中的元素一旦创建不可更改。可变序列有如下操作,需要注意的是列表元素可以为任意元素,bytearray的元素只能是范围0~256的整数:
操作 | 结果 |
---|---|
s[i] = x | 将索引i的元素的值替换为x |
s[i:j] = t | 将索引为i到j的切片替换为可迭代对象t |
del s[i:j] | 类似s[i:j] = [] |
s[i:j:k] = t | 将s[i:j:k]的元素替换为t |
del s[i:j:k] | 将s[i:j:k]里的元素删除 |
s.append(x) | 等同于s[len(s) : len(s)] = [x] |
s.extend(x) | 等同于s[len(s) : len(s)] = x |
s.count(x) | 返回s中值为x元素的个数 |
s.index(x[, i[, j]]) | 返回序列i到j切片中元素值等于x的最小索引 |
s.insert(i, x) | 等同于s[i:i] = [x] |
s.pop([i]) | 等同于 x = s[i]; del s[i]; return x |
s.remove(x) | 等同于del s[s.index(x)] |
s.reverse() | 反转序列元素 |
s.sort([key[, reverse]]) | 对序列元素排序 |
说明:
可迭代对象t的长度应当与被替换的切片长度一致;
x可以为任意可迭代对象;
- 当序列s中不包含值为x的元素时,index方法会抛出ValueError异常;
- 当insert方法传入负索引时,序列长度会增加。
- pop方法的参数i默认值为-1,即默认删除序列最后一个元素;
- 当排序或反转一个大序列时,sort方法和reverse方法开销较小,但不好的一点是这两种方法都不返回操作过的序列;
- sort方法必须传入排序关键字参数,作为排序的对比依据。key参数接收一个函数,对序列里每个值处理后进行排序,例如:key=str.lower,这样会把序列中的元素。
bytes和bytearray
bytes和bytearray对象,都属于字节字符串,可以使用字符串的所有方法,但bytes不接收str做参数,同理str也不接收bytes做参数。
a = "abc"
b = a.replace("a", "f")
a = b"abc"
b = a.replace(b"a", b"f")
bytes.decode(encoding=”utf-8”, errors=”strict”) bytesarray.decode(encoding=”utf-8”, errors=”strict”)
返回字节解码后的字符串,默认编码方式为utf-8。errors参数为处理异常的模式,默认为strict,即编码的时候遇到错误会抛出UnicodeError异常。其他可用值有’ignore’,’replace’等。
bytes.fromhex(sting) bytesarray.fromhex(string)
类方法,返回对string解码后的字符对象。参数string中,每个字节必须至少包含两个十六进制数,空格会被忽略。
>>> bytes.fromhex('f0 f1f2 ') b'\xf0\xf1\xf2'
bytes.translate(table[, delete]) bytearray.translate(table[, delete])
返回bytes或bytearray对象的副本,其中删除了可选参数delete中出现的左右字节,其余字节通过给定转换表映射,该转换表必须是长度为256的字节对象。
可以通过bytes.maketrans()方法来构造一个转换表。
如果只是想删除字符,可以将table参数设为None。
>>> b'read this short text'.translate(None, b'aeiou') b'rd ths shrt txt'
bytes.maketrans(from, to) bytearray.maketrans(from, to )
静态方法,返回一个转换表,这个表通常提供给bytes.translate()使用。会把from和to中相同位置的字符做映射,而from和to必须为字节类型并且长度相等。