文章目录
*args 用法
*args 主要用于函数的定义,可以将不定数量的参数传递给一个函数。
*agrs 是用来发送一个非键值对的可变数量的参数列表给一个函数。
def fun(a, *args):
print('a:'+ a)
for i in args:
print('args:'+i)
fun('a','b','c','d')
# a:a
# args:b
# args:c
# args:d
**kwargs 用法
允许将不定长度的 键值对 作为参数传递给一个函数。
def fun(**kwargs):
for k, v in kwargs.items():
print(k, v)
fun(a='1',b='2',c='3')
# a 1
# b 2
# c 3
可迭代对象
迭代对象
- Python 中的任意对象,只要定义了可以返回一个迭代器的
__iter__
方法 - 或者定义了支持下标索引的
__getitem__
方法 - 它就是一个可迭代对象
- 可迭代对象就是能提供迭代器的任意对象
迭代器
iter
可以将一个 可迭代对象 返回一个迭代器对象。
- 任意对象,只要定义了
__next__
方法,它就是一个迭代器。
my_string = 'HuWenBo'
my_iter = iter(my_string)
for i in range(4):
print(next(my_iter))
# H
# u
# W
# e
迭代
- 就是从某个地方取出一个元素的过程。
- 当我们使用一个循环来遍历某个对象,这个 过程本身 叫做迭代。
生成器
生成器是一种迭代器,但是只能迭代一次。
因为生成器没有把值存在内存中,而是在运行时生成值。
要么用for
循环,或传递给任意可以进行迭代的函数和结构。
大多数并不返回一个值,而是yield
一个值。
def fun():
for i in range(5):
yield i
for i in fun():
print(i)
# 0
# 1
# 2
# 3
# 4
Map、Filter、Reduce
能为函数式编程提供便利
Map
会将一个函数映射到一个输入列表的所有元素上
map(fun_apply, list)
items = [1,2,3,4]
result = map(lambda x : x ** 2, items)
print(list(result))
# [1, 4, 9, 16]
Filter
filter
过滤列表中的元素,并且返回一个由所有符合要求的元素所构成的列表。
number_list = range(-5, 5)
result = filter(lambda x: x < 0, number_list)
print(list(result))
# [-5, -4, -3, -2, -1]
Reduce
当对一个列表进行计算并返回结果时,
Reduce
十分有用
from functools import reduce
result = reduce(lambda x, y : y * y, [1,2,3,4])
print(result)
# 16
三元运算符
is_ok = True
result = 'yes' if is_ok else 'noe'
print(result)
# yes
装饰器
修改其它函数功能的函数,有助于代码复用。
它们封装一个函数,并且来修改他们之前或之后的行为。
Python 中一切皆对象
from functools import wraps
def out_fun(fun):
@wraps(fun) # 当取消这个装饰器,return后函数name就是inner_fun
def inner_fun(*args, **kwargs):
if fun.__name__ == 'demo':
print('fun() name is demo')
return fun(*args, **kwargs)
else:
print('fun() name is not demo')
return fun(*args, **kwargs)
return inner_fun
@out_fun
def demo():
return 'this is demo fun'
print(demo())
# fun() name is demo
# this is demo fun
日志功能
日志是装饰器运用的另一个亮点
from functools import wraps
def logit(func):
@wraps(func)
def save_logging(*args, **kwargs):
print(func.__name__ + 'is called')
return func(*args, **kwargs)
return save_logging
@logit
def add_fun(a):
return a
result = add_fun(2)
print(result)
# add_funis called
# 2
在函数中嵌入装饰器
通过装饰器函数传递参数给函数
from functools import wraps
def logit(logfile='out.log'):
def logging_fun(func):
@wraps(func)
def inner_fun(*agrs, **kwargs):
log_string = func.__name__ + 'was called'
print(log_string)
with open(logfile, 'a') as f:
f.write(log_string)
return func(*agrs, **kwargs)
return inner_fun
return logging_fun
@logit()
def fun1():
pass
@logit(logfile = 'out1.log')
def fun2():
pass
fun1()
fun2()
__slots__魔法
Python 中每个类都有实例熟悉,默认情况下 Python 用一个字典来保存一个对象的实例熟悉。
slots 来告诉Python不使用字典,而且只给一个固定集合的属性分配空间。
class MyClass(object):
__slots__ = ['name', 'identifier']
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
try/else 语句
else从句只会在没有异常的情况下执行,而且它会在finally语句之前执行。
try:
print('I am sure no exception is going to occur!')
except Exception:
print('exception')
else:
# 这里的代码只会在try语句里没有触发异常时运行,
# 但是这里的异常将 *不会* 被捕获
print('This would only run if no exception occurs. And an error here '
'would NOT be caught.')
finally:
print('This would be printed in every case.')
一行式
一行式内容比较多,参考另一片文章。
官网参考
简易 Web server
快速通过网络共享文件
# Python 2
python -m SimpleHTTPServer
# Python 3
python -m http.server
一行构造器
避免类初始化时大量重复的赋值语句
class A(object):
def __init__(self, a, b, c, d, e, f):
self.__dict__.update({k: v for k, v in locals().items() if k != 'self'})
列表展平
快速展平一个嵌套列表
a_list = [[1, 2], [3, 4], [5, 6]]
print(list(itertools.chain.from_iterable(a_list)))
# Output: [1, 2, 3, 4, 5, 6]
# or
print(list(itertools.chain(*a_list)))
# Output: [1, 2, 3, 4, 5, 6]
使用C扩展
开发者有三种方法可以在自己的Python代码中来调用C编写的函数-ctypes,SWIG,Python/C API。每种方式也都有各自的利弊。
CTypes
Python中的ctypes模块可能是Python调用C方法中最简单的一种。
ctypes模块提供了和C语言兼容的数据类型和函数来加载dll文件,因此在调用时不需对源文件做任何的修改。
正是如此奠定了这种方法的简单性。
SWIG
Python中调用C代码的另一种方法。
在这个方法中,开发人员必须编写一个额外的接口文件来作为SWIG(终端工具)的入口。
Python/C API
Python/C API可能是被最广泛使用的方法。它不仅简单,而且可以在C代码中操作你的Python对象。
协程
生成器是数据的生产者
协程则是数据的消费者
def grep():
while True:
line = yield
print(line)
demo = grep()
next(demo) # 启动一个协程
demo.send('hello')
demo.send('word')
demo.close() # 关闭一个协程
# hello
# word
函数缓存
函数缓存允许我们将一个函数对于给定参数的返回值缓存起来。
Python 3.2以后版本,有个lru_cache的装饰器,允许我们将一个函数的返回值快速地缓存或取消缓存。
from functools import lru_cache
@lru_cache(maxsize=30) # maxsize参数告诉lru_cache缓存最近多少个返回值
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print([fib(n) for n in range(10)])
fib.cache_clear() # 清空缓存
上下文管理器
上下文管理器的类,要定义
__enter__
和__exit__
class File:
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, type, value, traceback):
self.file_obj.close()
with File('demo.txt', 'w') as opened_file:
opened_file.write('Hello!')
with
语句先暂存File
类的__exit__
方法- 然后调用
File
类的__enter__
方法 __enter__
方法打开文件并返回给with语句- 打开的文件句柄被传递给
opened_file
参数 - 我们使用
write()
来写文件 with
语句调用之前暂存的__exit__
方法__exit__
方法关闭了文件
- 在第4步和第6步之间,如果发生异常,
Python
会将异常的type
,value
和traceback
传递给__exit__
方法。 - 当发生异常把异常的
type
,value
和traceback
传递给__exit__
方法 - 如果
__exit__
返回的是True
,异常会被处理,返回的是True
之外的,改异常被with
语句抛出
基于生成器的实现
装饰器(decorators)和生成器(generators)来实现上下文管理器
我们可以使用一个生成器函数来实现一个上下文管理器
Python有个contextlib模块专门用于这个目的
from contextlib import contextmanager
@contextmanager
def open_file(name):
f = open(name, 'w')
yield f
f.close()
with open_file('demo.txt') as f:
- 被装饰器装饰的函数分为三部分:
with
语句中的代码块执行前执行函数中yield
之前代码yield
返回的内容复制给as
之后的变量with
代码块执行完毕后执行函数中yield
之后的代码
变为上下文对象
- 如果一个对象没有实现上下文,我们就不能把它用于with语句。这个时候,可以用closing()来把该对象变为上下文对象。
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('http://httpbin.org/get')) as page:
for line in page:
print(line)
closing
也是一个经过@contextmanager
装饰的generator
@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()
它的作用就是把任意对象变为上下文对象,并支持with语句。