遇到个lambda,不知道什么鬼,先放着
看到编码风格了,虽然我很想找个程序来搞搞,还是先看看规范,这是一种态度。
https://www.python.org/dev/peps/pep-0008/
有点长,我就简要看看。。。。
这条直接伤害了我的习惯:把空格放到操作符两边,以及逗号后面,但是括号里侧不加空格:a = f(1, 2) + g(3, 4)
。
很好,步入数据结构
列表自然不说,堆栈一直搞不懂什么时候用得着,后进先出的规则。队列就先进先出
http://www.pythondoc.com/pythontutorial27/datastructures.html
对于列表来讲,有三个内置函数非常有用: filter()进行条件过滤map() 计算立方等等以及 reduce()求和等等。
列表推导式也来了,嵌套的特性不深究
元组,还是要研究,因为我经常忘记它,元组是 不可变的
一个元组由数个逗号分隔的值组成,例如:
>>> 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))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
File "" , line 1, in
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
集合,也是经常忘记的,这里就了解特性。集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素
字典,重点
序列是以连续的整数为索引,与此不同的是,字典以 关键字 为索引,关键字可以是任意不可变类型,通常用字符串或数值。如果元组中只包含字符串和数字,它可以作为关键字,如果它直接或间接地包含了可变对象,就不能当做关键字。不能用链表做关键字,因为链表可以用索引、切割或者 append()
和 extend()
等方法改变。
理解字典的最佳方式是把它看做无序的键:值对 (key:value 对)集合,键必须是互不相同的(在同一个字典之内)。一对大括号创建一个空的字典:{}。初始化链表时,在大括号内放置一组逗号分隔的键:值对,这也是字典输出的方式。
这里是使用字典的一个小示例:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> tel.keys()
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
dict() 构造函数可以直接从 key-value 对中创建字典:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
此外,字典推导式可以从任意的键值表达式中创建字典:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
如果关键字都是简单的字符串,有时通过关键字参数指定 key-value 对更为方便:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}
遍历字典时,使用 iteritems()
方法可以同时得到键和对应的值。:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.iteritems():
... print k, v
...
gallahad the pure
robin the brave
6. 模块
如果你退出 Python 解释器并重新进入,你做的任何定义(变量和方法)都会丢失。因此,如果你想要编写一些更大的程序,为准备解释器输入使用一个文本编辑器会更好,并以那个文件替代作为输入执行。这就是传说中的 脚本。 随着你的程序变得越来越长,你可能想要将它分割成几个更易于维护的文件。你也可能想在不同的程序中使用顺手的函数,而不是把代码在它们之间中拷来拷去。
模块是包括 Python 定义和声明的文件。文件名就是模块名加上 .py 后缀。模块的模块名(做为一个字符串)可以由全局变量 __name__ 得到
如果打算频繁使用一个函数,你可以将它赋予一个本地变量:
>>> fib = fibo.fib
>>> fib(500)
1 1 2 模块可以导入其他的模块。一个(好的)习惯是将所有的 import 语句放在模块的开始(或者是脚本),这并非强制。被导入的模块名会放入当前模块的全局符号表中。
import 语句的一个变体直接从被导入的模块中导入命名到本模块的语义表中。例如:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这样不会从局域语义表中导入模块名(如上所示,fibo 没有定义)。
甚至有种方式可以导入模块中的所有定义:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 3773 5 8 13 21 34 55 89 144 233 377
需要注意的是在实践中往往不鼓励从一个模块或包中使用 * 导入所有,因为这样会让代码变得很难读
出于性能考虑,每个模块在每个解释器会话中只导入一遍。因此,如果你修改了你的模块,需要重启解释器或者如果你就是想交互式的测试这么一个模块,可以用 reload() 重新加载,例如 reload(modulename)。
当你使用以下方式运行 Python 模块时,模块中的代码便会被执行:
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
6.1.2. 模块的搜索路径
导入一个叫 spam 的模块时,解释器先在当前目录中搜索名为 spam.py 的文件。如果没有找到的话,接着会到 sys.path 变量中给出的目录列表中查找。sys.path 变量的初始值来自如下:
输入脚本的目录(当前目录)。
环境变量 PYTHONPATH 表示的目录列表中搜索
(这和 shell 变量 PATH 具有一样的语法,即一系列目录名的列表)。
Python 默认安装路径中搜索。
实际上,解释器由 sys.path 变量指定的路径目录搜索模块,该变量初始化时默认包含了输入脚本(或者当前目录),PYTHONPATH 和安装目录。这样就允许 Python 程序了解如何修改或替换模块搜索目录。需要注意的是由于这些目录中包含有搜索路径中运行的脚本,所以这些脚本不应该和标准模块重名,否则在导入模块时 Python 会尝试把这些脚本当作模块来加载。这通常会引发错误。请参见 标准模块 以了解更多的信息。
6.3. dir() 函数
内置函数 dir() 用于按模块名搜索模块定义,它返回一个排好序的字符串类型的存储列表:其实就是可以看模块有什么东西啦
一个模块集(一个“包”),原来在python模块的每一个包中,都有一个__init__.py文件(这个文件定义了包的属性和方法)然后是一些模块文件和子目录,假如子目录中也有 __init__.py 那么它就是这个包的子包了。当你将一个包作为模块导入(比如从 xml 导入 dom )的时候,实际上导入了它的 __init__.py 文件。
一个包是一个带有特殊文件 __init__.py 的目录。__init__.py 文件定义了包的属性和方法。其实它可以什么也不定义;可以只是一个空文件,但是必须存在。如果 __init__.py 不存在,这个目录就仅仅是一个目录,而不是一个包,它就不能被导入或者包含其它的模块和嵌套包。
输入、输出
如何将值转化为字符串?很幸运,Python 有办法将任意值转为字符串:将它传入 repr() 或 str() 函数。
常用的format(),操作符 %
也可以用于字符串格式化(比较旧式了)
文件读写:open(),read()等等的方法自己看参考手册吧
从文件中读写字符串很容易。数值就要多费点儿周折,因为 read()
方法只会返回字符串,应将其传入 int() 这样的函数,就可以将 '123'
这样的字符串转换为对应的数值 123。当你想要保存更为复杂的数据类型,例如嵌套的列表和字典,手工解析和序列化它们将变得更复杂。
好在用户不是非得自己编写和调试保存复杂数据类型的代码,Python 允许你使用常用的数据交换格式 JSON(JavaScript Object Notation)。标准模块 json 可以接受 Python 数据结构,并将它们转换为字符串表示形式;此过程称为 序列化。从字符串表示形式重新构建数据结构称为 反序列化。网上解释:实际上JSON就是Python字典的字符串表示,但是字典作为一个复杂对象是无法直接传递,所以需要将其转换成字符串形式.转换的过程也是一种序列化过程.
错误、异常
说实话,我还是很难用到异常。。。。
try ... except 语句可以带有一个 else子句 ,该子句只能出现在所有 except 子句之后。当 try 语句没有抛出异常时,需要执行一些代码,可以使用这个子句。使用 else 子句比在 try 子句中附加代码要好,因为这样可以避免 try ... except 意外的截获本来不属于它们保护的那些代码抛出的异常。
不管有没有发生异常,finally子句 在程序离开 try 后都一定会被执行。
自动清理:
有些对象定义了标准的清理行为,无论对象操作是否成功,不再需要该对象的时候就会起作用。以下示例尝试打开文件并把内容打印到屏幕上:
for line in open("myfile.txt"):
print line
这段代码的问题在于在代码执行完后没有立即关闭打开的文件。这在简单的脚本里没什么,但是大型应用程序就会出问题。with 语句使得文件之类的对象可以确保总能及时准确地进行清理:
with open("myfile.txt") as f:
for line in f:
print line
语句执行后,文件 f 总会被关闭,即使是在处理文件中的数据时出错也一样。其它对象是否提供了预定义的清理行为要查看它们的文档。
看到这里http://www.pythondoc.com/pythontutorial27/classes.html
类:
链接的讲解太翻译化了,新手根本看得云里雾里!
我挑了几个重点,作用域和命名空间。
可以参考比较白话版的解释:
http://www.jb51.net/article/73516.htm
类定义了 __init__() 方法的话,类的实例化操作会自动为新创建的类实例调用 __init__() 方法。
下面的说了半天还是没说出到底有什么用。
9.3.3. 实例对象
现在我们可以用实例对象作什么?实例对象唯一可用的操作就是属性引用。有两种有效的属性名。
数据属性 相当于 Smalltalk 中的“实例变量”或 C++ 中的“数据成员”。和局部变量一样,数据属性不需要声明,第一次使用时它们就会生成。例如,如果 x 是前面创建的 MyClass 实例,下面这段代码会打印出 16 而在堆栈中留下多余的东西:
x.counter = 1
while x.counter < 10:
x.counter = x.counter * 2
print x.counter
del x.counter
另一种为实例对象所接受的引用属性是 方法 。方法是“属于”一个对象的函数(在 Python 中,方法不止是类实例所独有:其它类型的对象也可有方法。例如,链表对象有 append,insert,remove,sort 等等方法。然而,在后面的介绍中,除非特别说明,我们提到的方法特指类方法)。
实例对象的有效名称依赖于它的类。按照定义,类中所有(用户定义)的函数对象对应它的实例中的方法。所以在我们的例子中,x.f 是一个有效的方法引用,因为 MyClass.f 是一个函数。但 x.i 不是,因为 MyClass.i 不是函数。不过 x.f 和 MyClass.f 不同,它是一个 方法对象,不是一个函数对象。
类的 实例化 使用函数符号。只要将类对象看作是一个返回新的类实例的无参数函数即可,例如(假设沿用前面的类):
x = MyClass()
方法的特别之处在于实例对象作为函数的第一个参数传给了函数。在我们的例子中,调用 x.f() 相当于 MyClass.f(x)
一般来说,实例变量用于对每一个实例都是唯一的数据,类变量用于类的所有实例共享的属性和方法:
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
一般,方法的第一个参数被命名为 self
。这仅仅是一个约定:对 Python 而言,名称 self
绝对没有任何特殊含义(但是请注意:如果不遵循这个约定,对其他的 Python 程序员而言你的代码可读性就会变差,而且有些类查看器程序也可能是遵循此约定编写的。)。
通过 self 参数的方法属性,方法可以调用其它的方法:
class Bag:
def __init__(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)
派生类可能会覆盖其基类的方法。因为方法调用同一个对象中的其它方法时没有特权,基类的方法调用同一个基类的方法时,可能实际上最终调用了派生类中的覆盖方法
以一个下划线开头的命名(例如 _spam )会被处理为 API 的非公开部分(无论它是一个函数、方法或数据成员)。它会被视为一个实现细节,无需公开。(类似私有变量)
"单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量;
"双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。
专有方法
如果是以双划线开头,但不是以它结尾,所命名的方法是私有方法;
如果以双划线开头,并且以双划线结尾,所命名的方法就是专有方法。
这是python规定的。所以在写程序的时候要执行,不执行就是跟python过不去,过不去就报错了。
比如前面反复提到的__init__(),就是一个典型的专有方法。那么自己在写别的方法时,就不要用__开头和结尾了。虽然用了也大概没有什么影响,但是在可读性上就差很多了,一段程序如果可读性不好,用不了多长时间自己就看不懂了,更何况别人呢?
关于专有方法,出了__init__()之外,还有诸如:__str__,__setitem__等等,要向看,可以利用dir()函数在交互模式下看看某个函数里面的专有东西。当然,也可以自己定义啦。
至于迭代器,生成器,用到再说目前接触到的库:sys,os,针对日常的文件和目录管理任务,shutil 模块,datetime模块,模块直接支持通用的数据打包和压缩格式:zlib,gzip,bz2,zipfile 以及 tarfile:性能度量解决同一问题的不同方法之间的性能差异timeit
质量控制
开发高质量软件的方法之一是为每一个函数开发测试代码,并且在开发过程中经常进行测试。
还有就是这些模块,看看即可。
xmlrpclib 和 SimpleXMLRPCServer 模块让远程过程调用变得轻而易举。
尽管模块有这样的名字,用户无需拥有XML的知识或处理 XML。
email 包是一个管理邮件信息的库,包括MIME和其它基于 RFC2822 的信息文档。
不同于实际发送和接收信息的 smtplib 和 poplib 模块,email 包包含一个构造或解析复杂消息结构(包括附件)及实现互联网编码和头协议的完整工具集。
xml.dom 和 xml.sax 包为流行的信息交换格式提供了强大的支持。
同样,csv 模块支持在通用数据库格式中直接读写。综合起来,这些模块和包大大简化了 Python 应用程序和其它工具之间的数据交换。
国际化由 gettext, locale 和 codecs 包支持。
正则表达式也是用到再说,输出重定向什么的。
互联网访问,这个要看看了,urllib2
第二部分的标准库都是给老司机看的。这里略过
一些资料的链接
标准库:https://docs.python.org/2.7/library/index.html#library-index
安装 Python 模块 展示了如何安装其他 Python 用户编写的附加模块。https://docs.python.org/2.7/install/index.html#install-index
Python 语言参考: 詳細说明了 Python 语法和语义。它读起来很累,不过对于语言本身,有份完整的手册很有用。https://docs.python.org/2.7/reference/index.html#reference-index
基础过了一遍。准备研究代码,撸撸撸