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不能再次贴在其它变量上了。

循环对象

循环对象是这样一个对象,它包含有一个next()方法(__next__()方法,在python 3.x中), 这个方法的目的是进行到下一个结果,而在结束一系列结果之后,举出StopIteration错误。(该句解释来自Vamei大神,我写博客也是受到他的启发,附上他的博客地址http://www.cnblogs.com/vamei)

关于循环对象难免要涉及以下一些概念:生成器(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)]

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

223405_5Q36_590878.jpg

拉链的两边就像zip函数的两个参数(当然参数可以有多个)

map()函数

map()函数的第一个参数是一个函数对象,第二个参数是包含多个元素的列表。由map这个名字不难理解这个函数的功能,map函数是将第二个列表参数里面的元素依次循环地作用于第一个函数对象,并返回一个列表(列表中的元素是函数对象的返回值)。

>>> map(lambda x: x + 1, range(10))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

在python3.x中map函数不再返回一个列表,而是返回一个循环对象。后面的filter函数的命运和map一样,在python 3.x中都是返回一个循环对象了。

对于第一个函数对象里面需要多个参数,则第二个列表对象也需要同样数目的多个参数。一图值千言。

224735_9FJc_590878.jpg

不会用那种看起来很专业的工具画图,直接qq截的。

filter()函数

有了前面两个函数就不难理解filter了,看名字是过滤的意思。我们来看看他的doc string吧。

Help on class filter in module builtins:

class filter(object)
 |  filter(function or None, iterable) --> filter object
 |  
 |  Return an iterator yielding those items of iterable for which function(item)
 |  is true. If function is None, return the items that are true.

同样第一个参数是一个函数对象。

>>> filter(lambda x: x > 5, range(10))
[6, 7, 8, 9]

从上面简短的一句代码可以知道filter的第一个参数相当于一个起到过滤作用的函数。将列表中元素符合过滤函数的都过滤出来。

reduce()函数

reduce函数和上面几个的参数一样,它的功能是累进地将列表参数作用于函数对象。比如可以用reduce函数来求N的阶乘。

>>> reduce(lambda x, y: x*y, range(1, 6))
120

python 3.x中需要从functools导入reduce。我想可能是因为reduce的返回值和上面的不统一吧,被踢出了内置函数。

转载于:https://my.oschina.net/seandor/blog/267061

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值