zoukankan      html  css  js  c++  java
  • 《python tutorial》python 学习第二天

    本部分主要包括数据结构, 模块,输入输出

    数据结构包括列表(用[]表示),元组(用()表示),字典(用{}表示),集合sets(用sets([])表示)四种。


    一  数据结构

    1 深入列表(list)

    (1)列表的所有函数:

    list.insert(i, x)   插入-----指定位置

    list.append(x)   插入——把一个元素添加到链表的结尾,相当于 a[len(a):] = [x] 。
    list.extend(L)    插入——将一个给定列表中的所有元素都添加到另一个列表中,相当于 a[len(a):] = L 。
    list.remove(x)   删除——删除链表中值为 x 的第一个元素。
    list.pop([i ])       删除——从链表的指定位置删除元素,并将其返回。

    list.index(x)       查询索引-回链表中第一个值为 x 的元素的索引。
    list.count(x)       查询次数——返回 x 在链表中出现的次数。
    list.sort()           排序——对链表中的元素就地排序

    list.reverse()     倒序——就地倒排链表中的元素。

    del                   删除——del 还可以从列表中删除切片或清空整个列表
                         >>> a = [1, 66.25, 333, 333, 1234.5]
                         >>> del a[2:4]
                         >>> a
                         [1, 66.25, 1234.5]
                         >>> del a[:]
                         >>> a
                         []
                         del 也可以删除整个变量,此后再引用命名 a 会引发错误
                         >>> del a

    (2)列表作为堆栈

    用 append() 方法可以把一 个元素添加到堆栈顶。用不指定索引的 pop() 方法
    可以把一个元素从堆栈顶释放 出来。
    (3)列表当作队列
    列表作为队列,效率不高。相对来说从列表末尾添加和弹 出很快;在头部插入和弹出很慢(因为,为了一个元素,要移动整个列表中的所 有元素)。要实现队列,使用 collections.deque ,它为在首尾两端快速插入和 删除而设计。例如
    使用append和popleft
    >>> from collections import deque
    >>> queue = deque(["Eric", "John", "Michael"])
    >>> queue.append("Terry")
    # Terry arrives
    >>> queue.append("Graham")
    # Graham arrives
    >>> queue.popleft()
    # The first to arrive now leaves
    'Eric'
    >>> queue.popleft()
    # The second to arrive now leaves
    'John'
    >>> queue
    # Remaining queue in order of arrival
    deque(['Michael', 'Terry', 'Graham'])

    (4)函数式方法
    对于链表来讲,有三个内置函数非常有用: filter() , map ,reduce。

    filter(function, sequence) 返回一个sequence(序列),包括了给定序 列中所有调用 function(item)后返回值为true的元素。
    >>> def f(x): return x % 2 != 0 and x % 3 != 0
    ...
    >>> filter(f, range(2, 25))
    [5, 7, 11, 13, 17, 19, 23]


    map(function, sequence) 为每一个元素依次调用 function(item) 并将返回值 组成一个链表返回。例
    如,以下程序计算立方
    >>> def cube(x): return x*x*x
    ...
    >>> map(cube, range(1, 11))
    [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

    可以传入多个序列,
    >>> seq = range(8)
    >>> def add(x, y): return x+y
    >>> map(add, seq, seq)
    [0, 2, 4, 6, 8, 10, 12, 14]

    reduce(func, sequence)——类似haskell中的foldl 返回一个单值,它是这样构造的:首先以序列的 前两个元素调用函数 function
    ,再以返回值和第三个参数调用,依次执行下去。例如,以 下程序计算 1 到 10 的整数之和
    >>> def add(x,y): return x+y
    >>> reduce(add, range(1, 11))
    55
    可以传入第三个参数做为初始值。如果序列是空的,就返回初始值,否则函数会 先接收初始值和序列的第
    一个元素,然后是返回值和下一个元素,依此类推。例 如
    >>> def sum(seq):
    def add(x,y): return x+y
    return reduce(add, seq, 0)
    >>> sum(range(1, 11))
    55

    (5)列表推导式--作用等价于map,filter,lambda,比他们更强大

    每一个列表推导式包括 在一个 for 语句之后的表达式,零或多个 for 或 if 语句。返回值是由 for 或 if 子句之后的表达式得到的元素组成的列表。如果想要得到一个元组,必须要加 上括号。
    >>> vec1 = [2, 4, 6]
    >>> vec2 = [4, 3, -9]
    >>> [x*y for x in vec1 for y in vec2]
    [8, 6, -18, 16, 12, -36, 24, 18, -54]
    >>> [x+y for x in vec1 for y in vec2]
    [6, 5, -7, 8, 7, -5, 10, 9, -3]
    >>> [vec1[i]*vec2[i] for i in range(len(vec1))]
    [8, 12, -54]

    列表推导式比 map() 更复杂,可使用复杂的表达式和嵌套函数
    >>> [str(round(355/113.0, i)) for i in range(1,6)]
    ['3.1', '3.14', '3.142', '3.1416', '3.14159']

    (6)嵌套的列表推导

    >>> mat = [
    ...
    [1, 2, 3],
    ...
    [4, 5, 6],
    ...
    [7, 8, 9],
    ...
    ]

    如果你想交换行和列,可以用列表推导式
    >>> print [[row[i] for row in mat] for i in [0, 1, 2]]
    [[1, 4, 7], [2, 5, 8], [3, 6, 9]]


    为了不被嵌套的列表推导式搞晕,从右往左读。
    接下来有一个更容易读的版本
    for i in [0, 1, 2]:
    for row in mat:
    print row[i],
    print

    实用中,你可以利用内置函数完成复杂的流程语句。函数 zip() 在这个 例子中可以搞定大量的工作。zip取每个列表的对应元素放在一起。
    >>> zip(*mat)
    [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

    2 元组和序列

    元组和列表都属于序列类型。含有索引和切片等操作。

    >>> t = 12345, 54321, 'hello!'
    >>> t[0]
    12345
    >>> t
    (12345, 54321, 'hello!')
    >>> # Tuples may be nested:
    ... u = t, (1, 2, 3, 4, 5)
    >>> u
    ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

    语句 t = 12345, 54321, 'hello!' 是 元组封装 (tuple packing)的 一个例子:值 12345 , 54321
    和 'hello!' 被封装进元组。其逆 操作可能是这样>>> x, y, z = t

    这个调用等号右边可以是任何线性序列,称之为 序列拆封 非常恰当。序列拆 封要求左侧的变量数目与序列的元素个数相同。

    3  sets集合

    集合是一个无序不重复元素的 集。基本功能包括关系测试和消除重复元素。集合对象还支持 union(联 合),intersection(交),difference(差)和sysmmetric difference(对 称差集)等数学运算。
    >>> a = set('abracadabra')
    >>> b = set('alacazam')
    >>> a
    # unique letters in a
    set(['a', 'r', 'b', 'c', 'd'])
    >>> a - b
    # letters in a but not in b
    set(['r', 'd', 'b'])
    >>> a | b
    # letters in either a or b
    set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
    >>> a & b
    # letters in both a and b
    set(['a', 'c'])
    >>> a ^ b
    # letters in a or b but not both
    set(['r', 'd', 'b', 'm', 'z', 'l'])

    4 字典--键值对集合

    序列是以连续的整数为索引,与此不同的是,字 典以 关键字 为索引,关键字可以是任意不可变类型,通常用字符串或数值。

    一对大括号创建一个空的 字典: {} 。初始化链表时,在大括号内放置一组逗号分隔的键:值对,这也 是字典输出的方式。
    字典的 keys() 方法返回由所有关键字组成的链表,该链表的顺序不定(如果你 需要它有序,只能调用关键字链表的 sort() 方法)。
    >>> tel = {'jack': 4098, 'sape': 4139}
    >>> tel['guido'] = 4127
    >>> tel
    {'sape': 4139, 'guido': 4127, 'jack': 4098}

    链表中存储关键字-值对元组的话,:func:dict 可以从中直接构造字典。
    >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
    {'sape': 4139, 'jack': 4098, 'guido': 4127}
    >>> dict([(x, x**2) for x in (2, 4, 6)])
    # use a list comprehension
    {2: 4, 4: 16, 6: 36}
    >>> dict(sape=4139, guido=4127, jack=4098)
    {'sape': 4139, 'jack': 4098, 'guido': 4127}

    5 循环技巧

    在字典中循环时,关键字和对应的值可以使用 iteritems() 方法同时解读出来

    >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
    >>> for k, v in knights.iteritems():
    print k, v

    在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得 到。
    >>> for i, v in enumerate(['tic', 'tac', 'toe']):
    print i, v
    0 tic
    1 tac
    2 toe

    同时循环两个或更多的序列,可以使用 zip() 整体打包。
    >>> questions = ['name', 'quest', 'favorite color']
    >>> answers = ['lancelot', 'the holy grail', 'blue']
    >>> for q, a in zip(questions, answers):
    print 'What is your {0}? It is {1}.'.format(q, a)
    .
    What is your name? It is lancelot.
    What is your quest? It is the holy grail.
    What is your favorite color? It is blue.

    需要逆向循环序列的话,先正向定位序列,然后调用 reversed() 函数
    >>> for i in reversed(xrange(1,10,2)):
    print i
    9
    7
    5
    3
    1

    二 模块-封装变量和函数

    模块是包括 Python 定义和声明的文件。文件名就是模块名加上 .py 后缀。

    当前目录下创建一个叫fibo.py 的文件,

    # Fibonacci numbers module
    def fib(n):
    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
    print b,
    a, b = b, a+b
    def fib2(n): # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while b < n:
    result.append(b)
    55
    Python Tutorial, Release 2.7
    a, b = b, a+b
    return result


    1  导入模块

    >>> import fibo(模块名字--文件名字去掉py)

    这样做不会直接把 fibo 中的函数导入当前的语义表;它只是引入了模块名 fibo 。你可以通过模块名按
    如下方式访问这个函数
    >>> fibo.fib(1000)
    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
    >>> fibo.fib2(100)
    [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    >>> fibo.__name__
    'fibo'


    推荐导入方法如下:

    2 import 语句的一个变体直接从被导入的模块中导入名字到本模块的语义表中。 例如
    >>> from fibo import fib, fib2
    >>> fib(500)
    1 1 2 3 5 8 13 21 34 55 89 144 233 377


    甚至有种方式可以导入模块中的所有定义--不推荐,因 为这样会让代码变得很难读。

    >>> from fibo import *
    >>> fib(500)
    1 1 2 3 5 8 13 21 34 55 89 144 233 377


    2 执行模块

    python fibo.py <arguments>
    模块中的代码会被执行,就像导入它一样,不过此时"__name__"
    被设置为" __main__ " 这相当于,如果你在模块后加入如下代码

    if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

    就可以让此文件像作为模块导入时一样作为脚本执行。此代码只有在模块作为 “main” 文件执行时才被调

    $ python fibo.py 50
    1 1 2 3 5 8 13 21 34


    3模块搜索路径

    变量 sys.path 是解释器模块搜索路径的字符串列表。

    它由环境变 量:envvar:PYTHONPATH 初始化,如果没有设定 PYTHONPATH ,就由 内置的默认值初始化。

    你可以用标准的字符串操作修改它
    >>> import sys
    >>> sys.path.append('/ufs/guido/lib/python')

     

    入一 个 叫 spam 的 模 块 时, 解 释 器 先 在 当 前 目 录 中 搜 索 名 为 spam.py 的 文 件, 然 后 在 环 境 变 量
    PYTHONPATH 表示的目录 列表中搜索,然后是环境变量 PATH 中的路径列表。如果 PYTHONPATH 没有
    设置,或者文件没有找到,接下来搜索安装目录, 在 Unix 中,通常是 .:/usr/local/lib/python 。
    实际上,解释器由 sys.path 变量指定的路径目录搜索模块,该变量初始化 时默认包含了输入脚本(或者
    当前目录), PYTHONPATH 和安装目录。


    4 pyc,pyo

    对于引用了大量标准模块的短程序,有一个提高启动速度的重要方法,如果在 spam.py 所在的目录下存在一个名为 spam.pyc 的文件,它会 被视为 spam 模块的预“编译”(``byte-compiled'' ,二进制编译) 版本。


    以 -O 参数调用Python解释器时,会生成优化代码并保存在 .pyo 文件中。
    compileall 模块 可以为指定目录中的所有模块创建 .pyc 文 件(或者使用 .pyo 参数创建 .pyo
    文件)。

    5标准模块

    变量 sys.path 是解释器模块搜索路径的字符串列表。它由环境变 量:envvar:PYTHONPATH 初始化,如果
    没有设定 PYTHONPATH ,就由 内置的默认值初始化。你可以用标准的字符串操作修改它
    >>> import sys
    >>> sys.path.append('/ufs/guido/lib/python')

    内置函数 dir() 用于按模块名搜索模块定义,它返回一个字符串类型的存储列 表
    >>> import fibo, sys
    >>> dir(fibo)
    ['__name__', 'fib', 'fib2']


    6包

    包是一个模块集。一个可能的结构如下
    sound/
         __init__ .py
          formats/
               __init__ .py
                auread.py
                auwrite.py
                 ...
           effects/
                 __init__ .py
                echo.py
                 surround.py
                 reverse.py
                  ...
           filters/
                __init__ .py
                equalizer.py
                 vocoder.py
                 karaoke.py
    必须要有一个 __init__ .py 文件的存在,才能使 Python 把该目录当作 一个包;

    包用户可以从包中导入合法的模块,例如
    import sound.effects.echo
    from sound.effects import echo ————推荐写法

    需要注意的是使用 from package import item 方式导入包时,这个子项(item)既可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数、类或变量。

    Importing * From a Package 可能浪费时间并且出现边际效应,而且可能只导入__init__.py的内容。

    解决方法是:如果包中的 init .py 代码定义了一个名为 all 的列表,就
    会按照列表中给出的模块名进行导入。例如_all__ = ["echo", "surround", "reverse"]

    目录

    from . import echo
    from .. import formats
    from ..filters import equalizer

    包支持一个更为特殊的特性, path 。 在包的 init .py 文件代码执行之前,该变量初始化一个目录
    名列表。该变量可以修改,它作用于 包中的子包和模块的搜索功能


    三 输入输出

    1format

    第一种是由你来控制整个字符串,使用字符切割和联 接操作就可以创建出任何你想要的输出形式。第二种方法是使用 str.format() 方法。

    (1)基本用
    >>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
    We are the knights who say "Ni!"
    大括号和其中的字符会被替换成传入 format() 的参数。大括号中 的数值指明使用传入 format() 方法的对象中的哪一个
    >>> print '{0} and {1}'.format('spam', 'eggs')
    spam and eggs
    >>> print '{1} and {0}'.format('spam', 'eggs')
    eggs and spam

    (2)值转化为字符串?

    很幸运,Python 有办法将任意 值转为字符串:将它传入repr() 或 str() 函数。
    >>> str(1.0/7.0)
    '0.142857142857'
    >>> # The argument to repr() may be any Python object:
    ... repr((x, y, ('spam', 'eggs')))
    "(32.5, 40000, ('spam', 'eggs'))"

    2format
    >>> for x in range(1,11):
    ...
    print '{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)
    ...
    1   1    1
    2   4    8
    3   9   27
    4  16  64
    5 25 125
    6 36 216
    7 49 343


    (3)关键字参数

    如果在 format() 调用时使用关键字参数,可以通过参数名来引用 值
    >>> print 'This {food} is {adjective}.'.format(food='spam', adjective='absolutely horrible')
    This spam is absolutely horrible.

    可以用 ‘**’ 标志将这个字典以关键字参数的方式传入。
    >>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
    >>> print 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)
    Jack: 4098; Sjoerd: 4127; Dcab: 8637678

    (4)对其格式

    rjust() 方法把字符串输出到一列,并通过向左 侧填充空格来使其右对齐。类似的方法还有 ljust() 和 center()。

    zfill() 它用于向数值的字符串表达左侧填充 0
    >>> for x in range(1, 11):
    ...
    print repr(x).rjust(2), repr(x*x).rjust(3),
    ...
    # Note trailing comma on previous line
    ...
    print repr(x*x*x).rjust(4)
    ...
    1   1   1
    2    4   8
    3    9   27

    >>> '12'.zfill(5)
    '00012'
    >>> '-3.14'.zfill(7)
    '-003.14'
    >>> '3.14159265359'.zfill(5)
    '3.14159265359'

    2读写文件

    fopen

    >>> f = open('/tmp/workfile', 'w')
    >>> print f


    f.read(size) ,

    该方法读取若干数量的数据并以字符串形式返回其内容,size 是可选的数值,指定字符串长度。
    f.readlines()

    从文件中读取单独一行,
    有个按行读取的好办法是在文件对象上循环。这样容易记忆,高速而且代码更简单
    >>> for line in f:
    print line,


    f.write(string)

    将 string 的内容写入文件,返回 None 。
    >>> f.write('This is a test\n')


    f.tell()

    返回一个整数,代表文件对象在文件中的指针位置,自文 件开头到指针处的比特数。


    f.seek(offset,from what) 。

    指针在该操作中从指定的引用位置 移动 offset 比特,引用位置由 from what 参数指定。
     from what 值为 0 表示自文件 起始处开始,1 表示自当前文件指针位置开始,2 表示自文件末尾开始。


    f.close()

    用关键字 with 处理文件对象是个好习惯。它的先进之处在于文件 用完后会自动关闭,就算发生异常也没
    关系。它是 try-finally 块的简写。
    >>> with open('/tmp/workfile', 'r') as f:
    ...
    read_data = f.read()
    >>> f.closed
    True


    3 pickle 模块---将对象封装为字符串

    我们可以很容易的读写文件中的字符串。数值就要多费点儿周折,因为 read() 方法只会返回字符串,应该将其传入 int() 这样的方法中,就可以将 '123' 这样的字符转为对应的数值 123 。不过,当你需要保存更为复杂的 数据类型,例如列表、字典,类的实例,事情就会变得更复杂了。

    Python提供了 一个名为 pickle 的标准模块。几乎可以把任何 Python 对象 (甚至是一些 Python 代码段!)表达为为字符串,这一过程称之 为封装 ( pickling )。从字符串表达出重新构造对象称之为拆封 ( unpickling)。封装状态中的对象可以存储在文件或对象中,也可以通过网 络在远程的机器之间传输。

    如果你有一个对象 x ,一个以写模式打开的文件对象 f ,封装对象的最简单的 方法只需要一行代码
    pickle.dump(x, f)
    如果 f 是一个以读模式打开的文件对象,就可以重装拆封这个对象
    x = pickle.load(f)




     

  • 相关阅读:
    Java实现 LeetCode 27 移除元素
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
  • 原文地址:https://www.cnblogs.com/catkins/p/5270673.html
Copyright © 2011-2022 走看看