0. 请写下这一节课你学习到的内容:格式不限,回忆并复述是加强记忆的好方式!
大家可能还不知道,在Python的社区里有句俗话:“Python自己带着电池(Batteries included)”,什么意思呢?要从Python的设计哲学说起,Python的设计哲学是:优雅、明确和简单。因此,Python开发者演变出来的哲学就是,用一种方法,最好是只有一种方法来做一件事。虽然我们常常努力大家多思考,条条大路通罗马,那是为了训练大家的发散式思维,但是在正式编程中,如果有完善、并且经过严密测试过的模块可以直接实现,那么我的建议是使用现成的模块来工作。
所以Python附带安装的有Python标准库,一般我们说的电池就是Python标准库中的模块,这些模块都极其有用,Python标准库中包含一般任务所需要的模块,不过呢,Python标准库包含的模块有100多个之多,一个个单独来讲那着实是不科学的,所以这一讲,我们将学习如何独立的来探索模块。
对于Python来说,学习资料其实一直都在身边(Python不仅带着电池,还带着充电器....),我们这里给大家分析,遇到问题,我们应该如何去找答案,其实90%的答案你都可以通过我们以下的方式来找到解决的方法。
首先要做的就是打开Python的文档,IDLE-Help-Python Docs(F1),如图:
What the huck!!! 都是鸟文啊,我看不懂怎么办,不会的话当然是学啊,说实话,对于一个程序员来说,还是需要一定的英语基础的,因为对于经济全球化的今天,最新最全的文档基本上都是鸟文的,所以你一点都不懂英语真的是很被动。不过大家也不要气馁,对于变成来说,只需要掌握基本的单词就行。
我们接着讲,那这个文档的基本部分包括哪些呢?
(1)What's new in Python3.5?
介绍了相比Python2.0来说的新的变动。
(2)Tutorial
简易的Python教程,简单介绍了Python的语法。
(3)Liberary Reference
Python的整编书,这里详细列举了Python所有内置函数和标准库的各个模块的用法,非常详细,但是,你从头到尾是看不完的,当做字典来查就可以了。
(4)Inatalling Python Modules
教你如何安装Python的第三方模块
(5)Distuributing Python Modules
教你如何发布Python的第三方模块,你需要知道,Python除了标准库的几百个官方模块之外,还有一个叫做 pypi 的社区,网站为:https://pypi.python.org/pypi 搜集了全球Python爱好者贡献出来的模块,你自己也可以写一个模块发布到pypi社区,分享给全世界。
关于第三方模块,我将会在后面的笔记中为大家整理,
(6)language reference
讨论Python的语法和设计哲学
(7)Python setup and usage
谈论Python如何在不同平台上安装和使用
(8)Python HOWTOs
针对一些特定的主题进行深入并且详细的探讨
(9)Extending and Embedding
介绍如何用 C和 C++ 来开发Python的扩展模块,还有开发对应所需要的API
关于用 C和 C++ 为Python开发扩展,也会在后面的笔记中谈到。
(10)FAQs
常见问题解答
另外大家可能经常会看到的就是类似于这个 PEP 这个词语
PEP是Python Enhancement Proposals 的缩写,翻译过来就是Python增强建议书的意思。它是用来规范与定义Python的各种加强和延伸功能的技术规格,好让Python开发社区能有共同遵循的依据。
每一个PEP都有一个唯一的编号,这个编号一旦给定就不会再改变。例如,PEP 3000 就是用来定义 Python 3.0 的相关技术规格;而PEP 333 则是 Python 的 Web 应用程序界面 WSGI (Web Server Gateway Interface 1.0)的规范。关于PEP 本身的相关规范定义在 PEP 1,而PEP 8 则定义了 Python 代码的风格指南。
有关 PEP 的列表大家可以参考 PEP 0 :<https://www.python.org/dev/peps/>
接下来就来举个实例,说说我遇到问题是怎么自救的,前阵子,我们不是举了一个计时器的例子吗,后来在第44课的课后作业的最后面,我们说,现实编程中,计时器工具千万不要自己动手写,因为有很多未知的因素会影响到你的数据,所以我们建议使用现成的模块,这个模块叫做 timeit,来对你的代码来进行计时。假设我们现在不知道 timeit 模块的用法,我应该如何入手呢?
那我们就开始来翻刚才这个文档了,我们可以使用它的搜索、索引功能,一般给出的第一个都是你需要的
如果你认为快速学习一个模块都要读这么长一篇长篇大论,那你真是 too young too simple 了,快速掌握一个模块的用法,事实上可以使用IDLE 交互界面,首先 import 该模块,然后可以调用 __doc__属性,这样就可以查看到这个模块的简介,如图:
事实上你对于这个方法应该很熟悉了,这跟我们之间讲过的函数文档是一样的,就是写在模块最开头的那个字符串,这个字符串是带格式的,我们可以使用 print() 把这个格式打印出来。会更好看一点:
然后你可能需要知道这个模块里面定义了哪些变量,哪些函数,哪些类,你可以用 dir() 内置方法把它显示出来:
>>> dir(timeit)
['Timer', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_globals', 'default_number', 'default_repeat', 'default_timer', 'dummy_src_name', 'gc', 'itertools', 'main', 'reindent', 'repeat', 'sys', 'template', 'time', 'timeit']
显示出来的这些并不是所有的名字对我们都有用,所以我们需要过滤一些我们不需要的东西,那你可能留意到 __all__这个属性了,这个属性其实就是帮助我们完成过滤的过程,我们调用 __all__属性:
>>> timeit.__all__
['Timer', 'timeit', 'repeat', 'default_timer']
它返回给我们的依然是一个列表,但是相比上面的来说,只有其中的4个成员,如果你有看前面的关于 timeit 的文档的话,你会发现,Timer是一个类,timeit、repeat、default_timer 是3个接口函数。所以,我们这个 __all__ 属性显示出来的就是这个模块可以供外界调用的所有东西。
这里有两点需要注意的,首先,不是所有的模块都有 __all__ 属性,有 __all__ 的话,这个属性里面包含的内容就是作者希望外部调用的名字,其它的就是不希望外部调用的了。其次,第二点就是,如果一个模块设置了 __all__ 属性,那么使用 from ‘模块名’ import * 语句导入到命名空间的操作,只有 __all__ 属性这里面的名字才能被导入。例如:
>>> from timeit import *
>>> Timer
<class 'timeit.Timer'>
>>> gc
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
gc
NameError: name 'gc' is not defined
找 Timer 就可以找到,但是找 gc 就找不到。
但是如果你没有设置这个 __all__ 属性的话,from ‘模块名’ import * 就会把所有不以下划线开头的名字都导入到当前命名空间,所以,我们建议,你再编写模块的时候,对外提供接口函数和类都设置到 __all__ 属性的列表中去,这样子是比较规范的做法。
还有一个属性叫做 __file__ 属性,这个属性是指明了该模块的源代码所在的位置
>>> import timeit
>>> timeit.__file__
'D:\\ProgramFiles\\Anaconda3\\lib\\timeit.py'
我们说过,快速提高编程能力有三大法宝,一个就是不断地编写代码,第二个就是阅读高手的代码。
这里提供了源代码的路径,我们就可以去找到它,并通过阅读它的源代码,吸取它的精华。
最后我们还可以使用 help() 函数
在本节课的最后,我需要提一点的就是,timeit 这个模块真的是太有用了,所以呢,我这里有对应的文档的中文详解 -> timeit 模块详解。大家有空的话,建议通读一下。
测试题(笔试,不能上机哦~)
总共 16 道题,不上机的情况下答中 14 道以下请自觉忏悔!
注:题目虽然简单,但有陷阱,反正这一讲也没什么要测试的,就考考大家常识^_^
0. 请问以下代码会打印什么内容?
>>> def func():
pass
>>> print(type(func()))
A. <type 'function'>
B. <type 'tuple'>
C. <type 'NoneType'>
D. <type 'type'>
答:C
1. 请问以下代码会打印什么内容?
>>> print(type(1J))
A. <type 'unicode'>
B. <type 'int'>
C. <type 'str'>
D. <type 'complex'>
答:D
2. 请问以下代码会打印什么内容?
>>> print(type(lambda:None))
A. <type 'NoneType'>
B. <type 'function'>
C. <type 'int'>
D. <type 'tuple'>
答:B
3. 请问以下代码会打印什么内容?
>>> a = [1, 2, 3, "FishC", ('a', 'b', 'c'), [], None]
>>> print(len(a))
A. 13
B. 7
C. 6
D. 5
答:B
4. 请问以下代码会打印什么内容?
class A:
def __init__(self, x):
x = x + 1
self.v1 = x
class B(A):
def __init__(self, x):
x = x + 1
self.v2 = x
>>> b = B(8)
>>> print("%d %d" % b.v1, b.v2)
A. 9 10
B. 9 9
C. 10 10
D. 抛出异常
答:D
5. 请问以下代码会打印什么内容?
class A:
def __init__(self, x):
self.x = x
x = 666
>>> a = A()
>>> a = A(888)
>>> a.x
A. 666
B. 888
C. None
D. 抛出异常
答:B
6. 请问以下代码会打印什么内容?
values = [1, 1, 2, 3, 5]
nums = set(values)
def checkit(num):
if num in nums:
return True
else:
return False
for i in filter(checkit, values):
print(i, end=' ')
A. 1 2 3 5
B. 1 1 2 3 5
C. 1 2 3 4 3 2 1
D. 抛出异常
答:B
7. 请问以下代码会打印什么内容?
values = [1, 1, 2, 3, 5]
def transform(num):
return num ** 2
for i in map(transform, values):
print(i, end=' ')
A. 1 1 4 9 25
B. 1 1 2 3 5
C. 0.5 0.5 1 1.5 2.5
D. 2 2 4 6 10
答:A
8. 请问以下代码会打印什么内容?
class A:
def __init__(self, x):
self.x = x
a = A(100)
a.__dict__['y'] = 50
print(a.y + len(a.__dict__))
A. 2
B. 50
C. 51
D. 52
答:D
9. 请问以下代码会打印什么内容?
class A:
def __init__(self):
pass
def get(self):
print(__name__)
>>> a = A()
>>> a.get()
A. A
B. a
C. __main__
D. _A__a
答:C
10. 请问以下代码会打印什么内容?
country_counter = {}
def addone(country):
if country in country_counter:
country_counter[country] += 1
else:
country_counter[country] = 1
addone('China')
addone('Japan')
addone('China')
addone("American")
print(len(country_counter))
A. 0
B. 1
C. 2
D. 3
答:D
11.请问以下代码会打印什么内容?
dict1 = {}
dict1[1] = 1
dict1['1'] = 2
dict1[1.0] = 3
result = 0
for each in dict1:
result += dict1[each]
print(result)
A. 2
B. 3
C. 5
D. 6
答:C
12. 请问以下代码会打印什么内容?
def dostuff(param1, *param2):
print type(param2)
dostuff('apples', 'bananas', 'cherry', 'dates')
A. <type 'int'>
B. <type 'str'>
C. <type 'tuple'>
D. <type 'dict'>
答:C
13. 请问以下代码会打印什么内容?
class A:
def __init__(self, a, b, c):
self.x = a + b + c
a = A(1,2,3)
b = getattr(a, 'x')
setattr(a, 'x', b+1)
print a.x
A. 1
B. 2
C. 6
D. 7
答:D
14. 请问以下代码会打印什么内容?
list1 = [1, 2]
list2 = [3, 4]
dict1 = {'1':list1, '2':list2}
dict2 = dict1.copy()
dict1['1'][0] = 5
result = dict1['1'][0] + dict2['1'][0]
print(result)
A. 5
B. 6
C. 8
D. 10
答:D
15. 请问以下代码会打印什么内容?
import copy
list1 = [1, 2]
list2 = [3, 4]
dict1 = {'1':list1, '2':list2}
dict2 = copy.deepcopy(dict1)
dict1['1'][0] = 5
result = dict1['1'][0] + dict2['1'][0]
print(result)
A. 5
B. 6
C. 8
D. 10
答:B