参考 Python学习手册 第四版

1 from vs import

  • import 模块 : 导入的一整个模块(python中模块对应一个py文件)

    因为import使用一个变量名引用整个模块对象,所以必须通过模块名称来得到该模块的属性。

    程序在第一次导入指定模块的时候,会执行三个步骤

    1. 找到模块文件
    2. 编译成字节码(需要时)
    3. 执行模块的代码来创建其所定义的对象

    这三个步骤,只在模块第一次被导入时才进行,第二次导入则不会,只会提取内存中已加载的模块对象。

    从技术上讲,python将载入的模块存储到一个名为``sys.modules`的表中,并在一次导入操作的开始检查该表,如果模块不存在,将会启动这三个步骤。

  • from... import : 导入模块中的一个变量

    因为from会把变量名复制到另一个作用域,所以就可以直接在脚本中使用复制后的变量名,而不需要通过模块访问

举个粒子

先建立一个ttttest.py脚本文件,输入一行代码。

  1. cnblog_name = "XiiX"

使用import需要通过模块名称来访问,导入的是一个模块

  1. In [6]: import ttttest
  2. In [7]: ttttest.cnblog_name
  3. Out[7]: 'XiiX'
  4. In [8]: type(ttttest)
  5. Out[8]: module

使用from可以直接访问,可以看到导入的就是一个变量

  1. In [10]: from ttttest import cnblog_name
  2. In [11]: cnblog_name
  3. Out[11]: 'XiiX'
  4. In [12]: type(cnblog_name)
  5. Out[12]: str

import和from其实是一个赋值语句

请注意,它们不是编译期间的声明,而是一个可以执行的语句。

  • import 将整个模块对象赋值给一个变量名
  • form 将一个或多个变量名赋值给另一个模块中同名的对象

2 列表解析

在处理序列的操作和列表的方法中,python有一个更高级的操作——列表解析表达式(list comprehension expression)。列表解析常常具有处理速度上的优势(会比手动的for循环语句快一倍以上,因为它们的迭代在解释器内存是以C语言的速度执行的而不是以手动python代码执行),能够在python的任何序列类型中发挥作用,甚至一些不属于序列的类型。

虽然列表解析速度上很有优势,但是只适用于小规模的任务,对于大规模的数值运算,使用Numpy包的效率会更高。

举个粒子:

  • 假设我们需要从矩阵中提取出第二列,我们可以通过一行代码就能解决这个问题

    1. In [2]: M
    2. Out[2]: [[1, 2, 4], [2, 5, 6], [1, 2, 3]]
    3. In [3]: col2 = [row[1] for row in M]
    4. In [4]: col2
    5. Out[4]: [2, 5, 2]

列表解析源自集合的概念,是一种通过对序列中的每一项运行一个表达式来创建一个新列表的方法。列表解析是编写在方括号中的(提醒你在创建一个新列表),并且使用了同一个变量名(这里是row)的表达式和循环结构组成。

实际操作中,我们还可以加一些额外的操作,比如算术运算,过滤等操作

  1. # +1
  2. In [5]: [row[1] +1 for row in M]
  3. Out[5]: [3, 6, 3]
  4. # 只取出偶数
  5. In [6]: [row[1] for row in M if row[1]%2==0 ]
  6. Out[6]: [2, 2]

再举一些粒子,大家也可以发挥自己的想象力

  • 取出矩阵中的对角线上的值,非常的方便

    1. In [8]: [M[i][i] for i in range(len(M))]
    2. Out[8]: [1, 5, 3]
  • 分离字符串,不过list()也能做

    1. In [9]: [c+',' for c in "Hello"]
    2. Out[9]: ['H,', 'e,', 'l,', 'l,', 'o,']
    3. In [10]: list('Hello')
    4. Out[10]: ['H', 'e', 'l', 'l', 'o']

还可以使用嵌套的循环

  1. In [13]: [x+y for x in "abc" for y in "XiiX"]
  2. Out[13]: ['aX', 'ai', 'ai', 'aX', 'bX', 'bi', 'bi', 'bX', 'cX', 'ci', 'ci', 'cX']

3 range迭代器

python3.0中,range返回一个迭代器,该迭代器根据需要产生范围内的数字,而不是在内存中构建一个结果列表。会比较节省空间。

如果需要一个列表的话,可以使用list(range(...))强制产生一个真正的范围列表

  1. In [15]: r = range(0,10)
  2. In [16]: r
  3. Out[16]: range(0, 10)
  4. In [17]: list(r)
  5. Out[17]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

python3.0中,range对象只支持迭代、索引以及len函数,不支持其他的序列操作。

  1. In [18]: len(r)
  2. Out[18]: 10
  3. In [19]: r[0]
  4. Out[19]: 0
  5. In [20]: r[2]
  6. Out[20]: 2
  7. In [22]: I = iter(r)
  8. In [23]: next(I)
  9. Out[23]: 0
  10. In [24]: next(I)
  11. Out[24]: 1

4 map、zip和filter迭代器

和range类似,,map、zip以及filter内置函数在Python3.0中也转变为迭代器以节约内存空间。

但是和range不同,它们都是自己的迭代器——在遍历其结果一次之后,它们就用尽了,换句话说,不能在它们的结果上引用在那些结果中保持不同位置的多个迭代器。

  1. In [35]: m = map(abs, (-2,-1,0))
  2. In [36]: m
  3. Out[36]: <map at 0x7fb371ca4130>
  4. In [37]: next(m)
  5. Out[37]: 2
  6. In [38]: next(m)
  7. Out[38]: 1
  8. In [39]: next(m)
  9. Out[39]: 0
  10. In [40]: next(m)
  11. StopIteration

可以看到,在遍历一次之后,它们就用尽了。无法再继续遍历。

如果还是不明白的话,我们再来观察一下对zip的试验。可以看到两次迭代之后,用list强制转换z,之后只剩一个值, 所以值是在消耗的,一旦迭代一次过后,这个值就没有了。

注意:list(z)会一次性将其全部消耗

  1. In [49]: z = zip((1,2,3),(10,20,30))
  2. In [50]: next(z)
  3. Out[50]: (1, 10)
  4. In [51]: next(z)
  5. Out[51]: (2, 20)
  6. In [52]: list(z)
  7. Out[52]: [(3, 30)]
  8. In [53]: next(z)
  9. StopIteration:

多个迭代器vs单个迭代器

range可以同时存在多个迭代器,并且支持len和索引,但是不是自身的迭代器,是使用iter产生的迭代器。

可以看到range本身没有迭代器,要使用iter产生,产生的迭代器之间互不干扰是独立的。

  1. In [54]: r = range(3)
  2. In [55]: next(r)
  3. TypeError: 'range' object is not an iterator
  4. In [56]: I1 = iter(r)
  5. In [57]: I2 = iter(r)
  6. In [58]: next(I1)
  7. Out[58]: 0
  8. In [59]: next(I2)
  9. Out[59]: 0

相反,zip和map和filter之间不支持相同结果上的多个迭代器同时存在。

从下方试验的代码可以看到,即使定义了两个迭代器,但是由于迭代是不断消耗的(与range不同),所以两个迭代器实际上指向的位置是一致的。

  1. In [60]: z = zip((1,2,3),(1,2,3))
  2. In [61]: I1 = iter(z)
  3. In [62]: I2 = iter(z)
  4. In [63]: next(I1)
  5. Out[63]: (1, 1)
  6. In [64]: next(I1)
  7. Out[64]: (2, 2)
  8. In [65]: next(I2)
  9. Out[65]: (3, 3)
  10. In [66]: next(I2)
  11. StopIteration:
  12. In [67]: next(I1)
  13. StopIteration:

map

在程序中对列表和其他序列常常要做的一件事就说对每一个元素进行一个操作,并把其结果集合起来,这样的情况就可以使用map来进行操作。

例如,在一个列表counter中更新所有的数字,这虽然可以写一个for循环,完成,但是通过map会更加高效。

lambda的使用见下一节

  1. In [5]: counter = [1,2,3,4]
  2. ## for
  3. In [6]: temp = []
  4. In [7]: for x in counter:
  5. ...: temp.append(x + 10)
  6. ...:
  7. In [8]: temp
  8. Out[8]: [11, 12, 13, 14]
  9. ## map
  10. In [9]: list(map(lambda x:x+10, counter))
  11. Out[9]: [11, 12, 13, 14]

zip

使用zip可以配对来自多个序列的参数

  1. In [12]: list(zip((1,2,3),(4,5,6),(7,8,9)))
  2. Out[12]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

filter

函数式编程工具filter,在python的内置函数中,map函数是用来进行函数式编程的这类工具中最简单的内置函数代表。

函数式编程的意思就是对序列应用一些函数的工具,例如,基于某一测试函数过滤出一些元素(filter)

举个例子,从一个序列中挑选出大于0的元素

  1. In [11]: list(filter( (lambda x: x>0), range(-5,3) ))
  2. Out[11]: [1, 2]

5 lambda表达式

lambda名称是来自LISP,而LISP则是从lambda calculus (一种符号逻辑形式)取得到的名称。

除了def以外,python还提供了一种生成函数对象的表达式形式,lambda。就像def一样,这个表达式创建了一个能够调用的函数,但是它返回了一个函数而不是将这个函数赋值给一个变量名。这也是lambda有时也叫做匿名函数的原因。

lambda表达式的一般写法

  1. lambda argument1, argument1, ... argumentN : expression using arguments
  • lambda是一个表达式,而不是一个语句。因为这一点,lambda可以出现在python语法不允许def出现的地方——例如,在一个列表常量中或者函数调用的参数中。
  • lambda的主体是一个单个的表达式,而不是一个代码块。主体非常简单,也决定了其不能执行复杂的任务
  1. In [68]: def func(x,y,z): return x+y+z
  2. In [69]: func(1,24,1)
  3. Out[69]: 26
  4. In [70]: f = lambda x,y,z:x+y+z
  5. In [71]: f(2,3,4)
  6. Out[71]: 9

这里的f被赋值给一个lambda表达式创建的函数对象,这也就是def所完成的任务。只不过def的赋值是自动进行的。

此外,默认参数也能够在lambda参数中使用

  1. In [72]: x = (lambda a='fee', b='fie', c='foe': a+b+c)
  2. In [73]: x("wee")
  3. Out[73]: 'weefiefoe'

为什么要使用lambda?

总体而言,使用lambda起到了一种函数速写的作用,允许在使用的代码内嵌入一个函数的定义。虽然能用def来代替,但是使用lambda会更简洁。

lambda通常用来编写跳转表(jump table),也就是行为的列表或者字典。

  1. In [1]: L = [lambda x : x**2, lambda x : x**3, lambda x : x**4 ]
  2. In [2]: for f in L:
  3. ...: print(f(2))
  4. ...:
  5. 4
  6. 8
  7. 16

像这样的情况,def无法直接写入列表,只能先定义好三个def,然后再创建列表,毫无疑问,使用lambda会更为高效。

还可以写入字典里

  1. In [3]: dict = {'already':(lambda:2+2), 'got':(lambda:2*4),'one':(lambda:2**3)}
  2. In [4]: dict['got']()
  3. Out[4]: 8

下一章会讲一下python的对象

Python 高级进阶知识(一)的更多相关文章

  1. Python高级进阶(一)Python框架之Django入门

    传说中的Django Django由来 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的框架模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下 ...

  2. Python高级进阶(二)Python框架之Django写图书管理系统(LMS)

    正式写项目准备前的工作 Django是一个Web框架,我们使用它就是因为它能够把前后端解耦合而且能够与数据库建立ORM,这样,一个Python开发工程师只需要干自己开发的事情就可以了,而在使用之前就我 ...

  3. 一凡老师亲录视频,Python从零基础到高级进阶带你飞

    如需Q群交流 群:893694563 不定时更新2-3节视频 零基础学生请点击 Python基础入门视频 如果你刚初入测试行业 如果你刚转入到测试行业 如果你想学习Python,学习自动化,搭建自动化 ...

  4. python最全学习资料:python基础进阶+人工智能+机器学习+神经网络(包括黑马程序员2017年12月python视频(百度云链接))

    首先用数据说话,看看资料大小,达到675G 承诺:真实资料.不加密,获取资料请加QQ:122317653 包含内容:1.python基础+进阶+应用项目实战 2.神经网络算法+python应用 3.人 ...

  5. python学习大全:python基础进阶+人工智能+机器学习+神经网络

    首先用数据说话,看看资料大小,达到675G承诺:真实资料.不加密.(鉴于太多朋友加我QQ,我无法及时回复,) 方便的朋友给我点赞.评论下,谢谢!(内容较大,多次保存) [hide]链接:[url]ht ...

  6. Python高级编程和异步IO并发编程

    第1章 课程简介介绍如何配置系统的开发环境以及如何加入github私人仓库获取最新源码. 1-1 导学 试看 1-2 开发环境配置 1-3 资源获取方式第2章 python中一切皆对象本章节首先对比静 ...

  7. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  8. Spring实战3:装配bean的进阶知识

    主要内容: Environments and profiles Conditional bean declaration 处理自动装配的歧义 bean的作用域 The Spring Expressio ...

  9. MEF高级进阶

    MEF高级进阶   好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四 ...

随机推荐

  1. Django Static与Media

    关于Django中Static和Media的设置问题(尤其是css和js静态文件加载的问题),网上有很多回答,但是发现有相当一部分回答并不能解决问题.有的可能是Django版本问题,有的是把media ...

  2. 上百本电子书(Java/Hadoop/Spark/Linux/机器学习/)免费分享 百度云持续更新

    分享一下自己整理的超多电子书, 其中包括:Java,Hadoop,Spark,Linux,Hbase,Hive,机器学习,区块链 目录如下: 1 Java 基础 2 Java 虚拟机 3 Java 并 ...

  3. 微信小程序一周时间表

    <view class="dateView"> <image class="dateLeft" bindtap="prevWeek& ...

  4. 抽一根烟的时间学会.NET Core 操作RabbitMQ

    什么是RabbitMQ? RabbitMQ是由erlang语言开发的一个基于AMQP(Advanced Message Queuing Protocol)协议的企业级消息队列中间件.可实现队列,订阅/ ...

  5. CodeBlocks的安装配置以及使用教程

    CodeBlocks的安装配置以及使用教程 教程写的很啰嗦,本来几句话就能搞定的,但为了照顾到那部分真正的小白还请大家见谅! 一.下载 前往CodeBlocks官网下载带编译器的版本,目前的最新版本为 ...

  6. 翻译:《实用的Python编程》03_06_Design_discussion

    目录 | 上一节 (3.5 主模块) | 下一节 (4 类) 3.6 设计讨论 本节,我们重新考虑之前所做的设计决策. 文件名与可迭代对象 考虑以下两个返回相同输出的程序. # Provide a f ...

  7. 建立高速缓存机制-java版

    前言 ​ 一台计算机的核心是CPU,它是计算机系统的运算和控制核心.由于它处理运算速度快,所以基本都会给CPU配置一级缓存,当CPU要读取一个数据时,首先从缓存中查询,如果没有在从内存或者磁盘块中找. ...

  8. css行高

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  9. gtk+2.0中函数set_widget_font_size()函数在编译时未定义的解决办法

    自己写一个头文件即可,代码如下: 在.c文件中包含该头文件即可

  10. C#无边框窗体拖动代码

    1.重写 protected override void WndProc(ref Message m) { if (m.Msg == 163 && this.ClientRectang ...