1.[a:b)
在使用list时,我们会常常使用左右区间的位置来赋值(range)或删除(del)其中的值。一定记住这个区间是一个左闭右开的区间;
a = range(1,6)
a
[1,2,3,4,5]
del a[1,3]
a
[1,4,5]
实际删除的是1,2号元素,所以剩下的是[1,4,5]
2.Lambda表达式
如果使用过filter/map/reduce这几个函数,就会知道lambda表达式真的在匿名函数的写法上非常省时省力,且便于阅读。举个例子:
>>> filter(lambda x : x % 2 == 0, range(10))
[0, 2, 4, 6, 8]map(lambda x, y : x * y, range(1,4), range(1,4))
[1, 4, 9]
reduce(lambda x, y : x + y, range(101))
注:想学习Python的小伙伴们进群:984632579领取从0到1完整学习资料 视频 源码 精品书籍 一个月经典笔记和99道练习题及答案*
lambda表达式的用法也很简单,“:”前写明参数,后面写表达式(函数体),表达式的结果就是函数返回值,这一点和R语言很像。
3.Tuples
A tuple consists of a number of values separated by commas
元组(tuples)在数据处理方面非常的powerful,因为它可以包含任意类型的变量,且可以嵌套,各个元素间用逗号分隔。但是,请注意:Tuples are immutable!(这一点和String一样),但是他们可以包含mutable的变量。
>>> 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 assignmentbut they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
v
([1, 2, 3], [3, 2, 1])
u可以看作一个嵌套的tuple;v可以看做包含了2个list的tuple,而list是可以赋值的mutable变量;但是我们不能直接去修改tuple中元素的值,因为tuple本身是immutable的,搞清楚这一点很重要。
4.unpacking
unpacking应该和tuples结合起来看:如果将一个个变量装进tuple中被称作pack的话;那么将tuple拆分成一个个独立的变量就叫做unpack。
t = 1, 2, ‘hello’
t
(1, 2, ‘hello’)
x, y, z = t
x
1
y
2
z
‘hello’
值得注意的是:左边的变量数量一定要与tuple中的元素数量一致!
Sequence unpacking requires the list of variables on the left to have the same number of elements as the length of the sequence.
5.Loop techniques
python对于循环的支持非常好,内置了很多有用的函数,这里以enumerate(), zip(), reversed(), sorted(),iteritems()为例进行说明。
enumerate()
the position index and corresponding value can be retrieved at the same time using the enumerate() function.
可以在循环时同时取得下标位置和对应值
for i, v in enumerate([‘tic’, ‘tac’, ‘toe’]):
… print i, v
…
0 tic
1 tac
2 toe
zip()
To loop over two or more sequences at the same time, the entries can be paired with the zip() function.
在循环中如果有两个几以上的队列时,可以通过zip函数进行对应的匹配
questions = [‘name’, ‘quest’, ‘favorite color’]
answers = [‘lancelot’, ‘the holy grail’, ‘blue’]
for q, a in zip(questions, answers):
… print ‘What is your {0}? It is {1}.’.format(q, a)
…
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
reversed()
To loop over a sequence in reverse, first specify the sequence in a forward direction and then call the reversed()function.
倒序输出结果
for i in reversed(xrange(1,10,2)):
… print i
…
9
7
5
3
1
sorted()
To loop over a sequence in sorted order, use the sorted() function which returns a new sorted list while leaving the source unaltered.
遍历后返回一个有序队列,并且不修改原队列。
basket = [‘apple’, ‘orange’, ‘apple’, ‘pear’, ‘orange’, ‘banana’]
for f in sorted(set(basket)):
… print f
…
apple
banana
orange
pear
iteritems()
When looping through dictionaries, the key and corresponding value can be retrieved at the same time using the iteritems() method.
当遍历dictionaries时,可以通过iteritems()来分别获取key和value
knights = {‘gallahad’: ‘the Pure’, ‘robin’: ‘the brave’}
for k, v in knights.iteritems():
… print k, v
…
gallahad the pure
robin the brave
6.Modules
很多人在开发时往往会涉及第三方package和多个脚本的情况,但是其实很多时候有些细节上的东西没有弄明白往往会出现事倍功半的效果。剩下两节就好好讲清楚Modules和Packages的关系,不感兴趣的可以跳过。
A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended. Within a module, the module’s name (as a string) is available as the value of the global variable name.
module就是一个包含了一些定义(函数,类,变量,对象等)和语句的文件,一般以”.py”作为后缀,编译后的python文件以”.pyc”作后缀。在module内,有一个全局变量”name”,可以通过dir()函数来查看当前环境中有哪些已定以的变量和函数。
以经典的fibonacci数列为例,假设下面这段代码是写在”fibo.py”这个文件中:
Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
现在如果我们想要在命令行或者终端中使用这个函数,我们可以import这个module:
import fibo
fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
你还可以给这个一个简单的别名,使代码更简洁:
fib = fibo.fib
fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
7.Packages
(1)Packages are a way of structuring Python’s module namespace by using “dotted module names”.
(2)A package is A collection of modules
简单来说,package就是一个有结构的module的集合,以便于实现某些特定功能和用途,比较出名的packages有:NumPy, PIL(Python Imaging Library)等等。
它与modules最大的不同在于import时的细节,一定要注意语法!
假设我们有个叫做”sound”的package,它主要用来处理多种不同格式的音频文件,如:mp3,wmv,wma等。它的结构如下:
sound/ Top-level package
init.py Initialize the sound package
formats/ Subpackage for file format conversions
init.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
init.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
init.py
equalizer.py
vocoder.py
karaoke.py
...
python官方不建议import整个package,因为它会降低代码的可读性。
Note that in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code.
因此,我们有必要学会如何科学正确的import我们需要的submodule或subpackage.假设我们只需要echo.py这个module,我们可以单独import它:
import sound.effects.echo
This loads the submodule sound.effects.echo. It must be referenced with its full name. 必须使用全名去调用echo中的函数
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
An alternative way of importing the submodule is: 另一种import方法:
from sound.effects import echo
This also loads the submodule echo, and makes it available without its package prefix, so it can be used as follows:通过from关键字,我们可以在调用时省去包名的前缀
echo.echofilter(input, output, delay=0.7, atten=4)
Yet another variation is to import the desired function or variable directly:如果你知道要调用什么函数,甚至可以直接import这个函数
from sound.effects.echo import echofilter
Again, this loads the submodule echo, but this makes its function echofilter() directly available:这样的话,你就可以像调用本地函数一样,省去所有前缀
echofilter(input, output, delay=0.7, atten=4)
通过三种import方法的对比,相信大家能够根据自己的实际情况找到最适合自己的方法。
但是,这里有一点语法上的细节,需要注意!
Note that when using from package import item, the item can be either a submodule (or subpackage) of the package, or some other name defined in the package, like a function, class or variable. The import statement first tests whether the item is defined in the package; if not, it assumes it is a module and attempts to load it. If it fails to find it, an ImportError exception is raised.
当使用from package import item这种语法结构时,item可以是一个submodule或subpackage,甚至是package中定义的一个函数,类和变量等对象;import会先假设item是一个对象,去测试其是否被定义;如果没有找到,它会尝试去加载,如果仍然没有找到,那么这时候会报ImportError
Contrarily, when using syntax like import item.subitem.subsubitem, each item except for the last must be a package; the last item can be a module or a package but can’t be a class or function or variable defined in the previous item.
相反,如果使用item.subitem.subsubitem这样的语法结构时,除了最后一个item可以是module或者package以外,上级(前缀)的所有item必须且只能是package,请谨记!
8.input() vs raw_input()
他们的作用都是用来读取命令行或者文件中的数据,区别在于返回结果
- input()返回的是numeric,如int,flat,double
- raw_input()返回的是String
举个例子:
>>> input()
12+2 #comand line input
14 #ouputraw_input()
12+2 #comand line input
'12+2' #ouput
然而在读过python的源码后,你会发现其实input()是通过raw_input来实现的:
def input(prompt):
return (eval(raw_input(prompt)))
9.Output Formating
从C语言开始,格式化字符串就已经为程序员所熟知,不管是C/C++还是Java,我觉得都没有python在输出格式化方面做的这么简练易用。举两个例子:
zfill()
‘pads a numeric string on the left with zeros. It understands about plus and minus signs:‘
这个函数的厉害之处在于它不仅能够高位补零,而且可以识别正负号!
>>> '12'.zfill(5)
'00012''-3.14'.zfill(7)
'-003.14'
str.format()
当有多个string需要输出时,这个函数非常的powerful:
>>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
We are the knights who say "Ni!"
with position:
>>> print '{0} and {1}'.format('spam', 'eggs')
spam and eggsprint '{1} and {0}'.format('spam', 'eggs')
eggs and spam
with keyword:
>>> print 'This {food} is {adjective}.'.format(
... food='spam', adjective='absolutely horrible')
This spam is absolutely horrible.
combine position with keyword:
>>> print 'The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
... other='Georg')
The story of Bill, Manfred, and Georg.
对于需要遍历输出对应项的情况,python更是给出了一个不错的解决方案—>:,再结合一下position和format,完美!
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}for name, phone in table.items():
... print '{0:10} ==> {1:10d}'.format(name, phone)
...
Jack ==> 4098
Dcab ==> 7678
Sjoerd ==> 4127
10.Serializing and Deserializing
序列化(serializing)和反序列化(deserializing)是为了数据的易用性而出现的,在不同开发平台和互联网中,数据的表示方法一直都是处于百花齐放的局面。直到JSON的出现,才有了一个便于交换(interchange)的数据格式
- 序列化: 将python中的数据结构以字符串形式表示
- 反序列化: 将上述的字符串重建为python中的数据结构
- JSON: JavaScript Object Notation
简单来说,只需要记住两个函数json.dumps()和json.load()就可以了。他们的函数原型分别是:
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
两个函数的参数意义相同,可以自行阅读tutorial了解详情,这里不展开了。
json.load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
11.Class Objects
python是支持OOP的语言,因此接下来几节介绍python中到的各种对象。
类是一个抽象的概念,类对象(class objects)支持两种操作(operations):
- 属性引用(attribute references)
- 实例化(instantiation)
与其它大多数OOP语言一样,python的类也有变量和方法(method),不过却又略有不同。python的变量(data attribute)是属于类的,也即是说只要定义了类,那么不需要实例化,就能够直接访问,类似于java中类的静态变量(static variable).并且可以直接通过赋值(assign)去修改值。举例:
>>> class Simple:
... i = 1
... def foo(self):
... return "hello world"
...Simple.i
1
Simple.i = 2
Simple.i
2
但是类的方法却必须通过实例化后才能访问,python中的实例化也有其独特之处,实例对象(instance object)放在下节讲。如果没有实例化而直接去访问类中定义的方法,会报unbound method,这是因为方法(method)是必须作用到一个实际的对象上的,而类对象本身是抽象的:
>>> Simple.foo
至于为什么类中的方法必须要自带一个self参数,我后面再讲,这也是python作为一个动态语言,与静态的OOP之间最大的差异!
12.Instance Objects
实例对象(instance object)是一个具体的可操作的对象,其实例化的过程在python的官方解释中是这么说明的:
“Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class.“
官方让我们假设类对象是返回一个实例对象的无参函数,所以实例化的过程就像是得到一个函数的返回结果。(晕吗?)个人感觉按照C++和Java的构造器(constructor)来理解,也不会出现太大问题。
>>> x = Simple()x.foo()
'hello world'
既然要实例化,必然躲不过一个词“初始化”(initialization),python中定义了init()这个方法来初始化实例对象。举个例子:
>>> class A:
... i = 1
... def init(self):
... self.i = 3
...A.i
1 #class attribute
x = A()
x.i
3 #instance attribute
A.i
1 #class attribute
前面我做了比喻,类的变量和Java中的静态变量类似,但这里可以看出它们的不同。在Java中静态变量是属于类的,被其所有实例共用。然而python的变量不是共用的,所以我才说python的类理解起来更抽象一点,类也是一个对象,不过和实例对象却不同,更加抽象(晕吗?)
之所以有这么大的差异,主要原因是python是一个动态语言,它可以动态添加属性,这就令很多一直用Java和C++的人不习惯。不过当你习惯之后,你会发觉它这种设计也真是好处多多。比如,你可以随时给你的类增加新的变量啊~
>>> class A:
... i = 1
...A.j = 2
A.j
2
13.Method Objects
在python中,方法(method)和函数(function)是不同的。方法应该特指在类中定义的,其特征就是在定义时必须带上一个参数self。这和其他语言隐式的处理this这个参数不同(两者作用一样)。python必须要显示的指定这个方法作用的对象,这样的好处是在调用时能够确保方法是绑定(bound)在作用对象上的。因此,类是不能凭空调用方法的,必须作用在实例上才行,所以前面章节的例子里会出现unbound method这个错误提示。举个例子:
>>> class B:
... def f(self):
... return "Hello Method"
...b = B() #b is an instance object
b.f()
'Hello Method'he
B.f(b) #B is a class object
'Hello Method'
当类B有了实例b之后,它也是可以调用方法f的,因为这一切都只是为了确保这个方法的作用对象是存在的!现在回过头来看self,其实就是指类的实例本身作为参数传进这个函数:
“the special thing about methods is that the object is passed as the first argument of the function.“
这样也就好解释为什么函数本身定义时是可以不用显示的写self参数了,因为函数本身可以不属于任何类。如果有学过pascal这类面向过程的语言,就很好理解这句话了。
>>> def f(): #Void, like a procedure in pascal
... 1 + 2
...f()
def ff(): #Return, like a function in pascal
... return 1 + 2
...
ff()
3