在python中,数值类型代表的并非只是数字,而是一系列相似类型的集合.具体如下:
1. 整型和浮点型对象
2. 复数对象
3. 十进制:固定精度对象
4. 分数:有理数对象
5. 集合:数值类型操作的集合
6. 布尔类型
7. 内建函数和模块:round,math,random等等
8. 表达式,非限制整数精度,按位运算符,十六进制,八进制和二进制.
9. 第三方扩展:容器,库.
以下表格是提供了数值字面量的表式:
字面量 |
说明 |
1234,-24,0 |
整数 |
1.23, 1., 3.14e-10 |
浮点数 |
0o177(第一个是数字0,第二个是字母o),0x9ff,0b101010 |
八进制,十六进制和二进制 |
3+4j,3.0+4.0j |
复数 |
set('spam'),{1, 2, 3, 4} |
集合 |
Decimal('1.0'),Fraction(1, 3) |
十进制和分数扩展形式 |
bool(x), True, False |
布尔类型 |
python提供一些列的工具来操作数值对象:
expression operators
+, -, *, /, >>, **, &等等
built-in mathematical functions
pow, abs, round, int, hex, bin等等
utility modules
random, math等等.
yield x: 生成器函数发送协议
lambda args: expression 匿名函数生成器
x if y else z: 如果y为true,则执行x,否则执行z
x in y, x not in y: 成员关系操作符(iterables,sets)
x is y, x is not y: 对象身份测试(判断类x是否是类y的实例,或者为y子类的实例)
(...): 元组,表达式,生成器表达式
[...]: 列表,列表操作(如列表推导式)
{...}: 字典,集合和字典推导式
变量在第一次被赋值时候创建,而且必须被赋值情况后才能被使用.
>>> a = 3 >>> b = 4 >>> a + b, a * b (7, 12)
我们可以使用%来显示字符串,并且可指定精度,或者使用format来显示:
>>> num = 1 / 3 >>> num 0.3333333333333333 >>> "%e" % num '3.333333e-01' >>> "%4.2f" % num '0.33' >>> "{0:4.2f}".format(num) '0.33'str函数: 以用户友好的方式显示
repr函数:以代码友好的方式显示(即如果是字符串,则提示字符串)
>>> repr("spam") "'spam'" >>> str('spam') 'spam'
python支持链式比较法,例如(A < B < C)是合法的,相当于(A < B and B < C):
>>> x, y, z = 2, 4, 6 >>> x < y < z True >>> x < y > z False >>> x < z > y True所以,这里通常会有一个陷阱:
>>> 1 == 2 < 3 False这里等价于:1 == 2 and 2 < 3,而非等价于(1 == 2) < 3.
对于浮点型比较要格外的注意:
>>> 1.1 + 2.2 == 3.3 False >>> 1.1 + 2.2 3.3000000000000003 >>> int(1.1 + 2.2) == int(3.3) True >>> float(1.1 + 2.2) == float(3.3) False
X / Y:
在python2.X情况下,是执行classic触发(在python3.X中移除了classic),即会截断成整数.但是python3.X情况下,会得到浮点数.
X // Y:
通过截断,得到整数.
支持不同的系统:
若想在python2.X中实现"/"的3.X效果,可以进行强制类型转换:
>>> 3 / (float)(2) 1.5floor与truncation
对于//操作符,总是调用"truncating"除法,即直接截断,而非正常的四舍五入:
>>> import math >>> math.floor(2.5) 2 >>> math.floor(-2.5) -3 >>> math.trunc(2.5) 2 >>> math.trunc(-2.5) -2 >>> -5 // 2 #对于负数来说是floor -3 >>> 5 // 2 #对于整数来说是trunc 2
python支持的整数精度大的惊人:
>>> len(str(2 ** 1000000)) 301030
>>> 0o1,0o20,0o377 #以数字0开头,后跟字母o/O (1, 16, 255) >>> 0x01,0x10,0xff #以数字0开头,后跟字母x/X (1, 16, 255) >>> 0b1,0b10000,0b11111111 #以数字0开头,后跟字母b/B (1, 16, 255)我们可以调用内建函数oct,hex,bin来显示字符串形式,通过内建函数int(第二个参数为基数)来格式化数值:
>>> oct(64), hex(64), bin(64) ('0o100', '0x40', '0b1000000') >>> int("64"), int("100", 8), int("40", 16), int("1000000", 2) (64, 64, 64, 64) >>> int("0x40", 16), int("0b1000000", 2) (64, 64) >>> int("0x40", 8) Traceback (most recent call last): File "<pyshell#54>", line 1, in <module> int("0x40", 8) ValueError: invalid literal for int() with base 8: '0x40'我们甚至可以格式化输出数值:
>>> "{0:o},{1:x},{2:b}".format(64, 64, 64) '100,40,1000000' >>> "%o, %x, %x, %X" % (64, 64, 255, 255) '100, 40, ff, FF'
python也可以进行类似C语言的位操作:
>>> x = 1 >>> x << 2 4 >>> x | 2 3 >>> x & 1 1我们也可以使用bit_length函数来计算位的个数:
>>> X = 99 >>> bin(X), X.bit_length(), len(bin(X)) - 2 ('0b1100011', 7, 7)
>>> import math >>> math.pi, math.e (3.141592653589793, 2.718281828459045) >>> math.sin(2 * math.pi / 180) 0.03489949670250097 >>> math.sqrt(144), math.sqrt(2) (12.0, 1.4142135623730951) >>> pow(2, 4), 2 ** 4, 2.0 ** 4.0 (16, 16, 16.0) >>> abs(-42.0), sum((1, 2, 3, 4)) (42.0, 10) >>> min(3, 1, 2, 3), max(3, 1, 2, 4) (1, 4)而我们可以使用floor,trunc来截断数值:
>>> math.floor(2.567), math.floor(-2.567) (2, -3) >>> math.trunc(2.567), math.trunc(-2.567) (2, -2) >>> int(2.567), int(-2.567) (2, -2) >>> round(2.567), round(2.467), round(2.567, 2) (3, 2, 2.57) >>> "%.1f" % 2.567, '{0:.2f}'.format(2.567) ('2.6', '2.57')而以下展示了三种求开方的方法:
>>> import math >>> math.sqrt(144) 12.0 >>> 144 ** 0.5 12.0 >>> pow(144, 0.5) 12.0以下展示了random模块的使用:
>>> import random >>> random.random() 0.9235287913204357 >>> random.random() 0.5782930012165811 >>> random.randint(1, 10) 6 >>> random.randint(1, 10) 7我们甚至可以使用choice随机从列表选择一项,使用shuffle打乱原列表顺序:
>>> random.choice(['Life of Brian', 'Holy Grail', 'Meaning of Life']) 'Life of Brian' >>> random.choice(['Life of Brian', 'Holy Grail', 'Meaning of Life']) 'Holy Grail' >>> suits = ['hearts', 'clubs', 'diamonds', 'spades'] >>> random.shuffle(suits) >>> suits ['spades', 'diamonds', 'hearts', 'clubs'] >>> random.shuffle(suits) >>> suits ['spades', 'hearts', 'clubs', 'diamonds']
对于浮点型有一个致命伤在于精度:
>>> 0.1 + 0.1 + 0.1 - 0.3 5.551115123125783e-17但是,使用Decimal模块则不会存在这样的问题:
>>> from decimal import Decimal >>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3') Decimal('0.0') >>> int(Decimal('0.0')) 0Decimal可以自动将精度调到最大精度:
>>> Decimal('0.1') + Decimal('0.10') + Decimal('0.10') + Decimal('0.30') Decimal('0.60')我们也可以使用浮点数来创建Decimal(但是貌似多此一举):
>>> Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3) Decimal('2.775557561565156540423631668E-17')对于特殊的Decimal操作,我们可以设定其小数点位数:
>>> import decimal >>> decimal.Decimal(1) / decimal.Decimal(7) Decimal('0.1428571428571428571428571429') >>> decimal.getcontext().prec = 4 >>> decimal.Decimal(1) / decimal.Decimal(7) Decimal('0.1429')但是问题来了:设定了小数点后精度,如何恢复呢?我们可以使用setcontext:
>>> decimal.setcontext(decimal.DefaultContext) >>> decimal.Decimal('1.0') / decimal.Decimal('3.0') Decimal('0.3333333333333333333333333333')我们也可以产生临时的作用域来操作精度:
>>> import decimal >>> decimal.Decimal('1.0') / decimal.Decimal('3.0') Decimal('0.3333333333333333333333333333') >>> with decimal.localcontext() as ctx: ctx.prec = 2 decimal.Decimal('1.0') / decimal.Decimal('3.0') Decimal('0.33') >>> decimal.Decimal('1.0') / decimal.Decimal('3.0') Decimal('0.3333333333333333333333333333')
当我们操作分数的时候,Fraction类型就可以派上用场了:
>>> from fractions import Fraction >>> x = Fraction(1, 3) >>> y = Fraction(4, 6) >>> x Fraction(1, 3) >>> y Fraction(2, 3) >>> print(y) 2/3而分数甚至也可以进行数值计算:
>>> x + y Fraction(1, 1) >>> x - y Fraction(-1, 3) >>> x * y Fraction(2, 9)而我们甚至可以往Fraction传递浮点数:
>>> Fraction("0.25") Fraction(1, 4) >>> Fraction("0.1234") Fraction(617, 5000) >>> Fraction(0.1234) Fraction(8891907104280307, 72057594037927936) >>> 8891907104280307 / 72057594037927936 0.1234类似于Decimal,Fraction相对于浮点型在计算上是有优势的:
>>> 0.1 + 0.1 + 0.1 - 0.3 5.551115123125783e-17 >>> from fractions import Fraction >>> Fraction(1, 10) + Fraction(1, 10) + Fraction(1, 10) - Fraction(3, 10) Fraction(0, 1)Fraction和浮点型可以进行相对的转换(下例中*是语法,代表f是元组):
>>> (2.5).as_integer_ratio() (5, 2) >>> f = 2.5 >>> z = Fraction(*f.as_integer_ratio()) >>> z Fraction(5, 2) >>> Fraction(2.5) Fraction(5, 2) >>> x = Fraction(1, 3) >>> x + z Fraction(17, 6) >>> float(x) 0.3333333333333333 >>> float(z) 2.5 >>> float(x + z) 2.8333333333333335 >>> Fraction.from_float(1.75) Fraction(7, 4) >>> x + 2.0 2.3333333333333335
集合是不可更改的容器,元素在集合中只会出现一次.集合是可迭代的,通常可以用作字典的键.
集合在Python2.6X版本中的应用
>>> x = set('abcde') >>> y = set('bdxyz') >>> x set(['a', 'c', 'b', 'e', 'd']) >>> x - y set(['a', 'c', 'e']) >>> x | y set(['a', 'c', 'b', 'e', 'd', 'y', 'x', 'z']) >>> x & y set(['b', 'd']) >>> x > y, x < y (False, False)备注:集合不可比较,所以集合是无序存储的.
我们可判断元素是否在集合中:
>>> 'e' in x True >>> 'e' in 'Camelot', 22 in [11, 22, 33] (True, True)而集合也有对应的方法(&,|):
>>> z = x.intersection(y) >>> z set(['b', 'd']) >>> z.add('SPAM') >>> z set(['b', 'd', 'SPAM']) >>> z.update(set(['X', 'Y'])) >>> z set(['Y', 'X', 'b', 'd', 'SPAM']) >>> z.remove('b') >>> z set(['Y', 'X', 'd', 'SPAM'])并且集合是可迭代的:
>>> for item in set('abc'): print(item * 3) aaa ccc bbb使用方法有一个好处是:方法可处理可迭代的集合,而&,|只能处理集合:
>>> x set(['a', 'c', 'b', 'e', 'd']) >>> x | [3, 4] Traceback (most recent call last): File "<pyshell#25>", line 1, in <module> x | [3, 4] TypeError: unsupported operand type(s) for |: 'set' and 'list' >>> x.union([3, 4]) set(['a', 'c', 3, 'e', 'd', 'b', 4])集合的不可改变性:
对于集合来说,由于其不可改变性,所以集合的元素不能是列表或者字典,但是可以是元组(且元组中元素也必须是不可改变的).
>>> s = set([1]) >>> s set([1]) >>> s.add([2, 3]) Traceback (most recent call last): File "<pyshell#41>", line 1, in <module> s.add([2, 3]) TypeError: unhashable type: 'list' >>> s.add({'a' : 1}) Traceback (most recent call last): File "<pyshell#42>", line 1, in <module> s.add({'a' : 1}) TypeError: unhashable type: 'dict' >>> s.add((2, 3)) >>> s set([1, (2, 3)]) >>> s.add(([4, 5], 6)) Traceback (most recent call last): File "<pyshell#45>", line 1, in <module> s.add(([4, 5], 6)) TypeError: unhashable type: 'list'python2.7X以上版本的集合推导式
>>> {x ** 2 for x in [1, 2, 3, 4]} set([16, 1, 4, 9])集合的优点
集合是不允许重复的,特别适用于一些特定的场合(比如统计电话号码,身份证):
>>> L = [1, 2, 3, 2, 1, 4, 5] >>> set(L) set([1, 2, 3, 4, 5])集合可用于比较两个字符串,列表或者字典的差异:
>>> set([1, 3, 5, 7]) - set([1, 2, 4, 5, 6]) set([3, 7]) >>> set('abcdefg') - set('abdghij') set(['c', 'e', 'f']) >>> set(dir(bytes)) - set(dir(bytearray)) set(['__getslice__', 'format', '__mod__', '_formatter_field_name_split', 'encode', '__rmod__', '__getnewargs__', '_formatter_parser'])若比较两个列表是否存在相同的元素(不一定排序),则集合优于排序后比较的算法:
>>> L1, L2 = [1, 3, 5, 2, 4], [2, 5, 3, 4, 1] >>> L1 == L2 False >>> set(L1) == set(L2) True >>> sorted(L1) == sorted(L2) True