*args 和 **kwargs
-
*是必要的, 后面的变量可以变换
-
*args 是用来发送一个非键值对的可变数量的参数列表给一个函数.
def 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') -
**kwargs允许你将不定长度的键值对, 作为参数传递给一个函数.
def greet_me(**kwargs): for key, value in kwargs.items(): print("{0} == {1}".format(key, value)) >>> greet_me(name="yasoob") name == yasoob -
如果你想在函数里同时使用所有这三种参数
some_func(fargs, *args, **kwargs)
生成器(Generators)
-
yield
- 生成器也是一种迭代器,但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中,而是在运行时生成值。
- 你通过遍历来使用它们,要么用一个“for”循环,要么将它们传递给任意可以进行迭代的函数和结构。
def generator_function(): for i in range(10): yield i for item in generator_function(): print(item) # Output: 0 # 1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 -
许多Python 2里的标准库函数都会返回列表,而Python 3都修改成了返回生成器,因为生成器占用更少的资源。
Map, Filter, Reduce
-
Map: 会将一个函数映射到一个输入列表的所有元素上。
map(function_to_apply, list_of_inputs) items = [1, 2, 3, 4, 5] squared = list(map(lambda x: x**2, items)) -
Filter: 过滤列表中的元素,并且返回一个由所有符合要求的元素所构成的列表
number_list = range(-5, 5) less_than_zero = filter(lambda x: x < 0, number_list) print(list(less_than_zero)) # 译者注:上面print时,加了list转换,是为了python2/3的兼容性 # 在python2中filter直接返回列表,但在python3中返回迭代器 # 因此为了兼容python3, 需要list转换一下 # Output: [-5, -4, -3, -2, -1] -
Reduce: 当需要对一个列表进行一些计算并返回结果时使用
from functools import reduce product = reduce( (lambda x, y: x * y), [1, 2, 3, 4] ) # Output: 24
Set数据结构
-
set与列表(list)的行为类似,区别在于set不能包含重复的值.
-
检查列表中是否包含重复的元素
""" For循环 """ some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n'] duplicates = [] for value in some_list: if some_list.count(value) > 1: if value not in duplicates: duplicates.append(value) print(duplicates) ### 输出: ['b', 'n'] """ set """ some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n'] duplicates = set([x for x in some_list if some_list.count(x) > 1]) print(duplicates) ### 输出: set(['b', 'n']) -
交集(intersection): 你对比两个集合的交集(两个集合中都有的数据)
valid = set(['yellow', 'red', 'blue', 'green', 'black']) input_set = set(['red', 'brown']) print(input_set.**intersection**(valid)) ### 输出: set(['red']) -
差集(difference): 找出无效的数据,相当于用一个集合减去另一个集合的数据
valid = set(['yellow', 'red', 'blue', 'green', 'black']) input_set = set(['red', 'brown']) print(input_set.**difference**(valid)) ### 输出: set(['brown']) -
创建集合可以用{}, 不用set()
三元运算符
is_fat = True
state = "fat" if is_fat else "not fat"
装饰器
-
原始版本
def a_new_decorator(a_func): def wrapTheFunction(): print("before a_func()") a_func() print("after a_func()") return wrapTheFunction def a_function_requiring_decoration(): print("smell") a_function_requiring_decoration() #outputs: "smell" a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration) #now a_function_requiring_decoration is wrapped by wrapTheFunction() a_function_requiring_decoration() #outputs:before a_func() # smell # after a_func() -
装饰器版本
# from functools import wraps def a_new_decorator(a_func): # @wraps(a_func) def wrapTheFunction(): print("before a_func()") a_func() print("after a_func()") return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): print("smell") a_function_requiring_decoration() #outputs:before a_func() # smell # after a_func()-
存在问题, 不显示原函数名
print(a_function_requiring_decoration.__name__) # Output: wrapTheFunction添加 @wraps(a_func) (@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。)
print(a_function_requiring_decoration.__name__) # Output: a_function_requiring_decoration -
wrap 日志: 日志是装饰器运用的另一个亮点
from functools import wraps def logit(func): @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + " was called") return func(*args, **kwargs) return with_logging @logit def addition_func(x): """Do some math.""" return x + x result = addition_func(4) # Output: addition_func was called- 还有详细logit构建, 发邮件啥的
-
对象变动 Mutation
- 不可变(immutable)对象
- int, string, float, tuple
- 可变(mutation)对象
- dict, list, set
slots
- 默认情况下Python用一个字典来保存一个对象的实例属性。这非常有用,因为它允许我们在运行时去设置任意的新属性。
- 然而,对于有着已知属性的小类来说,它可能是个瓶颈。这个字典浪费了很多内存。
- 使用__slots__来告诉Python不要使用字典,而且只给一个固定集合的属性分配空间。
class MyClass(object):
__slots__ = ['name', 'identifier'] # 使用slots减少内存占用
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
# ...
虚拟环境(virtualenv)
pip install virtualenv
virtualenv myproject
source myproject/bin/activate
-
如果你想让你的virtualenv使用系统全局模块
virtualenv --system-site-packages mycoolproject -
退出虚拟环境
deactivate
容器 Collections
- defaultdict
- 与dict不同, 你不需要检查key是否存在.
- 当你在一个字典中对一个键进行嵌套赋值时,如果这个键不存在,会触发keyError异常。 defaultdict允许我们用一个聪明的方式绕过这个问题。
- counter
-
Counter是一个计数器,它可以帮助我们针对某项数据进行计数。
from collections import Counter colours = ( ('Yasoob', 'Yellow'), ('Ali', 'Blue'), ('Arham', 'Green'), ('Ali', 'Black'), ('Yasoob', 'Red'), ('Ahmed', 'Silver'), ) favs = Counter(name for name, colour in colours) print(favs) ## 输出: ## Counter({ ## 'Yasoob': 2, ## 'Ali': 2, ## 'Arham': 1, ## 'Ahmed': 1 ## }) -
统计文件
with open('filename', 'rb') as f: line_count = Counter(f) print(line_count) -
deque
-
deque提供了一个双端队列,你可以从头/尾两端添加或删除元素.
-
可以像list一样用
from collections import deque d = deque() d.append(1) print(d[0]) d.popleft() # pop最左边 d.pop() # pop最右边 d = deque(maxlen=30) # 设置最大长度, deque塞满时, 最左的元素自动删除 -
你还可以从任一端扩展这个队列中的数据:
d = deque([1,2,3,4,5]) d.extendleft([0]) # 左边添加 d.extend([6,7,8]) # 右边添加 print(d) ## 输出: deque([0, 1, 2, 3, 4, 5, 6, 7, 8])
-
-
命名元组 (namedtuple)
from collections import namedtuple Animal = namedtuple('Animal', 'name age type') perry = Animal(name="perry", age=31, type="cat") print(perry) ## 输出: Animal(name='perry', age=31, type='cat') print(perry.name) ## 输出: 'perry' print(perry[0]) ## 输出: perry ############## perry.age = 42 # x ## 输出: ## Traceback (most recent call last): ## File "", line 1, in ## AttributeError: can't set attribute ############### print(perry._asdict()) # 将一个命名元组转换为字典 ## 输出: OrderedDict([('name', 'Perry'), ('age', 31), ...
-
枚举 Enumerate
for counter, value in enumerate(some_list):
print(counter, value)
my_list = ['apple', 'banana', 'grapes', 'pear']
for c, value in enumerate(my_list, 1): # 这个可选参数允许我们定制从哪个数字开始枚举
print(c, value)
# 输出:
(1, 'apple')
(2, 'banana')
(3, 'grapes')
(4, 'pear')
对象自省
-
dir: 返回一个列表,列出了一个对象所拥有的属性和方法。
my_list = [1, 2, 3] dir(my_list) # Output: ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', # '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', # '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', # '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', # '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', # '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', # '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', # 'remove', 'reverse', 'sort'] -
type: 返回一个对象的类型
-
id: 返回任意不同种类对象的唯一ID, 内存地址.
-
inspect: 获取活跃对象的信息
import inspect print(inspect.getmembers(str)) # Output: [('__add__', <slot wrapper '__add__' of ... ...
列表推导式, 字典推导式, 集合推导式
-
list
variable = [out_exp for out_exp in input_list if out_exp == 2] squared = [x**2 for x in range(10)] -
dict
# 把同一个字母但不同大小写的值合并起来 mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} mcase_frequency = { k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys() } # mcase_frequency == {'a': 17, 'z': 3, 'b': 34}# 快速对换一个字典的键和值 {v: k for k, v in some_dict.items()} -
squared
squared = {x**2 for x in [1, 1, 2]} print(squared) # Output: {1, 4}
异常
-
try except
try: file = open('test.txt', 'rb') except IOError as e: # 处理一个IOError的异常 print('An IOError occurred. {}'.format(e.args[-1]))try: file = open('test.txt', 'rb') except EOFError as e: print("An EOF error occurred.") raise e except IOError as e: print("An error occurred.") raise etry: file = open('test.txt', 'rb') except Exception: # 捕获所有异常 # 打印一些异常日志,如果你想要的话 raise -
finally从句: 包裹到finally从句中的代码不管异常是否触发都将会被执行.
try: file = open('test.txt', 'rb') except IOError as e: print('An IOError occurred. {}'.format(e.args[-1])) finally: print("This would be printed whether or not an exception occurred!") # Output: An IOError occurred. No such file or directory # This would be printed whether or not an exception occurred! -
try/else从句: 没有触发异常时运行
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.') # Output: I am sure no exception is going to occur! # This would only run if no exception occurs. # This would be printed in every case.
lambda表达式
lambda 参数:操作(参数)
add = lambda x, y: x + y
print(add(3, 5))
# Output: 8
for-else
- else从句会在循环正常结束时执行
for item in container:
if search_something(item):
# Found it!
process(item)
break
else:
# Didn't find anything..
not_found_in_container()
使用C扩展
from ctypes import *
Open函数
with open('photo.jpg', 'r+') as f:
jpgdata = f.read()
- 读取一个文件,检测它是否是JPG(提示:这些文件头部以字节FF D8开始)
with open('photo.jpg', 'rb') as inf:
jpgdata = inf.read()
if jpgdata.startswith(b'\xff\xd8'):
text = u'This is a JPEG file (%d bytes long)\n'
else:
text = u'This is a random file (%d bytes long)\n'
函数缓存
- 设置最多缓存最近多少个返回值
- 缓存多的话, 可重复调用的值, 节省运行时间
- cache_info() 用于查看缓存信息
from functools import lru_cache
@lru_cache(maxsize=32) # 最好设置为 2 的倍数,默认为 128。None 的话就相当于是 maxsize 为正无穷了
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
>>> print([fib(n) for n in range(10)])
# Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
fib.cache_clear() # 对返回值清空缓存
上下文管理器
class File(object):
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('Hola!')
- 当异常发生时,with语句会采取哪些步骤。
- 它把异常的type,value和traceback传递给__exit__方法
- 它让__exit__方法来处理异常
- 如果__exit__返回的是True,那么这个异常就被优雅地处理了。
- 如果__exit__返回的是True以外的任何东西,那么这个异常将被with语句抛出。
bisect 数组二分查找算法
这个模块对有序列表提供了支持,使得他们可以在插入新数据仍然保持有序。对于长列表,如果其包含元素的比较操作十分昂贵的话,这可以是对更常见方法的改进。
bisect.**bisect_left**(a, x, lo=0, hi=len(a), ***, key=None)
在 a 中找到 x 合适的插入点以维持有序。参数 lo 和 hi 可以被用于确定需要考虑的子集;默认情况下整个列表都会被使用。如果 x 已经在 a 里存在,那么插入点会在已存在元素之前(也就是左边)。如果 a 是列表(list)的话,返回值是可以被放在 list.insert() 的第一个参数的。
返回的插入点 i 将数组 a 分成两半,使得 all(val < x for val in a[lo : i]) 在左半边而 all(val >= x for val in a[i : hi]) 在右半边。
key 指定带有单个参数的 key function 用来从数组的每个元素中提取比较键。 为了支持搜索复杂记录,键函数不会被应用到 x 值。
如果 key 为 None,则将直接进行元素比较而不需要中间的函数调用。
在 3.10 版更改: 增加了 key 形参。
python中的特殊方法
python中的特殊方法被python解释器调用, 我们一般不会亲自调用.
我们可以使用内置函数来使用. eg: __len()__实现后, 使用len()即可.
也有特殊方法的调用是隐式的. eg: for i in x, 使用的是内置函数iter(x).
详细见:
-
特殊(魔术)方法汇总一览表
