《Intermediate Python》阅读笔记 上半部分
args 和 ***kwargs**
- 不是必须写成*args 和**kwargs。 只有变量前⾯的 * 才是必须的
*args的用法
将不定数量的参数传递给⼀个函数
发送⼀个⾮键值对的可变数量的参数列表
1
2
3
4
5
6
7
8
9
10
11
12def test_var_args(f_arg, *argv):
print("first normal arg:", f_arg)
for arg in argv:
print("another arg through *argv:", arg)
test_var_args('yasoob', 'python', 'eggs', 'test')
# 输出:
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test
**kwargs的用法
将不定长度的键值对,作为参数传递给⼀个函数——适合在一个函数中处理带有名字的参数
1
2
3
4
5
6def greet_me(**kwargs):
for key, value in kwargs.items():
print("{0} == {1}".format(key, value))
"yasoob") greet_me(name=
name == yasoob所有参数(包括标准参数)的使用:
1
some_func(fargs, *args, **kwargs)
调试(Debugging)
Python debugger(pdb)
1
$ python -m pdb my_script.py
- debugger在脚本第⼀⾏指令处停⽌执⾏
- 可以通过
pdb
模式接着查看变量信息
脚本内部设置断点,在某些特定点查看变量信息和各种执⾏时信息
1
2
3
4
5import pdb
def make_bread():
pdb.set_trace()
return "I don't have time"
print(make_bread())- 运⾏时进⼊debugger模式
- 命令列表
- c: 继续执⾏
- w: 显⽰当前正在执⾏的代码⾏的上下⽂信息
- a: 打印当前函数的参数列表
- s: 执⾏当前代码⾏,并停在第⼀个能停的地⽅(相当于单步进⼊)
- n: 继续执⾏到当前函数的下⼀⾏,或者当前⾏直接返回(单步跳过)
生成器(Generators)
迭代器(iterators)
- 可以遍历⼀个容器(特别是列表)对象
- 任意定义了
__next__
方法的对象
可迭代对象(Iterable):Python 中任意的对象,只要定义可以返回⼀个迭代器的
__iter__
⽅法,或支持下标索引的__getitem__
方法迭代(Iteration):从某地方取出一个元素的过程
生成器:只能对其迭代一次的迭代器
运行时生成值
通过遍历使用
for
循环将生成器传递给任意可迭代的函数和结构
1
2
3
4
5def generator_function():
for i in range(10):
yield i
for item in generator_function():
print(item) # 最终打印出数字0-9应用场景:不想同⼀时间将所有计算出来的⼤量结果分配到内存
1
2
3
4
5
6
7
8# 计算斐波那契数列
def fibon(n):
a = b = 1
for i in range(n):
yield a
a, b = b, a + b
for x in fibon(1000000):
print(x)可迭代对象不一定是迭代器——⽀持迭代,但不能直接对其进⾏迭代操作
1
2
3my_string = "Yasoob"
next(my_string) # 内置函数,用于获取⼀个序列的下⼀个元素
>>>Output: Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: str object is not an iteratoriter()
:根据⼀个可迭代对象返回⼀个迭代器对象
Map,Filter 和 Reduce
Map
1
map(function_to_apply, list_of_inputs)
将⼀个函数映射到⼀个输⼊列表的所有元素上
适用于“需要把列表中所有元素⼀个个地传递给⼀个函数”甚至一组函数的情况
1
2
3
4
5
6
7
8def multiply(x):
return (x*x)
def add(x):
return (x+x)
funcs = [multiply, add]
for i in range(5):
value = map(lambda x: x(i), funcs)
print(list(value)) # 返回迭代器
Filter
过滤列表中的元素,返回⼀个由所有符合要求的元素所构成的列表——即函数映射到该元素时返回值为True
1
2number_list = range(-5, 5)
less_than_zero = filter(lambda x: x < 0, number_list)
Reduce
要对⼀个列表进⾏⼀些计算并返回结果
1
2
3# 计算阶乘
from functools import reduce
product = reduce( (lambda x, y: x * y), [1, 2, 3, 4] )
set 数据结构
不包含重复的值
两个结合的交集
1
input_set1.intersection(input_set2)
两个集合的差集
1
input_set1.difference(input_set2)
三元运算符
伪代码:condition_is_true if condition else condition_is_false
1
2is_fat = True
state = "fat" if is_fat else "not fat"简单的⼀⾏快速判断
装饰器
前述
函数赋值给一个变量
1
2
3
4def hi(name="yasoob"):
return "hi " + name
greet = hi
print(greet())函数嵌套函数
函数中返回函数——一个函数作为变量被返回
函数作为参数传递给另一个函数
装饰器
1 | # 原理 |
但@重写了函数的名字和注释⽂档,即
a_function_requiring_decoration.__name__
为wrapTheFunction
——@wraps
接受⼀个函数进⾏装饰,并具有复制函数名称、注释⽂档、参数列表等功能from functools import wraps def a_new_decorator(a_func): @wraps(a_func) ... @a_new_decorator def a_function_requiring_decoration(): pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
* 蓝本规范
```python
from functools import wraps
def decorator_name(f):
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return decorated
def func():
return("Function is running")
can_run = True
func()应用
授权:⽤于Flask和Django web框架
日志
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15from functools import wraps
def logit(logfile='out.log'):
def with_logging(*args, **kwargs):
log_string = func.__name__ + " was called"
print(func.__name__ + " was called")
with open(logfile, 'a') as opened_file:
opened_file.write(log_string + '\n')
return func(*args, **kwargs)
return with_logging
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4) # Output: addition_func was called func2.log 的⽂件出现,并记录上⾯的字符串
带参数的装饰器
- 具体参见上面的日志应用场景
Global 和 Return
- global变量:在函数以外的区域都能访问
- 返回多个变量
slots
默认情况下Python⽤⼀个字典来保存⼀个对象的实例属性
对于有着已知属性的⼩类来说,这个字典浪费了许多内存——最好直接分配⼀个固定量的内存来保存所有的属性,即使用
__slot__
给一个固定集合的属性分配空间1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 不使⽤ __slots__
class MyClass(object):
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
pass
# 使⽤ __slots__,为内存减轻负担
class MyClass(object):
__slots__ = ['name', 'identifier']
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
pass