四:python 对象类型详解一:数字(下)

一:位操作

  除了一般的数学运算,python也支持c语言中的大多数数学表达式。这包括那些把整数当作二进制位串对待的操作。例如,还可以实现位移及布尔操作:

>>> x = 1   #0001
>>> x << 2  #shift left 2 bits:0100
4
>>> x | 2   #Bitwise OR:0011
3
>>> x & 1  #Bitwise AND:0001
1

这样的按位进行掩码的运算,使我们可以对一个整数进行多个标志位和值进行编码。在这里,我们不太过于涉及更多的关于“位运算”的细节。如果需要的话,它是支持的。在python3.1中,整数的bit_length方法也允许我们查询以二进制表示一个数字的值所需要的二进制的位数。另外,通过bin()和内置函数len()得到二进制字符串的长度,然后再减去2,往往可以得到同样的结果,尽管效率较低:

>>> X = 99
>>> bin(X),X.bit_length()
('0b1100011',7)

>>>bin(256),(256).bit_length()
('0b100000000',9)
>>> len(bin(256)) - 2    #字符串长度减去数字进制标志‘0b’两位长度
9

二:其他的内置数学工具

  除了核心对象类型以外,python还支持用于数字处理的内置函数和内置模块。内置函数pow(),abs(),分别计算幂和绝对值。这里有一些内置math模块(包含C语言中math库中的绝大多数工具)。

>>> abs(-42.0),sum((1,2,3,4))  #sum()作用于数字的一个序列
(42.0,10)

>>>min(3,1,2,4),max(3,1,2,4)  #min()和max()函数接受一个参数序列或者单个的参数
(1,4)

注意内置math这样的模块必须先导入,但是abs()这样的内置函数不需要导入就可以直接使用。换句话说,模块是外部的组件,而内置函数位于一个隐性的命名空间内,python自动搜索程序的变量名。这个命名空间对应于python3.0中名为builtins的模块(python2.6中是__builtin__)。

三:小数类型:

  a)小数数字:小数是通过一个导入的模块调用函数后创建的,而不是通过允许常量表达式创建的。从功能 上来说,小数对象就像浮点数,只不过它们有固定的位数和小数点,因此小数是有固定的精度的浮点数。小数类型对表现固定精度的特征(例如,钱的总和)以及对实现更好的数字精度是一个理想的工具。我们能够通过调用在decimal模块中的Decimal的构造函数产检一个小数对象,并传入一个字符串。这个字符串有我们希望在结果中显示的小数位数。当精读不同时,python自动升级为小数最多的:

>>>0.1 + 0.1 + 0.1 - 0.3      #浮点数缺乏精确性
5.5511151231257827e-17
>>>print(0.1 + 0.1 + 0.1 - 0.3)  #使用print仍旧不能解决问题
5.55111512313e-17
>>>
>>>
>>>from decimal import Decimal  #可以使用小数运算来解决
>>>Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')  #结果为一位小数
Decimal('0.0')

在python3.1中,将能够从一个浮点对象创建一个小数对象,通过 decimal.Decimal.from_float(1.25)形式的调用。这一转换时精确的,但有时候会产生较多的位数。

  b)设置全局精度:decimal模块中的其他工具可以用来设置所有小数数值的精度、设置错误处理等。例如,这个模块中的一个上下文对象允许指定精度(小数位数)和舍入模式(舍去、进位等)。该精度全局性地适用于调用线程中创建的所有小数:

>>> from decimal import Decimal
>>>Decimal('1') / Decimal('7')
Decimal('0.1428571428571428571428571429')

>>> import decimal
>>>decimal.getcontext().prec = 4
>>> Decimal('1') / Decimal('7')
Decimal('0.1429')

c)小数上下文管理器:可使用上下文管理器语句来重新设置临时精度。在语句退出后,精度又设置为初始值:

>>> import decimal
>>> decimal.Decimal('1.00') / decimal.Decimal('3.00')
Decimal('0.333333333333333333333')
>>>
>>>with decimal.localcontext() as ctx:
…    ctx.prec = 2
…    decimal.Decimal('1.00') / decimal.Decimal('3.00')
   
…     
Decimal('0.33')
>>>
>>> decimal.Decimal('1.00') / decimal.Decimal('3.00')
Decimal('0.333333333333333333333')

四:分数类型:

a)分数的创建:1,分数以类似于小数的方式使用,它也存在于模块中;导入其构造函数并传递一个分子和一个分母就可以产生一个分数。

       2,分数对象也可以从浮点数字符串来创建,这和小数很相似。

>>>from fractions import Fraction  #用构造函数创建分数对象
>>>x = Fraction(1,3)  #Numerator,denominator
>>>y = Fraction(4,6)

>>>from fractions import Fraction   #用浮点数字符串创建分数对象
>>>Fraction('.25')
Fraction(1,4)
>>>Fraction('1.25')
Fraction(5,4)

b)数值精度:实际上,分数保持精确性,并且自动化简结果。

>>>from fractions import Fraction #分数自动化简
>>>Fraction(6,12)
Fraction(1,2)

c)转换和混合类型:为了支持分数转换,浮点数对象现在有一个方法(float.as_integer_ratio()),能够产生它们的分子和分母比,分数有一个from_float方法,并且float接受一个Fraction作为参数。(测试中 *是一个特殊的语法,它把一个元祖扩展到单个的参数中 )

>>> (2.5).as_integer_ratio()  #float object method
(5,2)
>>>
>>>f = 2.5
>>>z = Fraction(*(f.as_integer_ratio()))  #Convert float ->fraction: two args
>>>z
Fraction(5,2)
>>>
>>>Fraction.from_float(1.75)
Fraction(7,4)
>>>
>>>Fraction(*(1.75).as_integer_ratio())  #Convert float ->fraction:other way
Fraction(7,4)

混合类型: Fraction + int ->Fraction

                Fraction + float -> float

      Fraction + Fraction ->Fraction

warning:尽管可以把浮点数转换成分数,在某些情况下,这么做的时候会有不可避免的精度损失,因为这个数字在其最初的浮点形式下是不精确的。当需要的时候,我们可以通过限制最大分母值来简化这样的结果(fraction.limit_denominator(N),其中N为分母的最大值)

>>>4.0 / 3
>>>1.3333333333333
>>>x = (4.0 /3).as_integer_ratio()  #Precision loss from float to fraction
>>>x
(6004799503160661, 4503599627370496)
>>>
>>>a = Fraction(*(4.0 /3).as_integer_ratio())
>>>a
Fraction(6004799503160661, 4503599627370496)
>>>
>>>a.limit_denominator(10)
Fraction(5,3)

五:集合

  集合(set)是一种新的类型,这是一些唯一的、不可变的对象的一个无序集合(collection)。根据定义,一个项在集合中只出现一次,不管它添加了多少次。集合是可以迭代的,可以根据需要增长或缩短,并且能够包含各种对象类型。

  a)集合的创建:要创建一个集合对象,向内置的set()函数传递一个序列或其他的可迭代的对象;集合并不包含位置信息,是一组无序集合,集合通过表达式操作符支持一般的数学集合运算。warning:不能在一般序列上应用这些表达式,必须通过序列创建集合后才能使用这些工具。

  b)集合的操作符:'in'(Membership), '-' (Difference), '|' (Union), '&' (Intersection),'^' (XOR),'>' (Superset), '<' (Subset)...

  c)集合的操作方法:add()(插入一个项目),updata()(按位置求并集),remove()(根据值删除一个项目)   Notice:在任何集合实例或集合类型名上允许dir来查看所有可用的方法。

  d)作为可迭代的容器,集合也可以用于len、for循环和列表解析这样的操作中,然而,由于它们是无序的,所有不支持像索引和分片这样的操作。

  e)尽管前面介绍的集合表达式通常需要两个集合,它们基于方法的对应形式往往对任何可迭代类型也有效。Notice:可用isinstance(object,Iterable)来判断object是不是一个可迭代的对象

>>>x = set('abcde')  #以下测试均在python2.6 中运行
>>>y = set('bdxyz')  #python2.6中创建集合
>>>x
set(['a','b','c','d','e'])
>>>
>>>'e' in x    #运算符测试
True
>>>z = x.intersection(y)   #x & y  #方法测试
>>>z
set(['b','d'])
>>>z.add('spam')
>>>z
set(['b','d','spam'])
>>>z.update(set(['X','Y']))  #in-place union
>>>z
set(['b','d','spam','X','Y'])
>>>z.remove('b')
>>>z
set(['d','spam','X','Y'])
>>>
>>>
>>>s = set([1,2,3])
>>>s.union([3,4]) #集合的方法可以用到任何可迭代类型的对象,list类型是可迭代对象
set([1,2,3,4])
>>>s.intersection((1,3,5))   #元组是可迭代对象
set([1,3])
s.issubset(range(-5,5))   #判断s集合的元素范围是不是在[-5,5]之间
True

六:python 3.0中的集合常量

  a)在python3.0 中,set([1,2,3,4]) 和{1,2,3,4}是等价的,前面一个是2.6版本的集合形式,后面一个是3.0版本的集合形式。不管如何创建集合,3.0版本都使用新的常量格式来显示它。但是在3.0版本中要创建空的集合或从已有的可迭代对象构建集合,还是需要内置的set函数。

warning:不可变限制:集合只能包含不可变的(即可散列的)对象类型。因此,列表和字典不能嵌入到集合中,但是,如果你需要存储复合值的话,元组是可以嵌入的。

  集合本身也是不可变的,因此,不能直接嵌入到其它集合中;如果需要在另一个集合中存储一个集合,可以像调用set一样来调用frozenset,但是,它创建一个不可变的集合,该集合不可修改并且可以嵌套到其它集合中。

>>>s = {1}
>>>s.add([2,3])
TypeError: unhashable type: 'list'
>>>s.add({'a' : 1})
TypeError: unhashable type: 'dict'
>>>s.add((2,3))
>>>s
{1,(2,3)}                                          #No list or dict,but tuple okay
>>>
>>>s = frozenset([1,2])                   #集合中嵌入集合的方法
>>>z = set([3,4])
>>>z.add(s)
>>>z
{frozenset({1, 2}), 3, 4}

七:python 3.0中的集合解析:

  除了常量,python 3.0 还引入了一个集合解析构造,类似于介绍过的列表解析的形式,但是,编写在花括号中而不是方括号中,并且作用于集合而不是列表。结果是通过运行代码创建的一个新的集合。

>>>{x ** 2 for x in [1,2,3,4]}  #集合解析
{16,1,4,9}
View Code

八:为什么使用集合?

  由于项在集合中只能存储一次,集合(set)可以用来把重复项从其它集合(collection)中过滤掉。即可以把一个列表中的重复项过滤掉。

>>>L = [1,2,3,1,2,4,5]   #过滤掉列表L中的重复元素
>>>set(L)
{1,2,3,4,5}
>>>L = list(set(L))
>>>L
[1,2,3,4,5]

九:布尔型

  python 如今正式有了一种明确的布尔型数据类型,叫做bool ,其值为True 和 False ,并且其值True和False 是预先定义的内置的变量名。在内部,仅仅是内置的整数类型 int 的一个子类(以面向对象的观点看),其行为和整数1和0是一样的,但它们有特定的显示逻辑:它们是作为关键字True和False 来显示的,而不是数字1和0(技术上:bool 为它的两个对象重新定义了str和repr 的字符串格式)。此外,布尔值让真值更精确。eg: 一个无限循环现在能编写成  while True: 而不是 while 1:。类似地,通过使用 flag = False ,可以更清楚地设置标志位。

所有博文均为原著,如若转载,请注明出处!
原文地址:https://www.cnblogs.com/zpcoding/p/8761892.html