目录
函数的参数
- 位置参数。例如power(x,y),调用函数时,传入的两个值按照位置顺序依次赋给参数x,y
- 默认参数。def power(x, n=2)。n=2就是默认参数
- 可变参数。def calc(*args)。*ages就是可变参数
- args接收的是一个tuple
- 可变参数既可以直接传入:
func(1, 2, 3)
,又可以先组装list或tuple,再通过*args
传入:func(*(1, 2, 3))
- 关键字参数。def person(name, age, **kw)。*kw就是关键字参数
- kw接收的是一个dict
- 关键字参数既可以直接传入:
func(a=1, b=2)
,又可以先组装dict,再通过**kw
传入:func(**{'a': 1, 'b': 2})
- 命名关键字参数。def person(name, age, *, city, job)。*表示命名关键字参数
- 因为关键字参数,可以不受限制的输入关键字参数,但是如果要限制关键字参数的命名,就可以使用命名关键字参数。如上例子表示,只接收city、job作为关键字参数
- 必须传入参数名
- def person(name, age, *args, city, job)。如果前面有一个可变参数,可以不用再加*,没有则必须加
- 参数的组合使用
- 参数定义的顺序必须是:位置参数、默认参数、可变参数、命名关键字参数和关键字参数
高级特性
-
切片(slice)。
# 切片slice,左闭右开
a = ['bob','lili','cobe','macy','mingming']
a[1:4] # ['lili','cobe','macy']
a[1:4:2] # ['lili', 'macy']
a[4:1:-1] #倒叙输出,['mingming', 'macy', 'cobe']
-
迭代(Iteration)。
- 我们可以通过
for
循环来遍历list
或tuple
,这种遍历称为迭代。 -
列表生成式。
- 我们可以通过
list(range(1,10)) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[x for x in range(1, 10)] #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
可迭代对象(Iterable)
- 特点:Iterable定义了__iter__()方法,该方法返回一个迭代器
- 你可以看到list、tuple、dict等容器都是实现了__iter__()方法的,证明他们是可迭代对象
- 当我们用方法iter([1,2,3,4])时候,就会调用
__iter__()这个方法,返回一个迭代器
- 这时候迭代器会带上__next__()方法,在执行next()时候就会执行__next__()方法
- for循环,机制就是以上过程,比如我们for i in [1,2,3,4,5],首先调用这个列表的__iter__()方法返回一个迭代器,然后不断调用这个迭代器的__next__()方法
- 特点:Iterable定义了__iter__()方法,该方法返回一个迭代器
-
迭代器(
Iterator
)- 所以你看上面的过程可以发现:迭代器对象会比一个不是迭代器的对象(如list、tuple)多一个__next__()方法。迭代器可以执行next()方法
- 迭代器是一种惰性计算,比如计算斐波那契数列,每次next时候我就返回下一个值
-
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__(self): return self # 实例本身就是迭代器,因为他实现了__next__()方法,故返回自己 def __next__(self): self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: # 退出循环的条件 raise StopIteration() return self.a # 返回下一个值
-
生成器(generator)。
- 生成器(generator)就是一种特殊的迭代器(iterator),那它特殊在哪呢?
- 关键字
yield
来替换迭代器中的__next__()方法,yield
有中断的功能 - 生成器可以传入数据进行计算
- 如下代码↓↓↓
- 当运行
a = c.send(None)
时,启动生成器函数,这时候yield返回b,并中断,但还未赋值给test。yield b,效果相当于renturn b,所以a拿到0 - 当运行
a = c.send(3)
时,马上进行赋值,test = None,并继续下面的运算,直到返回yield b,继续中断,下次send到来时候进行赋值
- 关键字
- 生成器(generator)就是一种特殊的迭代器(iterator),那它特殊在哪呢?
g = (x * x for x in range(10)) #将列表生成式中的中括号[],变成小括号()即可
next(g) # 通过next()函数获得generator的下一个返回值,没有元素将抛出StopIteration错误
for n in g:
print(n) # 一般通过for循环打印下一个元素
def fib(max):
n, a, b = 0, 0, 1
while n < max:
test = yield b #通过yield关键字定义generator,并可以接受参数
a, b = b, a + b
n = n + 1
return 'done'
c = fib(100)
a = c.send(None)
d = c.send(3)
最后可以用下面方法判断是否是可迭代对象、迭代器、生成器
from collections.abc import Iterable
isinstance([], Iterable) #可以使用isinstance()判断一个对象是否是Iterable对象
函数式编程
-
高阶函数
"""map 将每个元素传入f进行计算,返回一个迭代器Iterator
(可以用next()返回元素的叫迭代器)"""
from collections.abc import Generator,Iterator
def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(r) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
isinstance(r,Iterator) # True
"""reduce 将每两个元素传入f进行计算,将返回的结果继续下次计算"""
from functools import reduce
def f(x, y):
return x + y
reduce(f, [1, 3, 5, 7, 9]) #相当于(((1+3)+5)+7)+9
"""filter 将每个元素传入f,函数用于过滤序列,返回迭代器Iterator"""
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # [1, 5, 9, 15]
"""
sorted 排序,可以接收一个key函数来实现自定义的排序
将每个元素作用于key,依据返回的结果进行排序
"""
sorted([36, 5, -12, 9, -21], key=abs) #按绝对值大小排序,[5, 9, -12, -21, 36]
-
返回函数
def lazy_sum(*args):
ax = 0
def sum():
nonlocal ax
for n in args:
ax = ax + n
return ax
return sum
"""
我们在函数lazy_sum中又定义了函数sum,
内部函数sum可以引用外部函数lazy_sum的参数和局部变量,
这种结构称为“闭包(Closure)”"""
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
"""
f1(),f2()和f3()结果都是9,
因为返回的函数引用了变量i,但它并非立刻执行。
等到3个函数都返回时,它们所引用的变量i已经变成了3,
因此最终结果为9
"""
"""
返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量
"""
-
匿名函数
- lambda x: x*x
-
装饰器(Decorator)
"""
在不改变原有函数功能的情况下,动态增加功能
"""
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
"""
装饰器传入参数
"""
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('2015-3-25')
"""
函数是包含__name__属性的,通过上面的方式,__name__属性值由now变成wrapper
为将原始函数的__name__等属性复制到wrapper()函数
Python内置的functools.wraps就是干这个事的
"""
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
-
偏函数
- Python的
functools
模块提供了很多有用的功能。其中一个就是偏函数(Partial function)
- Python的
"""
简单总结functools.partial的作用就是:
把一个函数的某些参数给固定住(也就是设置默认值)
返回一个新的函数,调用这个新函数会更简单
"""
import functools
int2 = functools.partial(int, base=2)