Python作为一种弱类型编程语言,其数据类型较之于C/C++无论是在数据的存储还是调用都有着很大的区别。其特有的字典类型更是一个非常经典且功能强大的数据类型。下面一起来学习Python的数据类型,期间也会穿插一些Python的实用技巧。
整型int是一种不可变类型
In [9]: num = 1
In [10]: num = 2
In [11]: num
Out[11]: 2
需要注意的是,num = 1、 num = 2 并不是同一个数据对象。第一个num变量保存着 1 在内存中存储的索引地址,第二个变量num则表示 2 在内存中存储的索引地址。在上面的两次赋值中,1、2 两个数据对象在内存中并没有改变,改变的只是 num 变量所指向的内存地址。所以说int类型是一种不可变类型,int类型对象在内存中并不会发生改变,但可以改变int型对象所对应变量的值。其调用过程为:变量num只存储了索引地址,再通过索引找到在内存中存储的int型对象,并最终引用出来。
In [51]: floatTest
Out[51]: 3.141592
In [52]: floatTest = 3.14159299999999999999999999999999999999999
In [53]: floatTest
Out[53]: 3.141593
In [54]: type(float)
float floatTest
上面的例子可以看出Python中float类型的数据同样有着存储限制。
Python还支持复数,为Math领域的研究提供了非常好的支持。
In [48]: pulralTest = 3+6j
In [49]: pulralTest
Out[49]: (3+6j)
In [12]: bool = False
In [13]: bool
Out[13]: False
In [15]: bool = True
In [16]: bool
Out[16]: True
布尔类型可以直接赋值,注意首字母要大写。
In [42]: 2*3
Out[42]: 6
In [43]: print _
6
使用dir( )函数可以显示Python一般对象的内置方法,如下:
In [58]: import platform
In [59]: dir(platform)
Out[59]:
['DEV_NULL',
'__builtins__',
'__copyright__',
'__doc__',
'__file__',
'__name__',
'__package__',
'__version__',
'_abspath',
'_architecture_split',
'_bcd2str',
'_codename_file_re',
'_default_architecture',
'_dist_try_harder',
'_distributor_id_file_re',
'_follow_symlinks',
'_ironpython26_sys_version_parser',
'_ironpython_sys_version_parser',
'_java_getprop',
'_libc_search',
'_lsb_release_version',
'_mac_ver_gestalt',
'_mac_ver_lookup',
'_mac_ver_xml',
'_node',
'_norm_version',
'_parse_release_file',
'_platform',
'_platform_cache',
'_popen',
'_pypy_sys_version_parser',
'_release_file_re',
'_release_filename',
'_release_version',
'_supported_dists',
'_sys_version',
'_sys_version_cache',
'_sys_version_parser',
'_syscmd_file',
'_syscmd_uname',
'_syscmd_ver',
'_uname_cache',
'_ver_output',
'_win32_getvalue',
'architecture',
'dist',
'java_ver',
'libc_ver',
'linux_distribution',
'mac_ver',
'machine',
'node',
'os',
'platform',
'popen',
'processor',
'python_branch',
'python_build',
'python_compiler',
'python_implementation',
'python_revision',
'python_version',
'python_version_tuple',
're',
'release',
'string',
'sys',
'system',
'system_alias',
'uname',
'version',
'win32_ver']
In [60]: dir(type)
Out[60]:
['__abstractmethods__',
'__base__',
'__bases__',
'__basicsize__',
'__call__',
'__class__',
'__delattr__',
'__dict__',
'__dictoffset__',
'__doc__',
'__eq__',
'__flags__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__instancecheck__',
'__itemsize__',
'__le__',
'__lt__',
'__module__',
'__mro__',
'__name__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasscheck__',
'__subclasses__',
'__subclasshook__',
'__weakrefoffset__',
'mro']
而Module或函数的__doc__方法可以显示Module或函数的Document,以此来认识一个Module或函数。而这些Document,写入在Python Module文件首部的三引号中”’ “’,同时”’ ”’作为批量输出的标识,用于同时输出多行内容或充当注释。
In [64]: platform.__doc__
Out[64]: ' This module tries to retrieve as much platform-identifying data as\n possible. It makes this information available via function APIs.\n\n If called from the command line, it prints the platform\n information concatenated as single string to stdout. The output\n format is useable as part of a filename.\n\n'
In [65]: id.__doc__
Out[65]: "id(object) -> integer\n\nReturn the identity of an object. This is guaranteed to be unique among\nsimultaneously existing objects. (Hint: it's the object's memory address.)"
Python最基本的组合数据结构就是序列。序列,即由非负整数索引的对象的有序集合。有下列6种内建序列类型,其中又可以归为3类:
1. 整数序列:xrange对象
2. 字符序列:字符串、buffer(缓冲区)对象、Unicode字符串
3. 对象序列:列表、元组
其中列表、元组、字符串都是Python程序中非常常用的两种类型。
字符串是一种序列,可以通过索引引用,以字符为单位,属于不可变类型。当定义一个str对象时,str对象会在内存中以ASCII码的格式从索引对象指定的入口地址依次以字符为单位存放起来,其中每一个Char都占用1Byte(8bit)的存储空间。
注:在Python中的字符串可以使用 ‘Str’ 或者 “Str” 括起来,而且两者没有任何的区别,只视乎于那一个使用起来更加方便和更适合使用环境。随便一提’” Document ‘”在Python中表示文档,用在代码行中,有类似注释的功能,而且’” ‘”中可以使用单引号和双引号。
例子(1).
In [19]: name = 'jmilk'
In [20]: id(name)
Out[20]: 140682798476624
In [21]: name = 'chocolate'
In [22]: id(name)
Out[22]: 140682799006128
In [23]: type(name)
Out[23]: str
例子(2).
In [36]: name1 = 'jmilk'
In [37]: name2 = 'jmilk'
In [39]: id(name1) == id(name2)
Out[39]: True
id(variable):查询变量存储的索引地址
type(variable):查看变量的数据类型
例子(1)中,显然同一个name变量在赋与不同的字符串类型值后name变量自身的索引地址发生了改变。
例子(2)中,将同一个str对象’jmilk‘赋值给两个不同的变量,这两个变量的值(内存中的引用对象)却是一样的。
字符串的切片:
字符串最为序列的一种,可以使用切片操作符来实现字符串的切片显示。
In [62]: sentence = 'my name is jmilk'
In [63]: sentence
Out[63]: 'my name is jmilk'
(1)stringName[x:y] –>显示字符串中从第x个索引的字符–第y-1个字符,索引从0开始计算,其中的空格也算一个字符。
In [64]: sentence[0:7]
Out[64]: 'my name'
(2)当x或y为空时,默认为显示往前、往后的所有
In [66]: sentence[:7]
Out[66]: 'my name'
In [68]: sentence[7:]
Out[68]: ' is jmilk'
(3)string[x:y:步进],在上述的基础上加入步进显示
In [70]: sentence[0:7]
Out[70]: 'my name'
In [71]: sentence[0:7:3]
Out[71]: 'mne'
In [72]: sentence[0:7:2]
Out[72]: 'm ae'
从例子(3)中可以看出,步进的作用即将切片后的字符串,从第一次字符开始,往后均已以步进指定的间隔取出字符。
小结:当执行一条赋值语句时,生成了两个内存对象。分别如下:
1). 数据对象:Python会将所有的数据对象存放到分配的存储中(一般存放在内存中特定的地址块)。
2). 引用对象:既是变量,其在内存中存放指定的数据对象的索引地址,既数据对象和变量是分别存放的。程序运行时,通过引用对象(变量)来调用出数据对象的值。而且引用对象(变量)是动态类型,可以任意改变引用对象的索引值。
值得注意的是,Python自身带有垃圾回收的机制,各种对象在不被引用的时候,便自动由垃圾回收器回收。如上述例子(1),在str对象’jmilk‘不被任何引用对象指向时,会被系统回收掉其资源。
元组是不可变对象,使用tupleName = (parameters)创建。
In [3]: number = ('one','two','three')
In [4]: number
Out[4]: ('one', 'two', 'three')
In [5]: type(number)
Out[5]: tuple
In [6]: id(number)
Out[6]: 139715119475680
In [7]: number = ('one','two','four')
In [8]: id(number)
Out[8]: 139715119475360
使用id( )方法,显然两个number引用对象的索引是不一致的。而且在定义tuple对象后,就可以使用tuple对像的一些内置方法:
首先使用dir( )来获取tuple类型对象number的多有内置方法
In [9]: dir(number)
Out[9]:
['__add__',
'__class__',
'__contains__',
'__delattr__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getnewargs__',
'__getslice__',
'__gt__',
'__hash__',
'__init__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rmul__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'count',
'index']
或者也可以使用内置函数help(Object)来获取一个对象详细的帮助文档
In [25]: help(number)
会得到所有对象内置函数的使用格式和方法,如下:
Help on tuple object:
class tuple(object)
| tuple() -> empty tuple
| tuple(iterable) -> tuple initialized from iterable's items
|
| If the argument is a tuple, the return value is the same object.
|
| Methods defined here:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __eq__(...)
| x.__eq__(y) <==> x==y
|
| __ge__(...)
| x.__ge__(y) <==> x>=y
|
| __getattribute__(...)
例如可以使用__add__方法来连接两个tuple对象
In [32]: name = ('jmilk','chocolate')
In [33]: number.__add__(name)
Out[33]: ('one', 'two', 'four', 'jmilk', 'chocolate')
使用__eq__来判断两个tuple对象是否一致
In [42]: name.__eq__(number)
Out[42]: False
使用__contains__来判断tuple对象是否包含一个元素
In [44]: number.__contains__('one')
Out[44]: True
总而言之,善于使用help( )、doc()、__doc__等方法可以很好的帮助我们更加充分的认识Python这门语言,也可以非常的便于我们程序的编写。
列表是可变对象,使用ListName = [Parameters]创建。是任意对象的有序集合,通过索引访问其中的元素,可以任意的嵌套、伸长、异构(不同的数据类型,同时存放在一个List中,支持原处修改内部元素的引用。如果说元组类似于一元数组,那列表就相当于二元数组的效果。
In [41]: testListOne = [1,2,3]
In [42]: id(testListOne)
Out[42]: 139682261309632
In [45]: testListTwo = testListOne
In [43]: testListOne.append(4)
In [47]: testListOne
Out[47]: [1, 2, 3, 4]
In [48]: id(testListOne),id(testListTwo)
Out[48]: (139682261309632, 139682261309632)
从上面的例子可以看出,即便在testListOne对象中插入元素’4’后,testListOne与testListTwo的地址仍然是一致的,即在改变testListOne对象的值后,没有创建出一个新的内存对象,这是有别于不可变对象的。
值得注意的是,只有使用了List类型对象内置的append、extend、remove、insert等方法的时候才会在原有的内存对象的基础上作出修改。不可以直接使用下述的方法来直接修改一个List对象的value。
In [53]: testListOne = [1,2,3,4,5,6]
In [54]: id(testListOne),id(testListTwo)
Out[54]: (139682261332696, 139682261309632)
直接修改List对象的Value,会产生一个新的内存对象。
注:List类型的对象本质是在列表变量的引用对象指向的地址空间中存放了列表中的元素的存储索引地址。而这种可以包含其他对象的引用的对象也称为容器。所以List类型虽然是可变的,但是List的元素本身不一定是可变的。因为List作为一个组合数据类型对象其可以实现对象的嵌套,List中的元素可以是string、tuple等不可变的类型,也可以是dic、list等可变类型的嵌套。
小结:
1. 不可变对象:int、float、string、tuple 对一个不可变类型的变量赋以新的值,会改变变量引用对象的索引值,使引用对象新的索引指向新的内存对象。原有的内存对象不会发生改变,但若不再被引用对象引用时,会自动的被垃圾回收机制回收。
2. 可变对象:list、distionary 对一个可变类型的变量赋以新的值,会直接在变量引用对象指向的内存空间中存放新的value,而不会重新开辟新的空间存放新的值。
字典是Python特有的一种数据结构,其不是以下标的索引来查询数据,而是使用Key:Value的键值对来实现变量和数据的映射,所以字典也被称之为映射数据类型。字典使用dictName = {key1:vlalue1,key2:value2,…}创建。字典数据类型,使得Python程序具有了更好的灵活性,因为其键值对的设计,很好的兼用了JOSN、NoSQL等主流数据处理技术。
创建一个字典:
In [2]: dictName = {'fan':'jmilk','zhang':'san','li':'si'}
In [3]: dictName
Out[3]: {'fan': 'jmilk', 'li': 'si', 'zhang': 'san'}
显示字典中的元素:
In [17]: dictName['fan']
Out[17]: 'jmilk'
In [19]: dictName['fan'],dictName['zhang'],dictName['li']
Out[19]: ('jmilk', 'san', 'si')
分别显示字典中的keys或values
In [30]: dictName.keys()
Out[30]: ['li', 'fan', 'zhang']
In [31]: dictName.values()
Out[31]: ['si', 'jmilk', 'san']
在字典中加入key:value
In [33]: dictName['wang'] = 'wu'
In [36]: dictName
Out[36]: {'fan': 'jmilk', 'li': 'si', 'wang': 'wu', 'zhang': 'san'}
将字典中的一对key:value弹出(删除)
In [50]: dictName.pop('fan')
Out[50]: 'jmilk'
In [51]: dictName
Out[51]: {'li': 'si', 'wang': 'wu', 'zhang': 'san'}
当然,字典类型的对象还有许多使用的内置方法,建议使用help(dictName)取详细的了解一个字典类型的对象所能实现的功能。
掌握Python数据结构是编写Python程序的基本要求,当然Pyehon的数据结构的内容远比上述的要丰富许多。在以后的博文中我们更加详细
深入的去学习每一个数据类型的具体实现和功能。
Jmilk