包括Python中的常用数据类型。

int

64位平台上,int类型是64位整数:

  • 从堆上按需申请名为PyIntBlcok的缓存区域存储整数对象
  • 使用固定数组缓存[-5, 257]之间的小数字,只需计算下标就能获得指针
  • PyIntBlock内存不会返还给操作系统,直至进程结束
1
2
3
4
5
6
7
8
9
10
11
12
a = 15
b = 15
a is b
True
a = 1000
b = 1000
>>> a is b
False
>>> a = 257
>>> b = 257
>>> a is b
False

根据第三点,如果使用range创建巨大的数字列表,这就需要很大内存空间。但是换成xrange,每次迭代之后数字对象被回收,其占用内存空间出来并被复用,内存就不会暴涨。(仅指python2)。
当超出int限制时,会自动转换成为long

float

python2中,/默认返回整数,而python3中默认返回浮点数。如果需要准确控制运算精度,有效位数和round的结果,使用Decimal代替。(但是建议往Decimal传入字符串型的浮点数 – 为什么你需要少看垃圾博客以及如何在Python里精确地四舍五入

1
2
3
4
5
>>> from decimal import Decimal, ROUND_UP, ROUND_DOWN
>>> float('0.1') * 3 == float('0.3')
False
>>> Decimal('0.1') * 3 == Decimal('0.3')
True

string

不太熟的方法

  • splitlines(): 按行分割
  • find(): 查找
  • lstrip()/rstrip()/strip(): 剔除前后空格
  • replace():替换字符
  • expandtabs():将tab替换成空格
  • ljust()/rjust()/center()/zfill():填充

    字符编码

    在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,转换为UTF-8编码。
    py3

    包括bytesstr。字节的实例包含8个原生比特值,字符串实例是由Unicode字符组成

py2

包括strunicode。字符串代表原生的8比特,而unicodeUnicode字符组成。

因此代码中,最核心的部分应该使用Unicode字符类型,即py3中使用strpy2中使用unicode。这两种字符类型没有相关联的二进制编码(原生的8个比特值),因此如果要将Unicode转换为二进制数据,应该使用encode方法。而反过来,如果要二进制编码转化为Unicode字符,必须使用decode方法。
py3中的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
def (bytes_or_str):
if isinstance(bytes_or_str, bytes):
value = bytes_or_str.decode('utf-8')
else:
value = bytes_or_str
return value def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str):
value = bytes_or_str.encode('utf-8')
else:
value = bytes_or_str
return value

py2中的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
def to_unicode(unicode_or_str):
if isinstance(unicode_or_str, str):
value = unicode_or_str.decode('utf-8')
else:
value = unicode_or_str
return value def (unicode_or_str):
if isinstance(unicode_or_str, unicode):
value = unicode_or_str.encode('utf-8')
else:
value = unicode_or_str
return value

需要注意的是两大陷阱:

  • py2中,当一个str类型仅仅包含7个比特的ASCII码字符的时候,unicodestr实例看起来是一致的。因此可以采用:

    • +运算符合并strunicode
    • 可以使用等价或者不等价运算符来比较strunicode实例
    • 可以使用unicode来替换像%s这种字符串中的格式化占位符

      然而在py3中,bytesstr的实例是不可能等价的。

  • py3中,涉及到文件的处理操作,例如采用内置的open函数,会默认以utf8编码,而在py2中默认采用二进制的形式编码。举个例子,在py3的情况下,会报错:

    1
    2
    3
    4
    5
    def open('/tmp/random.bin','w') as f:
    f.write(os.urandom(10)) >>>
    TypeError: must be str,not bytes

这是因为py3中对于open函数新增了名为encoding的参数,并且此参数默认值为utf-8。因此,其对文件的源的期望是包含了unicode字符串的str实例,而不是包含了二进制的bytes文件。因此,可以采用py2py3中都通用的方法:

1
2
with open('/tmp/random.bin','wb') as f:
f.write(os.urandom(10))

画重点

  • py3中,bytes是包含8个比特位的序列,str是包含unicode的字符串,它们不能同时出现在操作符>或者+中。
  • py2中,str是包含8个比特位的序列,而unicode是包含unicode的字符串,二者可以同时出现在只包含7个比特的ASCII码的运算中。
  • 使用工具函数来确保程序输入的数据是程序预期的类型,例如上面的to_str之类的函数。
  • 总是使用wbrb模式来处理文件。

string.ascii_letters/digits

使用string类的ascii_letters或者digits可以获得大小写字符,以及数字,避免自己写循环生成:

1
2
3
4
5
6
7
>>> import string
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> type(string.ascii_letters)
<class 'str'>
>>> string.digits
'0123456789'

池化

使用intern()可以把运行期动态生成的字符串池化:

1
2
3
4
5
>>> s = "".join(['a', 'b', 'c'])
>>> s is "abc"
False
>>> intern(s) is "abc"
True

dict

  • popitem()

    随机返回并删除字典中的一对键值

  • setdefault(key, default=None)

    如果字典中包含有给定键,则返回键对应的值,否则返回为该键设置的值。

  • fromkeys(it, [initial])

    返回以可迭代对象it里的元素为键值的字典,如果有initial参数,就把它作为这些键对应的值,默认是None

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    In [104]: info = {}.fromkeys(['name', 'blog'])
    
    In [105]: info
    Out[105]: {'blog': None, 'name': None} In [106]: info = {}.fromkeys(['name', 'blog'], ['angel', 'jay']) In [107]: info
    Out[107]: {'blog': ['angel', 'jay'], 'name': ['angel', 'jay']} In [110]: info = {}.fromkeys(['name', 'blog', 'test'], 'angel') In [111]: info
    Out[111]: {'blog': 'angel', 'name': 'angel', 'test': 'angel'}
  • update

    使用指定键值对更新字典

可以采用key=value的形式:

1
2
3
4
In [112]: info.update(blog='jay')

In [113]: info
Out[113]: {'blog': 'jay', 'name': 'angel', 'test': 'angel'}

也可以采用{key:value}的形式:

1
2
3
4
In [114]: info.update({'test':'album'})

In [115]: info
Out[115]: {'blog': 'jay', 'name': 'angel', 'test': 'album'}

也可以使用tuple的形式:

1
2
3
4
In [119]: info.update((('name', 'unkown'),('test', 'secret')))

In [120]: info
Out[120]: {'blog': 'jay', 'name': 'unkown', 'test': 'secret'}

对于大字典,调用keys()values()items()会同样构造巨大的列表,因此可以使用迭代器(iterkeys()itervalues()iteritems())减少内存开销。

1
2
3
4
5
6
7
8
9
10
11
12
>>> d = {"a":1, "b":2}
>>> d.iterkeys()
<dictionary-keyiterator object at 0x7fde6e70b368>
>>> d.itervalues()
<dictionary-valueiterator object at 0x7fde6e70b3c0>
>>> d.iteritems()
<dictionary-itemiterator object at 0x7fde6e70b368>
>>> for k, v in d.iteritems():
... print k, v
...
a 1
b 2

视图

判断两个字典间的差异,除了使用Counter,也可以使用视图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> d1 = dict(a=1, b=2)
>>> d2 = dict(b=2, c=3)
>>> d1 & d2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'dict' and 'dict'
>>> v1 = d1.viewitems()
>>> v2 = d2.viewitems()
>>> v1 & v2
set([('b', 2)])
>>> v1 | v2
set([('a', 1), ('b', 2), ('c', 3)])
>>> v1 - v2
set([('a', 1)])
>>> v1 ^ v2
set([('a', 1), ('c', 3)])

视图会和字典同步变更:大专栏  Python拾遗(2)r/>

1
2
3
4
5
6
7
8
9
10
>>> d = {"a": 1}
>>> v = d.viewitems()
>>> v
dict_items([('a', 1)])
>>> d["b"] = 2
>>> v
dict_items([('a', 1), ('b', 2)])
>>> del d["a"]
>>> v
dict_items([('b', 2)])

collections.defaultdict

在实例化一个defaultdict的时候,需要给构造方法提供一个可调用对象或者无参数函数,这个可调用对象会在__getitem__(例如dd是个defaultdict,当dd[k]时会调用此方法)碰到找不到的键的时候被调用,让__getitem__返回某种默认值。如果在创建defaultdict的时候没有指定可调用对象,查询不存在的键会触发KeyError(这是由于__missing__方法的缘故)。
使用一个类型初始化,当访问键值不存在时,默认值为该类型实例。

1
2
3
4
5
6
>>> dd = defaultdict(list)
>>> dd['foo']
[]
>>> cc = defaultdict(dict)
>>> cc['foo']
{}

也可以使用不带参数的可调用函数进行初始化,当键值没有指定的时候,可以采用该函数进行初始化

1
2
3
4
5
6
7
8
9
10
11
>>> import collections
>>> def default_factory():
... return 'default value'
...
>>> d = collections.defaultdict(default_factory, foo='bar')
>>> print('d:', d)
d: defaultdict(<function default_factory at 0x7f2c39c04378>, {'foo': 'bar'})
>>> print(d['foo'])
bar
>>> print(d['bar'])
default value
1
2
3
4
5
6
>>> def zero():
... return 0
...
>>> ff = defaultdict(zero)
>>> ff['foo']
0

简化为:

1
2
3
>>> ee = defaultdict(lambda : 0)
>>> ee['foo']
0

OrderedDict

字典是哈希表,默认迭代是无序的,如果需要元素按照添加顺序输出结果,可以使用OrderedDict

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> from collections import OrderedDict
>>> od = OrderedDict()
>>> od["a"] = 1
>>> od["c"] = 3
>>> od["b"] = 2
>>> for k, v in od.items(): print k, v
...
a 1
c 3
b 2
>>> od.popitem()
('b', 2)
>>> od.popitem()
('c', 3)
>>> od.popitem()
('a', 1)

因为字典是有序的,因此当使用popitem时,不再是随机弹出

set

set方法的pop也是随机弹出的。集合和字典的主键都必须是可哈希类型对象。

1
2
3
4
5
6
7
8
9
10
11
>>> a = frozenset('abc')
>>> a
frozenset(['a', 'c', 'b'])
>>> a.add('d')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'
>>> b = set('abc')
>>> b.add('d')
>>> b
set(['a', 'c', 'b', 'd'])

如果需要将自定义类型放入集合中,需要保证hashequal的结果都相同才行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class User(object):

    def __init__(self, name):
self.name = name def __hash__(self):
return hash(self.name) def __eq__(self, other):
cls = type(self)
if not other or not isinstance(other, cls):
return False
return self.name == other.name s = set()
s.add(User('tom'))
s.add(User('tom'))
print s

list

对于频繁增删元素的大型列表,应该考虑使用链表或者迭代器创建列表对象的方法(itertools)。某些时候,可以考虑用数组(array)代替列表,但是它只能放指定的数据类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import array
>>> a = array.array("l", range(10)) # 创建一个long类型的数组
>>> a
array('l', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.tolist() #转化为list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = array.array("c")
>>> a.fromstring("abc")
>>> a
array('c', 'abc')
>>> a.fromlist(list("def"))
>>> a
array('c', 'abcdef')
>>> a.extend(array.array("c", "xyz"))
>>> a
array('c', 'abcdefxyz')

向有序列表插入元素

1
2
3
4
5
>>> l = ["a", "d", "c", "e"]
>>> l.sort()
>>> bisect.insort(l, "b")
>>> l
['a', 'b', 'c', 'd', 'e']

Tuple

在对tuple进行比较的时候,Python会优先比较元组中下标为0的元素,然后依次递增。有个很神奇的例子:

1
2
3
4
5
6
7
8
9
10
11
12
>>> values = [1,5,3,9,7,4,2,8,6]
>>> group = [7, 9]
>>> def sort_priority(values, group):
... def helper(x):
... if x in group:
... return (0, x)
... return (1, x)
... values.sort(key=helper)
...
>>> sort_priority(values, group)
>>> print(values)
[7, 9, 1, 2, 3, 4, 5, 6, 8]

namedtuple

需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。

继承自tuple的子类,创建的对象拥有可以访问的属性,但是仍然是只读的。

1
2
3
4
5
>>> from collections import namedtuple
>>> TPoint = namedtuple('TPoint', ['x', 'y'])
>>> p = TPoint(x=10, y=10)
>>> p.x, p.y
(10, 10)

也可以使用TPoint = namedtuple('TPoint', 'x y')这种格式

  • 将数据变为namedtuple类:

    1
    2
    3
    4
    5
    6
    7
    >>> TPoint = namedtuple('TPoint', ['x', 'y'])
    >>> t = [11 , 22]
    >>> p = TPoint._make(t)
    >>> p
    TPoint(x=11, y=22)
    >>> p.x
    11
  • 如果要进行更新,需要调用方法_replace

    1
    2
    3
    4
    5
    6
    7
    8
    >>> p
    TPoint(x=10, y=10)
    >>> p.y = 33
    Traceback (most recent call last):
    File "<input>", line 1, in <module>
    AttributeError: can't set attribute
    >>> p._replace(y=33)
    TPoint(x=10, y=33)
  • 将字典数据转换成namedtuple

    1
    2
    3
    4
    >>> p = {'x': 44, 'y': 55}
    >>> p = TPoint(**p)
    >>> p
    TPoint(x=44, y=55)

Python拾遗(2)的更多相关文章

  1. [python拾遗]异常处理

    异常 异常(Exception)是因为程序的例外.违例.出错等情况而在正常控制流以外采取的行为,一般分为如下两个阶段: 1.异常发生:一个错误发生后被打印出来,称为未处理异常,而默认的处理则是自动输出 ...

  2. [python拾遗]列表

    python列表拾遗 1.列表可以修改,使用 ‘+’ 将一个新列表附加在原列表的尾部: >>> a = [1,'a'] >>> b = a + [2,'b'] &g ...

  3. [python拾遗]文件操作

    文件操作 1.open()函数 open()函数主要用于文件处理,一般分为下面3个过程: 1.打开文件 2.操作文件 3.关闭文件 常见的格式示例: f = open('note.txt','r') ...

  4. [python拾遗]enumerate()函数

    在python中处理各类序列时,如果我们想显示出这个序列的元素以及它们的下标,可以使用enumerate()函数. enumerate()函数用于遍历用于遍历序列中的元素以及它们的下标,用法如下: 1 ...

  5. python 拾遗

    三引号 可以当做多行字符串使用.在类或者方法中用的时候,可以当做docstrings来使用.具体的规则为: 该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束.第二行为空行 ...

  6. Python拾遗

    for...else...语句 用 break 关键字终止当前循环就不会执行当前的 else 语句,而使用 continue 关键字快速进入下一论循环,或者没有使用其他关键字,循环的正常结束后,就会触 ...

  7. Python 中的一些小技巧

    这里是本人收集的一些 Python 小技巧,目前主要是一些实用函数,适合有一定基础的童鞋观看(不会专门介绍使用到的标准库函数).. 一.函数式编程 函数式编程用来处理数据,感觉很方便.(要是再配上管道 ...

  8. 我的Python笔记补充:入门知识拾遗

    声明:本文整理借鉴金角大王的Python之路,Day1 - Python基础1,仅供本人学习使用!!! 入门知识拾遗 一.bytes类型 二.三元运算 1 result = 值1 if 条件 else ...

  9. python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

随机推荐

  1. ZJNU 1205 - 侦探推理——高级

    双层枚举嫌疑犯与当日是星期几,统计真话与假话是否满足题意 注意 fake<=N&&fake+neutral>=N 即假话数量不大于N,假话加上没用的废话数量不小于N (注意 ...

  2. requset请求处理与BeanUtils封装

    HTTP: 概念:Hyper Text Transfer Protocol 超文本传输协议 传输协议:定义了,客户端和服务器端通信时,发送数据的格式 特点: 基于TCP/IP的高级协议 默认端口号:8 ...

  3. HTTP知识整理

    HTTP协议 HTTP协议的主要特点可概括如下: 1.支持客户/服务器模式. 2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有GET.HEAD.POST.每种方法规定了客 ...

  4. ! [remote rejected] master -> master (pre-receive hook declined)

    前天准备上传一个project到GitLab上,但是试了很多次都上传不上去,报错如下: ! [remote rejected] master -> master (pre-receive hoo ...

  5. linux中 su 与 su - 的区别

    linux中 su 与 su - 的区别 su只是切换了用户身份,shell环境仍然是切换前用户的shell环境 su -是用户和shell环境一起切换成. 备注:1.切换了shell环境会相应的用户 ...

  6. shell_backup_MySQL

    #!/bin/bash #可修改如下参数backup_filename=$(date +%Y%m%d%H%M%S)backup_tmp_dir=/data/backup/ip=10.0.1.182us ...

  7. static及final知识点整理

    final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译 ...

  8. 三十四、www服务apache进阶

    9.虚拟主机:部署多个站点,每个站点希望用不同的站点域名和站点目录,或者是不同的端口和不同的IP,则需要虚拟主机,简单理解就是一个http服务要配置多个站点,就要虚拟主机. apache虚拟主机分为三 ...

  9. [LC] 373. Find K Pairs with Smallest Sums

    You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...

  10. dom4j 为生成 XML 的文件添加 xmlns(命名空间) 属性

    dom4j 为生成 XML 的文件添加 xmlns(命名空间) 属性 分类: Java2011-06-03 16:14 976人阅读 评论(0) 收藏 举报 xml扩展语言 今天在开发sitemap地 ...