Differences between revisions 1 and 13 (spanning 12 versions)
Revision 1 as of 2007-04-12 06:01:41
Size: 320
Editor: HuangYi
Comment:
Revision 13 as of 2007-04-17 01:28:16
Size: 16758
Editor: HuangYi
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
||'''status'''|| 草稿 || HuangYi || 0%||

[[TableOfContents]]

= 内置数据类型 =

== 数值类型 ==
=== int ===
=== float ===

== 字符串 ==
=== 常见字符串操作 ===
=== Unicode 对象 ===
=== 字符串模板 ===

== 集合类型 ==
=== Tuple ===
=== List ===
=== Dict ===
=== Set ===
##language:zh
#format rst

:status: 草稿 ;HuangYi; 20%;

===================
Python内置数据类型
===================

.. contents::

数值类型
==========

布尔
-------

在所有的语言中,布尔类型可能都是数据类型中最简单的了, ``True`` 或者 ``False`` ,干脆俐落。

在 python 中,任何对象都可以隐式地转换为布尔对象,
转换的规则如下: ``None`` 、任何数值类型中的 ``0`` 、空字符串 ``''`` 、空元组 ``()`` 、空列表 ``[]`` 、空字典 ``{}``
都被当作 ``False`` ,还有自定义的类型如果它实现了 ``__nonzero__()`` 或 ``__len__()``
方法且方法返回 ``0`` 或 ``False`` 的,则其实例也被当作 ``False`` ,其他对象均为 ``True`` 。
::

  >>> 0 or 0L or 0.0 or 0j or '' or () or [] or {} or False
  False

上面这个代码就可以证明那些对象都被当作 ``False`` ,至于为什么就留给聪明的你自己思考吧 ;-)

你还可以使用任何对象来构造 ``bool`` 对象:
::

  >>> bool(0)
  False
  >>> bool(1)
  True
  >>> bool('hello')
  True
  >>> class FooBar(object):
  ... def __nonzero__(self):
  ... return False
  ...
  >>> foobar = FooBar() # 创建 FooBar 类的实例,见 ...
  >>> bool(foobar)
  False

python 中还有三个布尔操作符:not、and 和 or,
不过他们虽然叫做布尔操作符,但由于我们上面说过的任何对象都可以隐式转换为布尔对象,
实际上这三个操作符可以操作任何对象,而且返回的也不仅仅是布尔对象。
具体规则如下:

.. sidebar:: and or 组合

  通过 and 和 or 的组合你可以获得许多奇妙的效果,
  比如 ``condition and a or b`` 实际上就等价于 c 语言中的 ``condition? a:b`` ,
  意思就是说如果条件 ``condition`` 满足那么就 ``a`` ,否则就 ``b`` 。
  有意思吧 ;-) 至于为什么就当做作业留给聪明的你慢慢思考吧(见练习题1)。

.. topic:: not a

  如果 ``a`` 为 ``True`` 则返回 ``False`` ,为 ``False`` 则返回 ``True``

.. topic:: a and b
  
  如果 a 为 ``True`` 则返回 b,否则返回 a

.. topic:: a or b
  
  如果 a 为 ``False`` 则返回 b,否则返回 a

::

  TODO:给一些有趣的 and or 实例。

另外,布尔对象在进行数值运算的时候还可以当整数来用:
::

  >>> True+1
  2
  >>> False+1
  1
  >>> int(True)
  1
  >>> int(False)
  0


整数
------

.. sidebar:: 长整数

  实际上在内部 python 对整数的处理还是会分为普通整数和长整数,
  普通整数就是大家在其他语言中常见到整数。
  而超过这个范围的整数就自动当作长整数处理,
  而长整数可表示的范围就没有限制了。
  如果你还想刨根问底,那就只好去看 CPython 的实现了 ;-)

.. sidebar:: 小整数池

  为了提高性能,python 在启动时会对一定范围以内的小整数创建缓存,
  这样在后面创建这些小整数对象的时候,就不用重复的去申请内存,
  而是直接使用缓存中的小整数对象。
  这一点通过 ``id()`` 函数就可以看得出来:
  ::

    >>> a = 10
    >>> b = 10
    >>> id(a)
    11163620
    >>> id(b)
    11163620

整数也是相当常见的数据类型了。
不过 python 的整数却和普通的整数不同,首先 python 整数没有什么 short、long 等等的区分,
这还不算什么,python 整数最奇妙的地方莫过于他甚至没有大小的限制:
::

  >>> 1
  1
  >>> 9999999999999999999999
  9999999999999999999999L

浮点数
--------

TODO

复数
-------

TODO

字符串
========

python 字符串既可以用单引号表示也可以用双引号表示,
甚至还可以用三引号——哦不对,是三个引号——来表示。

这样如果字符串里本身包含双引号,你就可以用单引号来表示:
::

  >>> 'My name is "python"'
  'My name is "python"'

而如果字符串里本身包含单引号呢,你又可以用双引号用表示:
::

  >>> "My name is 'python'"
  "My name is 'python'"

真是太方便了!

三个引号的字符串就更方便了,中间甚至还可以换行!
::

  >>> '''My
  ... name
  ... is
  ... "python"
  ... !
  ... '''
  'My\nname\nis\n"python"\n!\n'
  >>> """My
  ... name
  ... is
  ... 'python'
  ... !
  ... """
  "My\nname\nis\n'python'\n!\n"

.. sidebar:: 字符串缓存

  TODO: 解释 python 实现对字符串的缓存

字符串转义
------------

那字符串里要是既有单引号又有双引号怎么办?答案就是字符串转义:
::

  >>> 'My \'name\' is "python"!'
  'My \'name\' is "python"!'

所谓字符串转义就是 ... TODO: 字符串转义的含义、作用 等。

下面这个表列出所有转义符及其简要说明,要是觉得这点简要的解释不过瘾的话,
直接跑到 python shell 下面去试验一下,马上就清楚了:
::

  >>> print '\a'

  >>> print 'aa\bbb'
  abb
  >>> print 'a\tb\nab'
  a b
  ab
  >>> TODO: 更多有趣例子

+-------------+------------------------------------------------+
| 转义符 | 含义 |
+=============+================================================+
| ``\换行`` | 忽略后面的换行符 |
+-------------+------------------------------------------------+
| ``\\`` | 字符 ``\`` |
+-------------+------------------------------------------------+
| ``\'`` | 单引号 ``'`` |
+-------------+------------------------------------------------+
| ``\"`` | 双引号 ``"`` |
+-------------+------------------------------------------------+
| ``\a`` | 发出声音:滴 |
+-------------+------------------------------------------------+
| ``\b`` | 退格符 |
+-------------+------------------------------------------------+
| ``\f`` | |
+-------------+------------------------------------------------+
| ``\n`` | 换行符 |
+-------------+------------------------------------------------+
| ``\r`` | 回车符 |
+-------------+------------------------------------------------+
| ``\t`` | 水平 TAB 符 |
+-------------+------------------------------------------------+
| ``\v`` | 竖直 TAB 符 |
+-------------+------------------------------------------------+
| ``\ooo`` | 输出 8 进制数字(最多3个) ``oo`` 所代表的字符 |
+-------------+------------------------------------------------+
| ``\xhh`` | 输出 16 进制数字(最多2个) ``hh`` 所代表的字符|
+-------------+------------------------------------------------+
| ``\N{name}``| |
+-------------+------------------------------------------------+
| ``\uxxx`` | |
+-------------+------------------------------------------------+
| ``\Uxxx`` | |
+-------------+------------------------------------------------+

序列操作
--------------

序列类型(Sequence Types)其实是一个抽象接口,
内置类型中实现了这一接口的有字符串、Unicode 对象、元组、列表、
buffer、xrange。既然先讲到字符串,那就在这里就把这个概念说明一下先,
在后面向大家介绍其他序列类型时就直接参考这里了。

所有的序列类型都支持一些共同的操作,这里拿字符串来举例子,其他序列类型大家到时候一看就明白了。

.. topic:: ``in``

  ::
  
    >>> 'python' in 'I love python!'
    True
    >>> 'c' not in 'I love python!'
    False

.. topic:: 连接 ``+``

  将多个序列对象连接起来。
  ::

    >>> 'I '+'love '+'python!'
    'I love python!'

.. topic:: ``*``

  拷贝 n 份(准确得说是浅拷贝,见第n章第n节)
  ::

    >>> print 'I love python!\n'*3
    I love python!
    I love python!
    I love python!

.. topic:: 索引

  第一个是 ``0`` ,正数表示从左向右数第几个,负数是从右向左数,不过第一个的左边没有,就绕到最右边去了。
  ::

    >>> 'python'[0]
    'p'
    >>> 'python'[3]
    'h'
    >>> 'python'[-1]
    'n'
    >>> 'python'[-3]
    'h'

.. sidebar:: 惯用法
  
  ``sequence[:]`` ,也就是使用 ``start`` 、 ``end`` 和 ``step`` 的默认值对序列对象切片,
  实际上就是对序列对象的一个浅拷贝,而这显然比实际的拷贝操作方便多了。

.. topic:: 切片

  取序列中一个片段。

  原型是 ``sequence[start:end:step]``

  ``start`` 表示起始位置, ``end`` 表示结束位置, ``step``
  表示每经过多少取一个值。
  三个值均可忽略。 ``step`` 默认值为 ``1`` ,表示没有间隔;
  ``start`` 默认值为 ``0`` ,也就是序列最开始的位置,
  ``end`` 默认为 ``-1`` ,也就是序列最末尾的位置。
  ::

    >>> 'python'[0:6:2] # 完整版本
    'pto'
    >>> 'python'[0:6] # 忽略 step
    'python'
    >>> 'python'[:3] # 忽略 start 和 step
    'pyt'
    >>> 'python'[3:] # 忽略 end 和 step
    'hon'
    >>> 'python'[:] # 全部忽略
    'python'


常用字符串操作
----------------

上面这一节讲的其实已经是属于常用字符串操作了,不过那些是所有序列对象都共同拥有的东西,
而这一节要介绍的是专门为字符串提供的操作。
::

  >>> dir(str)
  ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
  ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__g
  t__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__
  ', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '
  __rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode',
  'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdi
  git', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lst
  rip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit'
  , 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', '
  translate', 'upper', 'zfill']

其实里面许多的方法,都是看到名字就能联想到其功能的。
稍微复杂点的方法,只要在 python shell 里面做点实验也都能猜个八九不离十。
如果还剩下些什么疑问呢,就到这里来找答案吧。

.. topic:: 连接与分割

  上面介绍序列类型时,我们已经使用了 ``+`` 号来做字符串的连接操作,
  在某些情况下这当然是不错的,然而在多数情况下我们其实都不推荐这种做法,
  因为大量的这种连接操作会大大影响效率。比如说这个例子:::

    >>> 'I '+'love '+'python!'
    'I love python!'

  分解开来看就是 ``('I '+'love ') + 'python!'``
  ,第一次连接操作就会产生一个中间对象 ``'I love '``
  ,而这个对象从结果来看完全是没有用的。
  大量的连接操作,就会产生大量无用的中间对象。
  浪费了分配内存所花费的时间也浪费了内存。

  所以对于两个以上的字符串的连接,我们推荐下面这个更好的做法:
  ::

    >>> ' '.join(['I', 'love', 'python!'])
    'I love python!'

  你看,代码还是这么漂亮 ;-)

  你还可以试试用其他字符串来连接:
  ::

    >>> '--'.join(['I', 'love', 'python!'])
    'I--love--python!'

  也许你已经注意到了里面的中括号,中括号是用来构造列表的(参考 列表_ )。

  ``split`` 是 ``join`` 的逆操作,原型是 ``split( [sep [,maxsplit]])`` ,
  可以用它来把字符串分割成列表:
  ::

    >>> 'I love python!'.split(' ')
    ['I', 'love', 'python!']
    >>> 'I--love--python!'.split('--')
    ['I', 'love', 'python!']

  如果你不传递或者传递 ``None`` 给 ``sep`` 参数,那么 ``split`` 会启用
  一个比较特殊的字符串分割策略,多说无益,先看代码:
  ::

    >>> 'I love python!'.split(' ') # 使用空格分割
    ['I', 'love', '', '', '', '', 'python!']
    >>> 'I love python!'.split() # 默认分割策略
    ['I', 'love', 'python!']

  看出区别了吧,它会把连续的空白当作分割符,其作用就不用我明说了吧 ;-)

  ``split`` 方法还接受另一个可选的参数: ``maxsplit`` ,意思就是最大分割次数,
  这样分割结果的长度最大就是 ``maxsplit + 1`` 。
  ::

    >>> 'I love python!'.split(' ', 1)
    ['I', 'love python!']

.. topic:: 大小写转换

  ``upper`` 将字符串转换为大写, ``lower`` 转换成小写。
  比较奇妙的是 ``title`` ,它将每个单词的首字母转成大写,其他转成小写。
  ::

    >>> 'Python'.upper()
    'PYTHON'
    >>> 'Python'.lower()
    'python'
    >>> 'python book'.title()
    'Python Book'

.. topic:: 字符串测试

  ::

    >>> 'python'.islower() # 是否都是小写
    True
    >>> 'PYTHON'.isupper() # 是否都是大写
    True
    >>> 'Python Book'.istitle() # 是否 ... (参考上面对 title 方法的解释)
    True
    >>> 'python'.isalpha() # 是否都是字母, isalnum 方法作用相同
    True
    >>> '42'.isdigit() # 是否都是数字
    True
    >>> ' '.isspace() # 是否都是空格
    True
    >>> ''.islower() or ''.isupper() or ''.istitle() or ''.isalpha() or ''.isdigit() or ''.isspace()
    False

  最后一句证明了这些测试对空字符串都不成立。

.. topic:: 查找

  ``find`` 方法返回字串在字符串中出现的位置,原型是 ``find( sub[, start[, end]])`` ,
  可选的 ``start`` 、 ``end`` 参数用来限制查找范围,如果找不到则返回 ``-1`` 。

  ``index`` 方法和 ``find`` 方法一样,唯一区别就是找不到的时候会抛出
  ``ValueError`` 异常(见某章某节 异常)而不是返回 ``-1`` 。

  ``find`` 和 ``index`` 方法都可以在前面加个 ``r`` ,也就是 ``rfind`` 和 ``rindex`` ,功能类似,
  只不过查找的方向变成从右向左。
  ::

    >>> 'I love python!'.find('love')
    2
    >>> 'I love python!'.find('c')
    -1
    >>> 'I love python!'.index('c')
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: substring not found
    >>> 'python is pythonic!'.find('python')
    0
    >>> 'python is pythonic!'.rfind('python')
    10

.. topic:: TODO 更多字符串操作

  TODO 更多字符串操作

Unicode 对象
---------------

字符串模板
--------------

容器类型
============

元组
----------

列表
----------

字典
----------

集合
----------

数组(array)
--------------

TODO: 是否该加上 array 类型?

练习
======

* 解释 ``condition and a or b`` 与 ``condition?a:b`` 的等价关系。
  
  * 还没学过 c 语言?OK,可以告诉你, ``condition?a:b`` 的意思就是:
    ::
    
      if condition:
          return a
      else:
          return b

运算符表:

+----------+---------------------------------------------------+
| 简单运算 | 加+、减-、乘*、除/、取模%、指数运算**、取相反数-。|
+----------+---------------------------------------------------+
| 位运算 | 按位取反~、按位与&、按位或|、按位异或^, |
+----------+---------------------------------------------------+
| 移位运算 | 左移<<、右移>>。 |
+----------+---------------------------------------------------+
| 比较操作 | <、>、==、>=、<=、<>、!=。 |
+----------+---------------------------------------------------+
| 布尔操作 | not、and、or |
+----------+---------------------------------------------------+

.. macro:: [[PageComment2(nosmiley=1, notify=1)]]
Rendering of reStructured text is not possible, please install Docutils.

:status: 草稿 ;HuangYi; 20%;

===================
Python内置数据类型
===================

.. contents::

数值类型
==========

布尔
-------

在所有的语言中,布尔类型可能都是数据类型中最简单的了, ``True`` 或者 ``False`` ,干脆俐落。

在 python 中,任何对象都可以隐式地转换为布尔对象,
转换的规则如下: ``None`` 、任何数值类型中的 ``0`` 、空字符串 ``''`` 、空元组 ``()`` 、空列表 ``[]`` 、空字典 ``{}``
都被当作 ``False`` ,还有自定义的类型如果它实现了 ``__nonzero__()`` 或 ``__len__()`` 
方法且方法返回 ``0`` 或 ``False`` 的,则其实例也被当作 ``False`` ,其他对象均为 ``True`` 。
::

  >>> 0 or 0L or 0.0 or 0j or '' or () or [] or {} or False
  False

上面这个代码就可以证明那些对象都被当作 ``False`` ,至于为什么就留给聪明的你自己思考吧 ;-)

你还可以使用任何对象来构造 ``bool`` 对象:
::

  >>> bool(0)
  False
  >>> bool(1)
  True
  >>> bool('hello')
  True
  >>> class FooBar(object):
  ...     def __nonzero__(self):
  ...         return False
  ...
  >>> foobar = FooBar() # 创建 FooBar 类的实例,见 ...
  >>> bool(foobar)
  False

python 中还有三个布尔操作符:not、and 和 or,
不过他们虽然叫做布尔操作符,但由于我们上面说过的任何对象都可以隐式转换为布尔对象,
实际上这三个操作符可以操作任何对象,而且返回的也不仅仅是布尔对象。
具体规则如下:

.. sidebar:: and or 组合

  通过 and 和 or 的组合你可以获得许多奇妙的效果,
  比如 ``condition and a or b`` 实际上就等价于 c 语言中的 ``condition? a:b`` ,
  意思就是说如果条件 ``condition`` 满足那么就 ``a`` ,否则就 ``b`` 。
  有意思吧 ;-)  至于为什么就当做作业留给聪明的你慢慢思考吧(见练习题1)。

.. topic:: not a

  如果 ``a`` 为 ``True`` 则返回 ``False`` ,为 ``False`` 则返回 ``True``

.. topic:: a and b
  
  如果 a 为 ``True`` 则返回 b,否则返回 a

.. topic:: a or b
  
  如果 a 为 ``False`` 则返回 b,否则返回 a

::

  TODO:给一些有趣的 and or 实例。

另外,布尔对象在进行数值运算的时候还可以当整数来用:
::

  >>> True+1
  2
  >>> False+1
  1
  >>> int(True)
  1
  >>> int(False)
  0


整数
------

.. sidebar:: 长整数

  实际上在内部 python 对整数的处理还是会分为普通整数和长整数,
  普通整数就是大家在其他语言中常见到整数。
  而超过这个范围的整数就自动当作长整数处理,
  而长整数可表示的范围就没有限制了。
  如果你还想刨根问底,那就只好去看 CPython 的实现了 ;-)

.. sidebar:: 小整数池

  为了提高性能,python 在启动时会对一定范围以内的小整数创建缓存,
  这样在后面创建这些小整数对象的时候,就不用重复的去申请内存,
  而是直接使用缓存中的小整数对象。
  这一点通过 ``id()`` 函数就可以看得出来:
  ::

    >>> a = 10
    >>> b = 10
    >>> id(a)
    11163620
    >>> id(b)
    11163620

整数也是相当常见的数据类型了。
不过 python 的整数却和普通的整数不同,首先 python 整数没有什么 short、long 等等的区分,
这还不算什么,python 整数最奇妙的地方莫过于他甚至没有大小的限制:
::

  >>> 1
  1
  >>> 9999999999999999999999
  9999999999999999999999L

浮点数
--------

TODO

复数
-------

TODO

字符串
========

python 字符串既可以用单引号表示也可以用双引号表示,
甚至还可以用三引号——哦不对,是三个引号——来表示。

这样如果字符串里本身包含双引号,你就可以用单引号来表示:
::

  >>> 'My name is "python"'
  'My name is "python"'

而如果字符串里本身包含单引号呢,你又可以用双引号用表示:
::

  >>> "My name is 'python'"
  "My name is 'python'"

真是太方便了!

三个引号的字符串就更方便了,中间甚至还可以换行!
::

  >>> '''My
  ... name
  ... is
  ... "python"
  ... !
  ... '''
  'My\nname\nis\n"python"\n!\n'
  >>> """My
  ... name
  ... is
  ... 'python'
  ... !
  ... """
  "My\nname\nis\n'python'\n!\n"

.. sidebar:: 字符串缓存

  TODO: 解释 python 实现对字符串的缓存

字符串转义
------------

那字符串里要是既有单引号又有双引号怎么办?答案就是字符串转义:
::

  >>> 'My \'name\' is "python"!'
  'My \'name\' is "python"!'

所谓字符串转义就是 ... TODO: 字符串转义的含义、作用 等。

下面这个表列出所有转义符及其简要说明,要是觉得这点简要的解释不过瘾的话,
直接跑到 python shell 下面去试验一下,马上就清楚了:
::

  >>> print '\a'

  >>> print 'aa\bbb'
  abb
  >>> print 'a\tb\nab'
  a       b
  ab
  >>> TODO: 更多有趣例子

+-------------+------------------------------------------------+
| 转义符      | 含义                                           |
+=============+================================================+
| ``\换行``   | 忽略后面的换行符                               |
+-------------+------------------------------------------------+
| ``\\``      | 字符 ``\``                                     |
+-------------+------------------------------------------------+
| ``\'``      | 单引号 ``'``                                   |
+-------------+------------------------------------------------+
| ``\"``      | 双引号 ``"``                                   |
+-------------+------------------------------------------------+
| ``\a``      | 发出声音:滴                                   |
+-------------+------------------------------------------------+
| ``\b``      | 退格符                                         |
+-------------+------------------------------------------------+
| ``\f``      |                                                |
+-------------+------------------------------------------------+
| ``\n``      | 换行符                                         |
+-------------+------------------------------------------------+
| ``\r``      | 回车符                                         |
+-------------+------------------------------------------------+
| ``\t``      | 水平 TAB 符                                    |
+-------------+------------------------------------------------+
| ``\v``      | 竖直 TAB 符                                    |
+-------------+------------------------------------------------+
| ``\ooo``    | 输出 8 进制数字(最多3个) ``oo`` 所代表的字符 |
+-------------+------------------------------------------------+
| ``\xhh``    | 输出 16 进制数字(最多2个) ``hh`` 所代表的字符|
+-------------+------------------------------------------------+
| ``\N{name}``|                                                |
+-------------+------------------------------------------------+
| ``\uxxx``   |                                                |
+-------------+------------------------------------------------+
| ``\Uxxx``   |                                                |
+-------------+------------------------------------------------+

序列操作
--------------

序列类型(Sequence Types)其实是一个抽象接口,
内置类型中实现了这一接口的有字符串、Unicode 对象、元组、列表、
buffer、xrange。既然先讲到字符串,那就在这里就把这个概念说明一下先,
在后面向大家介绍其他序列类型时就直接参考这里了。

所有的序列类型都支持一些共同的操作,这里拿字符串来举例子,其他序列类型大家到时候一看就明白了。

.. topic:: ``in``

  ::
  
    >>> 'python' in 'I love python!'
    True
    >>> 'c' not in 'I love python!'
    False

.. topic:: 连接 ``+``

  将多个序列对象连接起来。
  ::

    >>> 'I '+'love '+'python!'
    'I love python!'

.. topic:: ``*``

  拷贝 n 份(准确得说是浅拷贝,见第n章第n节)
  ::

    >>> print 'I love python!\n'*3
    I love python!
    I love python!
    I love python!

.. topic:: 索引

  第一个是 ``0`` ,正数表示从左向右数第几个,负数是从右向左数,不过第一个的左边没有,就绕到最右边去了。
  ::

    >>> 'python'[0]
    'p'
    >>> 'python'[3]
    'h'
    >>> 'python'[-1]
    'n'
    >>> 'python'[-3]
    'h'

.. sidebar:: 惯用法
  
  ``sequence[:]`` ,也就是使用 ``start`` 、 ``end`` 和 ``step`` 的默认值对序列对象切片,
  实际上就是对序列对象的一个浅拷贝,而这显然比实际的拷贝操作方便多了。

.. topic:: 切片

  取序列中一个片段。

  原型是 ``sequence[start:end:step]``

  ``start`` 表示起始位置, ``end`` 表示结束位置, ``step``
  表示每经过多少取一个值。 
  三个值均可忽略。 ``step`` 默认值为 ``1`` ,表示没有间隔; 
  ``start`` 默认值为 ``0`` ,也就是序列最开始的位置,
  ``end`` 默认为 ``-1`` ,也就是序列最末尾的位置。
  ::

    >>> 'python'[0:6:2] # 完整版本
    'pto'
    >>> 'python'[0:6]   # 忽略 step
    'python'
    >>> 'python'[:3]    # 忽略 start 和 step
    'pyt'
    >>> 'python'[3:]    # 忽略 end 和 step
    'hon'
    >>> 'python'[:]     # 全部忽略
    'python'


常用字符串操作
----------------

上面这一节讲的其实已经是属于常用字符串操作了,不过那些是所有序列对象都共同拥有的东西,
而这一节要介绍的是专门为字符串提供的操作。
::

  >>> dir(str)
  ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
  ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__g
  t__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__
  ', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '
  __rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode',
  'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdi
  git', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lst
  rip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit'
  , 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', '
  translate', 'upper', 'zfill']

其实里面许多的方法,都是看到名字就能联想到其功能的。
稍微复杂点的方法,只要在 python shell 里面做点实验也都能猜个八九不离十。
如果还剩下些什么疑问呢,就到这里来找答案吧。

.. topic:: 连接与分割

  上面介绍序列类型时,我们已经使用了 ``+`` 号来做字符串的连接操作,
  在某些情况下这当然是不错的,然而在多数情况下我们其实都不推荐这种做法,
  因为大量的这种连接操作会大大影响效率。比如说这个例子:::

    >>> 'I '+'love '+'python!'
    'I love python!' 

  分解开来看就是 ``('I '+'love ') + 'python!'``
  ,第一次连接操作就会产生一个中间对象 ``'I love '``
  ,而这个对象从结果来看完全是没有用的。
  大量的连接操作,就会产生大量无用的中间对象。
  浪费了分配内存所花费的时间也浪费了内存。

  所以对于两个以上的字符串的连接,我们推荐下面这个更好的做法:
  ::

    >>> ' '.join(['I', 'love', 'python!'])
    'I love python!'

  你看,代码还是这么漂亮 ;-)

  你还可以试试用其他字符串来连接:
  ::

    >>> '--'.join(['I', 'love', 'python!'])
    'I--love--python!'

  也许你已经注意到了里面的中括号,中括号是用来构造列表的(参考 列表_ )。

  ``split`` 是 ``join`` 的逆操作,原型是 ``split( [sep [,maxsplit]])`` ,
  可以用它来把字符串分割成列表:
  ::

    >>> 'I love python!'.split(' ')
    ['I', 'love', 'python!']
    >>> 'I--love--python!'.split('--')
    ['I', 'love', 'python!']

  如果你不传递或者传递 ``None`` 给 ``sep`` 参数,那么 ``split`` 会启用
  一个比较特殊的字符串分割策略,多说无益,先看代码:
  ::

    >>> 'I love     python!'.split(' ') # 使用空格分割
    ['I', 'love', '', '', '', '', 'python!']
    >>> 'I love     python!'.split()    # 默认分割策略
    ['I', 'love', 'python!']

  看出区别了吧,它会把连续的空白当作分割符,其作用就不用我明说了吧 ;-)

  ``split`` 方法还接受另一个可选的参数: ``maxsplit`` ,意思就是最大分割次数,
  这样分割结果的长度最大就是 ``maxsplit + 1`` 。
  ::

    >>> 'I love python!'.split(' ', 1)
    ['I', 'love python!']

.. topic:: 大小写转换

  ``upper`` 将字符串转换为大写, ``lower`` 转换成小写。
  比较奇妙的是 ``title`` ,它将每个单词的首字母转成大写,其他转成小写。
  ::

    >>> 'Python'.upper()
    'PYTHON'
    >>> 'Python'.lower()
    'python'
    >>> 'python book'.title()
    'Python Book'

.. topic:: 字符串测试

  ::

    >>> 'python'.islower()      # 是否都是小写
    True
    >>> 'PYTHON'.isupper()      # 是否都是大写
    True
    >>> 'Python Book'.istitle() # 是否 ... (参考上面对 title 方法的解释)
    True
    >>> 'python'.isalpha()      # 是否都是字母, isalnum 方法作用相同
    True
    >>> '42'.isdigit()          # 是否都是数字
    True
    >>> '  '.isspace()          # 是否都是空格
    True
    >>> ''.islower() or ''.isupper() or ''.istitle() or ''.isalpha() or ''.isdigit() or ''.isspace()
    False 

  最后一句证明了这些测试对空字符串都不成立。

.. topic:: 查找

  ``find`` 方法返回字串在字符串中出现的位置,原型是 ``find( sub[, start[, end]])`` ,
  可选的 ``start`` 、 ``end`` 参数用来限制查找范围,如果找不到则返回 ``-1`` 。

  ``index`` 方法和 ``find`` 方法一样,唯一区别就是找不到的时候会抛出
  ``ValueError`` 异常(见某章某节 异常)而不是返回 ``-1`` 。

  ``find`` 和 ``index`` 方法都可以在前面加个 ``r`` ,也就是 ``rfind`` 和 ``rindex`` ,功能类似,
  只不过查找的方向变成从右向左。
  ::

    >>> 'I love python!'.find('love')
    2
    >>> 'I love python!'.find('c')
    -1
    >>> 'I love python!'.index('c')
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: substring not found
    >>> 'python is pythonic!'.find('python')
    0
    >>> 'python is pythonic!'.rfind('python')
    10

.. topic:: TODO 更多字符串操作

  TODO 更多字符串操作

Unicode 对象
---------------

字符串模板
--------------

容器类型
============

元组
----------

列表
----------

字典
----------

集合
----------

数组(array)
--------------

TODO: 是否该加上 array 类型?

练习
======

* 解释 ``condition and a or b`` 与 ``condition?a:b`` 的等价关系。
  
  * 还没学过 c 语言?OK,可以告诉你, ``condition?a:b`` 的意思就是:
    ::
    
      if condition:
          return a
      else:
          return b

运算符表:

+----------+---------------------------------------------------+
| 简单运算 | 加+、减-、乘*、除/、取模%、指数运算**、取相反数-。|
+----------+---------------------------------------------------+
| 位运算   | 按位取反~、按位与&、按位或|、按位异或^,          |
+----------+---------------------------------------------------+
| 移位运算 | 左移<<、右移>>。                                  |
+----------+---------------------------------------------------+
| 比较操作 | <、>、==、>=、<=、<>、!=。                        |
+----------+---------------------------------------------------+
| 布尔操作 | not、and、or                                      |
+----------+---------------------------------------------------+

.. macro:: [[PageComment2(nosmiley=1, notify=1)]]

ObpLovelyPython/LpyQLearn-2-data (last edited 2009-12-25 07:16:59 by localhost)