首页 > 代码库 > python学习笔记

python学习笔记

笔记概述

这个笔记是我为了把学过的python知识记录下来,以便以后查看。由于现在对python的理解还不够深入,我只会记录一些python中有些难理解的部分,而不会去做总结性的概括和归纳。随着python的不断学习,会持续更新这个笔记。

 

动态类型

python是一种动态类型(dynamic typing)的语言, python中的变量不需要提前申明类型,变量的类型由python自己决定。

例如:

a = 3

这句在python中应该理解为先生成“3”这个整型的对象,然后在用a指向这个对象。再次赋值:

a = 5

此时a又指向了“5”这个对象。此时对象“3”不再有引用指向它了,python会自动将没有引用指向的对象销毁(destrcut), 释放其内存。

上面的“3”和“5”都是int型的,和float,tuple,string这些都属于不可变数据对象(immutable object)。所以即使执行下面的语句:

a = 3
b = a
b = 5

虽然b指向了a所指向的对象“3”,但是由于“3”是不可变的数据对象,当对b再次赋值的时候不会改变“3”本身,而是重新生成“5”这个对像,并将b重新指向“5”。python中的变量就像一个标签(tag)贴在它所代表的对象上,当然这个标签也可以撕下来重新贴在另一个对象上。

既然有不可变的数据对象,那么也肯定有可变数据对象(mutable object)。python的字典(dictionary)类型,就要求其中的key不可以是可变数据类型的,也就是说key不可以是列表(list), 字典(dict)等可变的数据类型。

对于可变数据类型比如列表(list), 当变量指向它的时候,情况会有些不同。考虑下面的代码:

a = [1, 2, 3]
b = a
b[2] = 3

第一行说明a绑定了一个list对象(想象tag a贴在list [1, 2, 3]上), 下面一行是将b指向a指向的列表对象即 [1, 2, 3], 到这一句都和前面的整型对象一样,但最后一句就不一样了,不是将b重新贴在"3"这个整形对象上,而是改变了list中的值,a同时也会发生改变。其实从b[2]就可以看出,因为带了个"2", b不能再次贴在其它变量上了。

循环对象

关于循环对象难免要涉及以下一些概念:生成器(generator), 迭代器(iterator), list conprehension(表理解,没法翻译)

生成器(generator)

说生成器先从range这个最常用的内置函数说起,在python2.x版本中有:

>>> range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

range函数直接返回的是一个列表,range通常用于循环中,这样对于循环次数过大的语句,就必须先生成那个大列表,这样效率不高。所以很多人用xrange来代替range,且看下面代码:

>>> xrange(0, 10)
xrange(10)
>>> help(xrange)
Help on class xrange in module __builtin__:

class xrange(object)
 |  xrange(stop) -> xrange object
 |  xrange(start, stop[, step]) -> xrange object
 |  
 |  Like range(), but instead of returning a list, returns an object that
 |  generates the numbers in the range on demand.  For looping, this is 
 |  slightly faster than range() and more memory efficient.

xrange的用法和range几乎一模一样,只是它不直接生成一个列表,而是在每次循环的时候生成一个所需的数字用于循环。帮助中也说了这样会稍微快一点,也节省了一些内存空间。可以看到xrange函数返回的是xrange的对象,这样的对象也叫做生成器(generator)。自己也可以写生成器,通过自己写的生成器就能更加清晰地理解什么是生成器。

def fab(n):
    a = 0
    b = 1
    c = 1
    i = 0
    while i < n:
        yield c
        c = a + b
        a = b
        b = c
        i = i + 1

生成器的编写和函数类似,在需要return的地方改为yield,生成器可以有多个yield。当生成器遇到一个yield的时候会停下来,返回yield后面的值,等再次调用生成器的时候,继续刚才停下的地方执行。生成器自身又构成一个循环器,每循环一次,使用一个yield的值。上面的代码是生成斐波纳挈数列,下面我们来使用它:

>>> for num in fab(5):
    print(num)

    
1
1
2
3
5

或者这样使用:

>>> list(fab(10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

这样使用斐波纳挈数列是不是显得极为方便,而且效率也很高。这样再看xrange就很容易明白什么是生成器了。(python 3.x中没有了xrange函数,range函数也不再返回一个list,而是返回一个循环对象。)

迭代器(iterator)

迭代器和生成器几乎就是一个概念,但具体深究,循环对象和for循环调用之间还有一个中间层,就是要将循环对象转换成迭代器(iterator)。这一转换是通过使用iter()函数实现的。但从逻辑层面上,常常可以忽略这一层,所以循环对象和迭代器常常相互指代对方。

表推导(list conprehension)

假设你有一个列表,现在需要你生成一个每个元素是原来列表的平方的新的列表,这很容易做到:

l = range(5)
new_l = []
for value in l:
    new_l.append(value ** 2)

但是python不推荐上面的写法,因为不优雅。可以这样优雅的来实现:

new_l = [i ** 2 for i in range(5)]

 

 

几个常用的内置函数zip,map,filter,reduce

zip()函数 

看下面的例子:

>>> fruit = ["apple", "banana", "orange"]
>>> price = [8.5, 4.0, 3.5]
>>> list(zip(fruit, price))
[(apple, 8.5), (banana, 4.0), (orange, 3.5)]

由于zip函数返回的也是一个循环对象,所以我们用list方法将它转化为一个列表。zip函数依次取各个参数中的一个元素组成一个新的元素。下面用一个例子来说明zip函数的用法:

def transpose(data):
    ‘‘‘
    data is a list of list representing a matrix. return the transposed matrix.
    ‘‘‘    
    return [list(x) for x in zip(*data)]

上面函数的功能是输入一个矩阵,返回它的转置矩阵。

map()函数?

filter()函数

reduce()函数