Python 数据类型 ╰半橙微兮° 2022-07-15 02:50 151阅读 0赞 bool None、0、空字符串、以及没有元素的容器对象都可视为 False,反之为 True。 >>> map(bool, \[None, 0, "", u"", list(), tuple(), dict(), set(), frozenset()\]) \[False, False, False, False, False, False, False, False, False\] 虽然有点古怪,但 True、False 的确可以当数字使⽤用。 >>> int(True) 1 >>> int(False) 0 >>> range(10)\[True\] 1 >>> x = 5 >>> range(10)\[x > 3\] 1 int 在 64 位平台上,int 类型是 64 位整数 (sys.maxint),这显然能应对绝⼤大多数情况。整数是虚拟机 特殊照顾对象: • 从堆上按需申请名为 PyIntBlock 的缓存区域存储整数对象。 • 使⽤用固定数组缓存 \[-5, 257) 之间的⼩小数字,只需计算下标就能获得指针。 • PyIntBlock 内存不会返还给操作系统,直⾄至进程结束。 24 看看 "⼩小数字" 和 "⼤大数字" 的区别: >>> a = 15 >>> b = 15 >>> a is b True >>> sys.getrefcount(a) 47 >>> a = 257 >>> b = 257 >>> a is b False >>> sys.getrefcount(a) 2 因 PyIntBlock 内存只复⽤用不回收,同时持有⼤大量整数对象将导致内存暴涨,且不会在这些对象被 回收后释放内存,造成事实上的内存泄露。 ⽤用 range 创建⼀一个巨⼤大的数字列表,这就需要⾜足够多的 PyIntBlock 为数字对象提供存储空间。但 换成 xrange 就不同了,每次迭代后,数字对象被回收,其占⽤用内存空闲出来并被复⽤用,内存也就 不会暴涨了。 运⾏行下⾯面测试代码前,必须先安装 psutil 包,⽤用来获取内存统计数据。 $ sudo easy\_install -U psutil $ cat test.py \#!/usr/bin/env python import gc, os, psutil def test(): x = 0 for i in range(10000000):? \# xrange x += i return x def main(): print test() gc.collect() p = psutil.Process(os.getpid()) 25 print p.get\_memory\_info() if \_\_name\_\_ == "\_\_main\_\_": main() 对⽐比 range 和 xrange 所需的 RSS 值。 range: meminfo(rss=93339648L, vms=2583552000L)? \# 89 MB xrange: meminfo(rss=8638464L, vms=2499342336L)? \# 8 MB 在实际开发中,很少会遇到这样的情形。就算是海量整数去重、排序,我们也可⽤用位图等算法来节 约内存使⽤用。Python 3 已经⽤用 xrange 替换掉了默认的 range,我们使⽤用 2.x 时稍微注意⼀一下即 可。 long 当超出 int 限制时, 会⾃自动转换成 long。 作为变⻓长对象,只要有内存⾜足够,⾜足以存储⽆无法想象的 天⽂文数字。 >>> a = sys.maxint >>> type(a) <type 'int'> >>> b = a + 1? ? ? ? \# 超出,⾃自动使⽤用 long 类型。 >>> type(b) <type 'long'> >>> 1 << 3000 12302319221611....890612250135171889174899079911291512399773872178519018229989376L >>> sys.getsizeof(1 << 0xFFFFFFFF) 572662332 使⽤用 long 的机会不多,Python 也就没有必要专⻔门为其设计优化策略。 float 使⽤用双精度浮点数 (float),不能 "精确" 表⽰示某些⼗十进制的⼩小数值。尤其是 "四舍五⼊入 (round)" 的 结果,可能和预想不同。 >>> 3 / 2? ? ? \# 除法默认返回整数,在 Python 3 中返回浮点数。 1 >>> float(3) / 2 1.5 26 >>> 3 \* 0.1 == 0.3? ? \# 这个容易导致莫名其妙的错误。 False >>> round(2.675, 2)? ? \# 并没有想象中的四舍五⼊入。 2.67 如果需要,可⽤用 Decimal 代替,它能精确控制运算精度、有效数位和 round 的结果。 >>> from decimal import Decimal, ROUND\_UP, ROUND\_DOWN >>> float('0.1') \* 3 == float('0.3')? ? ? ? ? \# float 转型精度不同 False >>> Decimal('0.1') \* 3 == Decimal('0.3')? ? ? ? \# decimal 没有问题 True >>> Decimal('2.675').quantize(Decimal('.01'), ROUND\_UP)? ? \# 精确控制 round Decimal('2.68') >>> Decimal('2.675').quantize(Decimal('.01'), ROUND\_DOWN) Decimal('2.67') 在内存管理上,float 也采⽤用 PyFloatBlock 模式,但没有特殊的 "⼩小浮点数"。
还没有评论,来说两句吧...