1. 注释:#单行注释,’’’多行注释’’’
2. 多元赋值:x,y,z=1,2,'string' 等价于 (x,y,z)=(1,2,'string')
3. 异常处理:
for a in [1,2,3]:
try:
fobj=open(fname,'r')
except IOError,e:
print "file open error: ",e
continue
else:
for eachLine in fobj:
print eachLine,
fobj.close()
4. 什么是真什么是假:
>>> if '' or {} or [] or 0 or False :
... print 'false'
...
>>> if 'sdfs' and {1:'1'} and [1,2] and 1 and True :
... print 'adfasdf'
...
adfasdf
>>>
5. isinstance()和type()
from types import *
def displayNumType0(num) :
print num,'is',
if type(num) is IntType :
print 'an integer'
elif type(num) is LongType :
print 'a long'
elif type(num) is FloatType :
print 'a float'
elif type(num) is ComplexType :
print 'a complex'
else :
print 'not a number at all !!!'
def displayNumType1(num):
print num, 'is',
if(isinstance(num,(int,long,float,complex))):
print 'a number of type: ',type(num).__name__
else:
print 'not a number at all !!!'
6. 深拷贝和浅拷贝:
>>> person=['name',['savings',100.00]]
>>> import copy
>>> hubby=copy.deepcopy(person)
>>> wifey=copy.deepcopy(person)
>>> [id(x) for x in person]
[22135968, 27744536]
>>> [id(x) for x in hubby]
[22135968, 32582712]
>>> [id(x) for x in wifey]
[22135968, 32582952]
>>> hubby[0]='suo'
>>> wifey[0]='piao'
>>> person,hubby,wifey
(['name', ['savings', 100.0]], ['suo', ['savings', 100.0]], ['piao', ['savings', 100.0]])
>>> hubby[1][1]=50.00
>>> person,hubby,wifey
(['name', ['savings', 100.0]], ['suo', ['savings', 50.0]], ['piao', ['savings', 100.0]])
>>>
7. 字典
>>> dict = {1:'1',2:'2',3:'3'}
>>> dict[1]
'1'
>>> dict[4]='4'
>>> dict
{1: '1', 2: '2', 3: '3', 4: '4'}
>>> dict2 = dict.copy
>>> dict2 = dict.copy()
>>> [id(x) for x in dict2.keys()]
[23569264, 23569252, 23569240, 23569228]
>>> [id(x) for x in dict.keys()]
[23569264, 23569252, 23569240, 23569228]
>>> dict.items()
[(1, '1'), (2, '2'), (3, '3'), (4, '4')]
>>> dict.values()
['1', '2', '3', '4']
>>> dict.keys()
[1, 2, 3, 4]
>>> dict.has_key(1)
True
>>> dict.get(1)
'1'
>>> dict.pop(4)
'4'
>>> dict
{1: '1', 2: '2', 3: '3'}
>>> dict.update({4:'4',5:'5'})
>>> dict
{1: '1', 2: '2', 3: '3', 4: '4', 5: '5'}
>>>
8. 推导式
>>> [id(x) for x in dict2.keys()]
[23569264, 23569252, 23569240, 23569228]
>>> [x*2 for x in range(0,6)]
[0, 2, 4, 6, 8, 10]
>>>sum(len(word) for line in data for word in line.split())
>>>489
9. 装饰器
装饰器实际就是函数,它接受函数对象。我们在执行函数之前,可以运行些预备代码,也可以在执行代码之后做些清理工作。这类似于java中的AOP,即面向切面编程,可以考虑在装饰器中置入通用功能的代码来降低程序复杂度。例如,可以用装饰器来:引入日志、增加计时逻辑来检测性能、给函数加入事务的能力
1) 无参装饰器:
@deco2
@deco1
def func(arg1, arg2, ...):
pass
这和创建一个组合函数是等价的:
def func(arg1, arg2, ...):
pass
func = deco2(deco1(func))
2) 有参装饰器:
@deco1(deco_arg)
@deco2
def func():
pass
这等价于:
func = deco1(deco_arg)(deco2(func))
示例:
from time import ctime,sleep
def tsfunc(func):
def wrappedFunc():
print '[%s] %s() called' % (ctime(), func.__name__)
return func()
return wrappedFunc
@tsfunc
def foo():
print 'foo() is invoked !'
foo()
sleep(4)
for i in range(2):
sleep(1)
foo()
运行结果:
[Tue Jul 17 22:45:54 2012] foo() called
foo() is invoked !
[Tue Jul 17 22:45:59 2012] foo() called
foo() is invoked !
[Tue Jul 17 22:46:00 2012] foo() called
foo() is invoked !
10. 可变长度的参数
在函数调用时如有不确定的函数参数时,可以用一个可变的参数列表变量处理当超过数目的参数被传入的情形。所有额外的参数会被加入
变量参数元组。
def argc(argc1,argc2='default2', *another):
print ('first:',argc1)
print ('second:',argc2)
for eachargc in another:
print('another argc:',eachargc,)
argc('aa','bb','cc','dd')
argc('aa')
结果:
('first:', 'aa')
('second:', 'bb')
('another argc:', 'cc')
('another argc:', 'dd')
('first:', 'aa')
('second:', 'default2')
第二个参数为默认参数, 语法(参数名 = 默认值)
*another 处理额外的参数,到变量参数元组
一个*参数保存到元组
关键字变量参数到字典,
def dicVarArgc(arg1,arg2='default',**therest):
print ('arg1',arg1)
print('arg2',arg2)
for each in therest.keys():
print('arg %s:%s'% (each,str(therest[each])))
dicVarArgc('first','second',c=2,d=3)
结果:
('arg1', 'first')
('arg2', 'second')
arg c:2
arg d:3
参数名和参数值成对出现,所以用字典保存
关键字和非关键字可变参数都有可能用在同一个函数中,只要关键字字典是最后一个参数并且非关键字元组先于它之前出现。
11. 特殊函数
hasattr():对象是否存在某个属性。
getattr():获取对象某个属性
setattr():设置对象某个属性
delattr():删除对象某个属性
issubclass(sub, sup):给出的子类sub 确实是父类sup 的一个子类,则返回True,否则返回False
isinstance(obj1, obj2):在obj1 是类obj2 的一个实例,或者是obj2 的子类的一个实例时,返回True(反之,则为False)
dir():查看对象属性列表,只显示属性值
__dict__:查看对象属性,以map格式显示,包含值。
__get__: 当类被“get”的时候,被访问的时候,会默认把访问者的instance和class信息都传进来。
def __get__(self, instance, owner):
print("\t__get__() called")
print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner))
return self.f
apply(func[, nkw][, kw]):
用可选的参数来调用func,nkw 为非关键字参数,kw 关键字参数;返回值是函数调用的返回值。
filter(func, seq):
调用一个布尔函数func 来迭代遍历每个seq 中的元素; 返回一个使func 返回值为ture 的元素的序列
map(func, seq1[,seq2...]):
将函数func 作用于给定序列(s)的每个元素,并用一个列表来提供返回值;如果func 为None, func 表现为一个身份函数,返回一个含有每个序列中元素集合的n 个元组的列表。
reduce(func, seq[, init]):
将二元函数作用于seq 序列的元素,每次携带一对(先前的结果以及下一个序列元素),连续的将现有的结果和下雨给值作用在获得的随后的结果上,最后减少我们的序列为一个单一的返回值;如果初始值init 给定,第一个比较会是init 和第一个序列元素而不是序列的头两个元素。
12. 静态方法和类方法
# -*- coding: cp936 -*-
class AttrClass(object):
def __init__(self,name,age=23,sex='male'):
self.name=name
self.age=age
self.sex=sex
def show(self):
print self.name, self.age, self.sex
#使用staticmethod()内建方法,将一个方法设置为静态方法
def staticFoo1():
print 'calling static method foo1()'
staticFoo1=staticmethod(staticFoo1)
#使用classmethod()内建方法,将一个方法设置为类方法
def classMethod1(cls):
print 'calling class method1'
classMethod1=classmethod(classMethod1)
#使用修饰符将一个方法设置为静态方法
@staticmethod
def staticFoo2():
print 'calling static method foo2()'
#使用修饰符将一个方法设置为类方法
@classmethod
def classMethod2(cls):
print 'calling class method2'
13. Override
class Parent(object):
def implicit(self):
print "PARENT implicit()"
class Child(Parent):
pass
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
class Parent(object):
def override(self):
print "PARENT override()"
class Child(Parent):
def override(self):
print "CHILD override()"
dad = Parent()
son = Child()
dad.override()
son.override()
class Parent(object):
def altered(self):
print "PARENT altered()"
class Child(Parent):
def altered(self):
print "CHILD, BEFORE PARENT altered()"
super(Child, self).altered()
print "CHILD, AFTER PARENT altered()"
dad = Parent()
son = Child()
dad.altered()
son.altered()
class Parent(object):
def override(self):
print "PARENT override()"
def implicit(self):
print "PARENT implicit()"
def altered(self):
print "PARENT altered()"
class Child(Parent):
def override(self):
print "CHILD override()"
def altered(self):
print "CHILD, BEFORE PARENT altered()"
super(Child, self).altered()
print "CHILD, AFTER PARENT altered()"
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
dad.override()
son.override()
dad.altered()
son.altered()
class Other(object):
def override(self):
print "OTHER override()"
def implicit(self):
print "OTHER implicit()"
def altered(self):
print "OTHER altered()"
class Child(object):
def __init__(self):
self.other = Other()
def implicit(self):
self.other.implicit()
def override(self):
print "CHILD override()"
def altered(self):
print "CHILD, BEFORE OTHER altered()"
self.other.altered()
print "CHILD, AFTER OTHER altered()"
son = Child()
son.implicit()
son.override()
son.altered()
14. Python模块
# -*- coding: cp936 -*-
# 1. 起始行
# -*- coding: utf-8 -*-
# 2. 模块文档
"""This is a test module again"""
# 3. 模块导入
import sys
import os
# 4. 变量定义
debug=True
# 5. 类定义语句
class FooClass(object):
"""FooClass"""
flag=1
def foo(self):
print "FooClass.foo() is invoked, "+str(self.flag)
# 6. 函数定义语句
def test():
"""test function"""
foo=FooClass()
if debug:
print 'ran test()'
foo.foo()
print foo.flag
# 7. 主程序
if __name__ == '__main__':
test()
print "what are these?"
15. 参数解析
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
print options,args
16. 编码规范: pep8 http://www.python.org/dev/peps/pep-0008/
17. yield&generator:
# -*- coding: utf-8 -*-
def h():
print 'To be brave' #不会执行
yield 5
h()
def x():
m = yield 5 #yield是一个表达式
x()
'''
c.next()调用后,h()开始执行,直到遇到yield 5,因此输出结果:
Wen Chuan
当我们再次调用c.next()时,会继续执行,直到找到下一个yield表达式。由于后面没有yield了,因此会拋出异常:
'''
def h():
print 'Wen Chuan'
yield 5
print 'Fighting!'
c = h()
c.next()
def h2():
print 'Wen Chuan',
m = yield 5 # Fighting!
print m
d = yield 12
print 'We are together!'
c = h2()
c.next() #相当于c.send(None)
c.send('Fighting!') #(yield 5)表达式被赋予了'Fighting!'
'''
中断Generator是一个非常灵活的技巧,可以通过throw抛出一个GeneratorExit异常来终止Generator。Close()方法作用是一样的,其实内部它是调用了throw(GeneratorExit)的。
'''
def close(self):
try:
self.throw(GeneratorExit)
except (GeneratorExit, StopIteration):
pass
else:
raise RuntimeError("generator ignored GeneratorExit")
18. metaclass
元类一般用于创建类。在执行类定义时,解释器必须要知道这个类的正确的元类。解释器会先寻找类属性__metaclass__,如果此属性存在,就将这个属性赋值给此类作为它的元类。如果此属性没有定义,它会向上查找父类中的__metaclass__.如果还没有发现__metaclass__属性,解释器会检查名字为__metaclass__的全局变量,如果它存在,就使用它作为元类。否则, 这个类就是一个传统类,并用 types.ClassType 作为此类的元类。
在执行类定义的时候,将检查此类正确的(一般是默认的)元类,元类(通常)传递三个参数(到构造器): 类名,从基类继承数据的元组,和(类的)属性字典。
元类何时被创建?
#!/usr/bin/env python
print '1. Metaclass declaration'
class Meta(type):
def __init__(cls, name, bases, attrd):
super(Meta,cls).__init__(name,bases,attrd)
print '3. Create class %r' % (name)
print '2. Class Foo declaration'
class Foo(object):
__metaclass__=Meta
def __init__(self):
print '*. Init class %r' %(self.__class__.__name__)
print '4. Class Foo f1 instantiation'
f1=Foo()
print '5. Class Foo f2 instantiation'
f2=Foo()
print 'END'
输出结果:
1. Metaclass declaration
2. Class Foo declaration
3. Create class 'Foo'
4. Class Foo f1 instantiation
*. Init class 'Foo'
5. Class Foo f2 instantiation
*. Init class 'Foo'
END
可见在类申明的时候,就执行了__metaclass__中的方法了,以后在定义类对象的时候,就只调用该类的__init__()方法,MetaClass中的__init__()只在类申明的时候执行了一次。通过metaclass可以动态修改子类的父类。
19. Classmethod 和 static method实现
python在类中,有三种调用method的方法:普通method,staticmethod和classmethod
前两个应该都好理解,classmethod就是在调用这个函数的时候,会把调用对象的class object对象隐式地传进去。咦?这个class object不是一个类型?No,在python里面,class object不像静态语言一样是个类型,它在虚拟机中,就是一个对象
普通method调用需要把自己self作为参数传递,初学的时候怎么着也不能理解,不过看多了就自然熟悉了。比较奇怪的是staticmethod和classmethod不像静态语言一样,通过保留关键字定义,而是使用@staticmethod或者staticmethod()这种builtin函数进行定义。这个@staticmethod到底是个什么东东?
@staticmethod
def foo(x):
print(x)
之前用过java,所以第一反应这是个annotation……唔,确实感觉像个AOP的东西,python里把它称作decorator。如果我们要自己实现一个staticmethod,该怎么写呢?
研究了下官方的代码,我再改了改,感觉应该这样写:
def foo(x):
print(x)
class StaticMethod(object):
def __init__(self, function):
print("__init__() called")
self.f = function
def __get__(self, instance, owner):
print("\t__get__() called")
print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner))
return self.f
class Class1(object):
method = StaticMethod(foo)
if __name__ == '__main__':
ins = Class1()
print("ins = %s, Class1 = %s" % (ins, Class1))
print("ins.method = %s, Class1.method = %s" % (ins.method, Class1.method))
ins.method('abc')
Class1.method('xyz')
输出结果是:
__init__() called
ins = <__main__.Class1 object at 0xece2d0>, Class1 =
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =<__main__.Class1 object at 0xece2d0>, owner =
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =None, owner =
ins.method =
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =<__main__.Class1 object at 0xece2d0>, owner =
abc
__get__() called
INFO: self = <__main__.StaticMethod object at 0xece5d0>, instance =None, owner =
xyz
嗯,看上去一切都挺顺利,Class1包含了一个变量method,不过这个method其实也是一个特殊处理过的StaticMethod类。这个类中有一个__get__函数,当类被“get”的时候,被访问的时候,会默认把访问者的instance和class信息都传进来。所以我们看到不管是否调用method()这个函数,只要碰着了method,这个函数就会触发,就会打印出当前instance和class信息。虽然ins和Class1的instance各有不同,但__get__函数中只是返回foo函数,所以这里调用method之时就没有区别,调用的都是同一个function对象。
好的,那么classmethod又如何实现呢?
def foo2(cls, x):
print("foo2's class = ", cls)
print(x)
class ClassMethod(object):
def __init__(self, function):
print("ClassMethod: __init__() called")
self.f = function
def __get__(self, instance, owner = None):
print("\t__get__() called")
print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner))
def tmpfunc(x):
print("I'm tmpfunc")
return self.f(owner, x)
return tmpfunc
class Class2(object):
method = ClassMethod(foo2)
class Class21(Class2):
pass
if __name__ == '__main__':
ins = Class2()
print("ins.method = %s, Class2.method = %s, Class21.method = %s" % (ins.method, Class2.method, Class21.method))
ins.method('abc')
Class2.method('xyz')
Class21.method('asdf')
输出结果是:
ClassMethod: __init__() called
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =<__main__.Class2 object at 0xdeb350>, owner =
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner =
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner =
ins.method =
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =<__main__.Class2 object at 0xdeb350>, owner =
I'm tmpfunc
foo2's class =
abc
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner =
I'm tmpfunc
foo2's class =
xyz
__get__() called
INFO: self = <__main__.ClassMethod object at 0xdeb250>, instance =None, owner =
I'm tmpfunc
foo2's class =
asdf
可以看出,classmethod和staticmethod的实现方法是大同小异。staticmethod比较简单,直接返回self.f变量就好了,而classmethod不行,需要把调用时候的class类型信息传给foo2函数,这个函数根据接收的class信息来作不同的工作。(不过我现在也没有想到可以用来做些什么)
有个地方值得注意,可能同志们刚才也已经想到了,我一定必须要定义一个tempfunc,再返回它才能完成工作吗?可不可以不要
def tmpfunc(x):
print("I'm tmpfunc")
return self.f(owner, x)
return tmpfunc
而直接返回一个
return self.f(owner, *args)
刚试了一把,直接传args默认参数是不行的,因为__get__被调用的时候,还没有把参数传进来。只有return tmpfunc之后,Class2.method('xyz')的参数才挂在tmpfunc之上。