高阶函数:以其他函数作为其参数或者返回值的函数。跟JS一样,python提供了部分内置高阶函数
# 分解和汇总:map/reduce,作为内置高阶函数应用于python
# map:将一个集合中所有的元素经过指定函数处理之后组成一个新集合
# [f(1), f(2), f(3), f(4), f(5)]
def f1(x): return x*x
print map(f1, [1, 2, 3, 4, 5])
# 输出:[1, 4, 9, 16, 25]
# reduce:从集合头开始取两个元素交给指定函数计算出一个返回值,
# 再与下个元素组合成两个元素继续计算合并
# f(f(f(f(1, 2), 3), 4), 5)
def f2(x, y): return x + y
print reduce(f2, [1, 2, 3, 4, 5])
# 输出:15
# filter:从集合中筛选出能够符合指定函数的元素集合
# [f(1) ? 1 : None, f(2) ? 2 : None, f(3) ? 3 : None]
def f3(x): return x%2 == 0
print filter(f3, [1, 2, 3, 4, 5])
# 输出:[2, 4]
# sorted:对集合按指定的函数进行排序,函数接受两个元素进行比较,
# former < back则返回-1,former == back则返回0,former > back则返回1。
# 如果不给出比较函数,则按照如上比较策略排序
def f4(f, b):
if(f < b): return 1
elif(f == b): return 0
elif(f > b): return -1
print sorted([4, 3, 5, 1, 2])
print sorted(f4, [4, 3, 5, 1, 2])
# 输出:[1, 2, 3, 4, 5]
# [5, 4, 3, 2, 1]
匿名函数:python的匿名函数用关键字lambda描述
# lambda [params]: [return]
lambda x: x*x #相当于:def f(x): return x*x
装饰器模式:python的装饰器模式由装饰器函数实现
def decorator(func):
def wrapper(*args, **kw):
#做一些函数调用之前的工作
ret = func(*args, **kw)
#做一些函数调用之后的工作
return ret
return wrapper
@decorator
def f(x, y, z):
return x + y + z
# 这样,函数f就会被装饰着decorator所包装
# 这过程当中相当于执行了:f = log(f)的操作,我们定义的f函数变量指向了高阶函数log的返回值
# 配合着函数的__name__属性和系统时间,就可以做一个log装饰器
import time
def log(func):
def wrapper(*args, **kw):
tTime = time.time()
print "function %s"%func.__name__,"has been called at %d."%tTime
ret = func(*args, **kw)
print "function %s"%func.__name__,"used %d"%(time.time() - tTime),"milliseconds"
return ret
return wrapper
@log
def f(x, y): return x + y
print f(1, 4)
# 输出:function f has been called at 1502204876.
# function f used 0 seconds
# 5
偏函数:我的理解是在原有函数的基础上,进行一定的修改(不过事后用高阶函数的方式也轻松搞定了-_-)
# 廖雪峰的例子
import functools
int2 = functools.partial(int, base=2)
int2('1000000')
# 用高阶函数的实现方式(顺便试了下匿名函数)
def f(x = 2): return x*x
f3 = lambda x = 3: f(x)
print f3()
模块:一个.py文件就是一个模块,为了防止命名冲突,可以吧模块放进不同的包中
包:一个带有init.py文件的文件夹就是一个包
root #root包
|
+-- __init__.py
|
+-- abc.py #root.abc模块
|
+-- hello #hello包
|
+-- __init__.py
|
+-- abc.py #hello.abc模块
导入模块:用import关键字导入指定的模块
import module # module会变成一个变量指向这个模块
# 如果导入失败,会引发ImportError异常
# 也可以使用as关键字为导入的模块取别名
import module [as mdl] # 模块变为指向mdl这个变量
模块组件的作用域:用于指定那些函数、变量对外公开,那些私用
# __XXXX__:特殊组件
# _XXXX or __XXXX:私有组件
# XXXX:公开组件
安装外部包:跟npm一样,只不过用的是pip
pip install package
# 一旦装好了包便可以通过import的方式引用了,
# python查找包的路径是按照sys.path(数组)的定义流程来查找的
import sys
print sys.path
# 如果要修改,可以直接修改sys.path数组(临时)
# 也可以修改环境变量(永久)
# (不过一般不会修改吧 -_-)
使用新版特性:引入future模块可以使用最新版的语法
类和对象:
# 定义类格式(小括号里面的是类的父类):
class Test(superClass):
pass
# 定义构造函数、属性和方法
class Test(object):
def __init__(self, id, name):
self.id = id
self.name = name
def printSelf(self):
print self.id
print self.name
# 定义实例对象(不需要new关键字)
a = Test(100, "abcd")
a.printSelf()
所有python类的方法,第一个参数都是self,即这个类的当前实例
类成员访问域:只分为私有和公开,私有成员的名字前带双下划线
class Test(object):
def __init__(self, id):
self.__id = id
def __addId(self):
self.__id = self.__id + 1
def printId(self):
self.__addId()
print self.__id
Test(10).printId()
继承和多态:多态主要反映在isinstance()函数上,问一个子类对象是不是父类的实例,会返回True
对象信息函数:
# type()函数用于返回类或对象的类型,可以用于比较,python也提供了一个系统包定义了所有内部类型的type对象
# 相当于typeof
import types
print type(123) == type("abc")
print type(123) == types.IntType
# type函数的功能其实很强悍,我们甚至可以使用type函数创建一个类
Hello = type('Hello', (object,), dict(hello=fn))
# 接受三个参数:
# 1、类名
# 2、父类常列表(因为tuple,所以要加,)
# 3、属性方法KV表
# 之后便可以把Hello当一般类来使用了
h = Hello()
# isinstance()函数用于判断一个对象是否是指定类的实例
print isinstance("abcd", str)
# dir()函数用于遍历一个对象的所有属性和方法
print dir(0)
# 配合getattr()、setattr()和hasattr()可以直接操作一个对象
# 相当于JS的obj[attr]、obj[attr]和attr in obj
在python中,以__XXXX__命名的属性和方法被标识为特殊属性和方法,之前function类的__name__属性就是特殊属性
动态成员添加:
# 针对于实例,python有更简单的方法为实例绑定属性和方法
from types import MethodType
a = Test(1)
a.__age = 15
a.setAge = MethodType(setAge, a, Test)
# 对于不同的实例,添加的属性和方法是不存在的
b = Test(5)
b.setAge(12) # Error
# 如果要对类的所有对象都添加指定属性和方法,可以把上述操作作用在类上
# 如果想要限制类的属性,可以使用__slots__
class Test(object):
__slots__ = ("id", "name")
Test().age = 10 # Error
需要注意的是,slots仅对当前类有效,其子类不受影响(slots属性是属于当前类的)
高级属性:@property:同装饰器一样,为类的属性(成员变量)添加访问方法和设置方法
class Student(object):
def __init__(self, id):
self.__id = id
self.__name = ""
@property
def id(self):
return self.__id
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
if len(name) != 0:
self.__name = name
多重继承:python支持多重继承(不知怎么处理菱形问题?)
特殊属性和方法:
# __str__方法指定了类的打印信息(相当于JS的toString)
# __iter__方法返回一个迭代对象,交由for循环调用
# __getitem__方法允许通过下标的方式访问对象(相当于C++的重载[]操作符)
# __getattr__方法返回指定属性(相当于JS的obj[prop])
# __call__方法指定了当我们把对象当做函数一样来调用时,所调用的方法
std = Student(10)
std() # 这样就是在调用std.__call__方法
异常处理:基本的try - except(catch) - finally - raise(throw)
断言:条件表达式应该是True,否则,后面的代码就会出错。
assert n != 0, 'n is zero!'
日志记录:import logging 包之后,便可以记录日志了。可以通过设置级别来指定日志的类型
import logging
logging.basicConfig(level=logging.INFO)
...
logging.info('n = %d' % n)
...
单步调试工具pdb:命令行级别的单步工具
python -m pdb helloWorld.py
# l - 查看完整代码文件
# p - 查看变量当前值
# n - 单步执行下一句语句
# 如果需要执行到指定行,需要在代码文件的指定行添加pdb.set_trace()语句(pdb是import的)
可以使用这种方式编写自己的IDE,或者在Sublime上开发调试环境
单元测试包:import unittest包之后,就可以定义单元测试类了。从unittest.TestCase派生下来,默认以【test】开头的方法会被标识为测试方法,在测试单元运行时自动被执行
import unittest
class Animal:
def __init__(self):
self.__health = 10
self.__body = { "body": 1, "head": 1, "hands": 2, "foot": 2 }
def eat(self, food):
self.__health += food
def printState(self):
print "Current health",self.__health
@property
def health(self):
return self.__health
def __getattr__(self, key):
return self.__body[key]
class TestAnimal(unittest.TestCase):
def testInit(self):
a = Animal()
self.assertEquals(a.health, 10)
def testPrint(self):
a = Animal()
self.assertTrue("printState" in a)
def testEat(self):
a = Animal()
with self.assertRaises(KeyError):
val = a["tail"]
# 在测试方法调用之前执行
def setUp(self):
print "Start test"
# 在测试方法调用之后执行
def tearDown(self):
print "Test end"
if __name__ == '__main__':
unittest.main()
文档测试:可以把测试用的代码写在文档里,然后在命令行运行。编译器会执行文档中的测试代码,并把结果写在文档中,以便之后生成文档的用例。
# 直接使用廖雪峰的例子了
class Dict(dict):
'''
Simple dict but also support access as x.y style.
>>> d1 = Dict()
>>> d1['x'] = 100
>>> d1.x
100
>>> d1.y = 200
>>> d1['y']
200
>>> d2 = Dict(a=1, b=2, c='3')
>>> d2.c
'3'
>>> d2['empty']
Traceback (most recent call last):
...
KeyError: 'empty'
>>> d2.empty
Traceback (most recent call last):
...
AttributeError: 'Dict' object has no attribute 'empty'
'''
def __init__(self, **kw):
super(Dict, self).__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
if __name__=='__main__':
import doctest
doctest.testmod()
注意到最后两行代码。当模块正常导入时,doctest不会被执行。只有在命令行运行时,才执行doctest。所以,不必担心doctest会在非测试环境下执行。
网友评论