Python的日常:常用数据类型

数据类型定义了数据的长度和能够对该类数据实施的一些操作。在C语言中,某类型的变量实际是某块内存空间的首地址,对该变量的操作,将直接操作到内存中存放的数据。

Python的设定是一切皆为对象。定义一个变量将自动创建一个对象,对象绑定了值和相关的操作。例如:a = "abc",将会以"abc”创建一个字符串对象,变量a则是对该对象的引用。

如果对a进行赋值操作,其实是改变了其所引用的位置,被引用的对象本身并不会被修改。如果有新的变量被定义为同样的值,如:b = “abc”,b将会引用定义a时创建的那个对象。

每个对象都会有确定的身份、类型和值。对象一旦被创建,其身份和类型就不可改变。对象创建后,其值允许被修改的叫做可变对象,否则为不可变对象。如果非要修改不可变对象的值,就只能对其做赋值操作,即,显式改变引用位置。

  • 身份:对象的唯一标识,标识了该对象所在的内存地址,可用id()方法查看。

  • 类型:对象的类型决定了它所能进行的操作,用type()方法查看。

  • 值:由该对象维护的具体内容。

3.1. 类型概括

一些常见的内置类型

  • 数字:int,long,float,complex(复数),bool(True, False)
  • 字符:str,unicode
  • 列表:list
  • 字典:dict
  • 元组:tuple
  • 文件:file
  • 其它类型:set(集合,多个数据聚集在一起,没有顺序),frozenset(冻结集合,不可变),None等

其它文件类工具(与文件相关的):pipes(管道)、fifos(先进先出管道)、sockets(套接字文件)、面向对象的接口(用于访问数据库的接口ORM)等。

Python是动态类型,同时也是强类型语言,实施不属于某类型的任何操作,都会引发异常。

一些常用的类型转换函数:

  • str(),repr(),format():将非字符型转换为字符。简单地说,str()得到的是一个对用户友好的字串,repr()则会给出一个更精确地,用于描述对象的一个字串;format是利用我们指定的特定格式来转换成字符串。
  • int():转为整数。
  • float():转为浮点。

  • list(s):将字符串s转换为列表,把字串中的每一个字符当做列表中的每一个元素。很少将列表转换成字串,需要对列表进行遍历,拼接出字串,效率较低。

  • tuple(s):将字串s转换为元组,元组是不可变类型。
  • set(s):将字串s转换为集合(没有次序的,放在一起的一堆元素,它会自动去掉重复元素)。
  • dict(d1):创建字典(字典本身也是没有次序的);根据指定的键值对创建字典,d1必须是k-v元组序列(元组列表)。比如:d1 = (‘a’,1),(‘b’,11),d = dict(d1)。
  • frozenset(s):将字串s转换为不可变的set,set本身是可变的。

  • chr(x):将整数转换为单个字符(即str类型,字符就是单个的str,没有char类型)。

  • ord(x):将字符转换成整数值。
  • hex(x):将整数转为16进制字符串。
  • bin(x):转换为二进制字符串 。
  • oct(x):转为8进制字符串。

3.2. 数字类型

Python支持五种数字类型:整型、长整型、浮点型、复数和布尔型。它们均是不可变对象。

常用操作:

  • 加:a + b
  • 减:a - b
  • 乘:a * b
  • 除:a / b
  • 截断除:a // b (直接舍去小数部分)
  • 取模:a % b
  • 乘方(a的b次方):a ** b
  • 左移:a << b
  • 右移:a >> b
  • 按位与:a & b
  • 按位或:a | b
  • 按位异或:a ^ b
  • 按位取反:~a

使用Python著名的numpy库,可以进行复杂的科学运算。

3.3. 序列类型

序列是对象的有序集合,包括字符串,列表和元组。序列类型有一组通用的操作,以字符串s = “abcdefg”为例说明:

  • 索引运算:使用[i]运算符
  • 切片运算:使用[i:j]运算符。切出的字串会将会产生一个新的对象。
  • 指定步长的切片运算:使用[i:j:n]运算符。通常的切片运算,在提取字符的时候,是以给定的起始位置,逐个向后提取,即:索引号每次增1,这里的n用来指定每次增加的数值。
  • 成员判断:a in s,a not in s,判断a是否是s中的元素。
  • 拼接两个序列:假设要拼接两个序列s和a,方法为 s + a
  • 将序列重复n次:将s重复n次,方法为 s * n

  • min(s)函数:返回序列s中的最小值,对于字符串来说,根据ASCII码来计算。

  • max(s)函数:返回序列s中的最大值,对于字符串来说,根据ASCII码来计算。
  • len(s)函数:返回序列s中的元素个数。
  • sum(s)函数:计算s中各元素的和,它只适用于数字序列。
  • all(s)函数:检查s的所有项是否都为True,是的话返回True。
  • any(s)函数:检查s中是否存在为True的元素,是的话返回True。

以下操作,要求对序列进行改动,因此只适用于可变对象,对字符串不适用:

  • s[i] = x:对序列中的指定元素赋值。
  • s[i:j] = y:对切片赋值。
  • s[i:j:n] = y:对指定步长的切片赋值。
  • del(s[i]):删除序列中的指定元素。
  • del(s[i:j]):删除切片。
  • del(s[i:j:n]):删除指定步长的切片。

3.3.1. 字符串

用字符类型表示的字符串字面量,它是不可变对象。把字符放入单引号,双引号或者三引号中即可。单引号(’ ’)双引号,(” ”)和三引号(’’’ ’’’)表示法,并无本质区别,只是三引号可以跨行。

Python2中定义字符串的时候,默认不是unicode类型,若要使用unicode编码,需要显示指定,如:u”abcdefg”

常用的内置操作:

  • s.lower():将所有元素变为小写。
  • s.upper():将所有元素变为大写。
  • s.capitalize():将首个元素大写,其余小写。
  • s.split([sep[,n]]):以字符(串)sep作为分隔点,对s进行分隔,n指定了分隔次数。
  • s.join(x):以s为分隔点,将x中的各元素拼接成一个字符串。x可以是一个字符串,元组或列表。
  • s.index(sub[,start[,end]]):查找子串sub在s中首次出现的位置,返回值为子串的首个字符的索引号。start和end用来指定查找范围。
  • s.replace(dst, src[,n]):用src串替换dst串,n指定替换次数。

3.3.2. 列表(list)

列表是一个容器(包含了对其它对象的引用的对象),它可以包含任意类型的对象(支持异构),可以嵌套,长度可变。他是可变对象。

常用的内置操作:

  • l.index(value[,start[,end]]):查找元素value在列表l中首次出现的位置(索引号)。start和end用来指定查找范围。
  • l.count(value):查询指定元素value在列表l中出现的次数。
  • l.append(object):将对象object作为一个元素追加到列表l末尾。
  • l.extend(iterable):将一个可迭代的对象(字符串,列表,元组)中的元素,依次加入到列表l的末尾。
  • l.insert(index, object):在指定索引位置之前插入一个对象。
  • l.pop([index]):弹出指定索引位置的元素,弹出的元素作为返回值给出。不指定参数,将弹出末尾元素。
  • l.remove(value):按值删除列表l中的元素。
  • l.reverse():逆序。
  • l.sort():升序。

像列表这种允许被改值的对象,就不能指望通过赋值操作来“保存”对象的值。基于Python的设定,将一个已有的对象赋给另一个对象,其实是创建了一个引用。而被引用的这个对象的值是允许被修改的,就意味着那个被“保存”的值很有可能被修改掉。

对于列表对象,可通过如下方式产生一个新对象,而非对目标对象的引用。这样就可以用这个新对象来“保存”目标对象的值了:

1
list_1 = list_2[:]

最后,有一种基于现有序列快速生成列表的方法:“列表解析”。


列表解析会一次性生成整个列表并返回,如果列表很长的话,这么做显然会消耗大量内存。其实,列表中的元素有可能大部分都不会被用到。有一种比列表解析更节省内存空间的方法叫做“生成器”。使用生成器表达式并不会真的生成一个完整的列表,而是返回一个生成器对象。

生成器使用的是延迟计算机制,真正需要的时候才会计算(yield)出值。生成器与列表解析的语法差别只是使用了不同的括号而已。

3.3.3. 元组(tuple)

元组也是一种容器,它可以包含任意类型的对象(支持异构),可以嵌套,长度固定。他是不可变对象。

常用的内置操作:

  • 有与列表类似的count和index操作。

3.4. 字典(dict)

字典(关联数组或散列表)是对象的无序集合,通过key来检索元素。它也是容器,可包含任意类型的对象(支持异构),可嵌套,长度可变,是可变对象。

常用的内置操作:

  • d.clear():清除所有元素。
  • d.copy():返回字典d的一个副本。
  • d.keys():返回一个用键构成的列表。
  • d.values():返回一个用值构成的列表。
  • d.items():把字典d转为以元组为元素的列表并返回,每一个元组对应了字典d中的一个key-value对。
  • d.update(d1):用字典d1更新字典d,d1中的键值对会加入到d中,若有键重复,则d1会覆盖掉d中的相应键值对。
  • d.get(key):返回指定key对应的值。
  • d.pop(key):弹出指定key的元素(key-value对)。
  • d.popitem():随机弹出元素(key-value对)。
  • d.iteritems():返回一个key-value对迭代器。例如:it = d.iteritems(),使用it.next()进行迭代。

3.5. 集合(set)

集合由一组无序对象组成,支持数学中的集合关系运算。它有两类,可变集合set和不可变集合frozenset。创建时必须使用工厂函数。

集合不支持通过索引获取单个元素。

常用的内置操作:

  • s.copy():返回集合s的一个副本。
  • s.union(s1):计算s与s1的并集,返回结果为一个集合。可直接使用 s | s1 求并集。
  • s.intersection(s1):计算s与s1的交集,返回结果为一个集合。可直接使用 s & s1 求交集。
  • s.difference(s1):计算s与s1的差集,即,在s中且不在s1中的那些元素。返回结果为一个集合。可直接使用 s - s1 求差集。
  • s.symmetric_difference(s1):计算s与s1的对称差集,即,在s中且不在s1中的元素与在s1中且不在s中的元素的并集,也就是求不同时在s和s1中的那些元素。可直接使用 s ^ s1 求对称差集。
  • s.issubset(s1):判断s是否是s1的一个子集,是的话返回True。
  • s.issuperset(s1):判断s是否是s1的一个超集,是的话返回True。
  • s.isdisjoint(s1):判断s与s1是否“没有”交集,没有的话返回True。

<== index ==>