以下是《python进阶中文版》的一些总结和个人记录内容
http://docs.pythontab.com/interpy/
1、set() build an ordered collections of unique elements
用set()强制转换时,会排序??,去重。。排序的结果存在不正确。
set.intersection 交集
set.difference 差集
1/1 zip()产生的生成器只能使用一次。
如:
prices_and_names = zip(prices.values(), prices.keys())
print(min(prices_and_names)) # OK
print(max(prices_and_names)) # ValueError: max() arg is an empty sequence
正确使用:
min_price = min(zip(prices.values(), prices.keys()))
# min_price is (10.75, 'FB')
max_price = max(zip(prices.values(), prices.keys()))
# max_price is (612.78, 'AAPL')
2、random.choice
从给定的序列中随机选择一个元素返回。
源码:
def choice(self,seq):
return seq[int(self.random() * len(seq))]
3、默认参数问题
g = lambda x, y=2, z : x + y**z
g(1, z=10) =
报错。SyntaxError: non-default argument follows default argument
默认参数后必须都是默认参数。
4、map,filter,reduce
print map(lambda x,y:x+y,[1,2,3,4],[1,6,8,9])
print filter(lambda x:x>3,[2,4,6,8])
print reduce(lambda x,y:x+y,[1,2,3,4])
res:[2, 8, 11, 13] [4, 6, 8] 10
5、装饰器 函数和类
装饰器函数
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写入内容
with open(logfile, 'a') as opened_file:
# 现在将日志打到指定的logfile
opened_file.write(log_string + '\n')
return func(*args, **kwargs)
return wrapped_function
return logging_decorator
装饰器类,支持继承
from functools import wraps
class logit(object):
def __init__(self, logfile='out.log'):
self.logfile = logfile
def __call__(self, func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile并写入
with open(self.logfile, 'a') as opened_file:
# 现在将日志打到指定的文件
opened_file.write(log_string + '\n')
# 现在,发送一个通知
self.notify()
return func(*args, **kwargs)
return wrapped_function
def notify(self):
# logit只打日志,不做别的
pass
class email_logit(logit):
'''
一个logit的实现版本,可以在函数调用时发送email给管理员
'''
def __init__(self, email='[email protected]', *args, **kwargs):
self.email = email
super(logit, self).__init__(*args, **kwargs)
def notify(self):
# 发送一封email到self.email
# 这里就不做实现了
pass
def add_to(num, target=[]):
target.append(num)
return target
结果错误,target会成为类似全局变量的东西。
在Python中当函数被定义时,默认参数只会运算一次,而不是每次被调用时都会重新运算。你应该永远不要定义可变类型的默认参数,除非你知道你正在做什么。
正确:
def add_to(element, target=None):
if target is None:
target = []
target.append(element)
return target
7、__slots__
对类使用__slots__可以减少内存。
在Python中,每个类都有实例属性。默认情况下Python用一个字典来保存一个对象的实例属性。这非常有用,因为它允许我们在运行时去设置任意的新属性。
然而,对于有着已知属性的小类来说,它可能是个瓶颈。这个字典浪费了很多内存。Python不能在对象创建时直接分配一个固定量的内存来保存所有的属性。因此如果你创建许多对象(我指的是成千上万个),它会消耗掉很多内存。
class MyClass(object):
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
# ...
#使用 __slots__:
class MyClass(object):
__slots__ = ['name', 'identifier']
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
以下通过ipython根据来查看内存使用情况,可以看到使用slots后的好处。
Python 3.4.3 (default, Jun 6 2015, 13:32:34)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import ipython_memory_usage.ipython_memory_usage as imu
In [2]: imu.start_watching_memory()
In [2] used 0.0000 MiB RAM in 5.31s, peaked 0.00 MiB above current, total RAM usage 15.57 MiB
In [3]: %cat slots.py
class MyClass(object):
__slots__ = ['name', 'identifier']
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
num = 1024*256
x = [MyClass(1,1) for i in range(num)]
In [3] used 0.2305 MiB RAM in 0.12s, peaked 0.00 MiB above current, total RAM usage 15.80 MiB
In [4]: from slots import *
In [4] used 9.3008 MiB RAM in 0.72s, peaked 0.00 MiB above current, total RAM usage 25.10 MiB
In [5]: %cat noslots.py
class MyClass(object):
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
num = 1024*256
x = [MyClass(1,1) for i in range(num)]
In [5] used 0.1758 MiB RAM in 0.12s, peaked 0.00 MiB above current, total RAM usage 25.28 MiB
In [6]: from noslots import *
In [6] used 22.6680 MiB RAM in 0.80s, peaked 0.00 MiB above current, total RAM usage 47.95 MiB
8、collections
defaultdict无key不报错的dict:
import collections
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"
## 运行正常
#你可以用json.dumps打印出some_dict,例如:
import json
print(json.dumps(some_dict))
## 输出: {"colours": {"favourite": "yellow"}}
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
## })
deque双端队列:
popleft,pop,extendleft,extend
注意:extendleft([1,2,3])实际上会先在左边插入1,然后2,然后3。最后结果如:3,2,1。。。
namedtuple命名元组:
from collections import namedtuple
Animal = namedtuple('Animal', 'name age type')
perry = Animal(name="perry", age=31, type="cat")
print(perry[0])
## 输出: perry
使用方式:命名元组需要两个初始化参数,元组名称和字段名称。命名元组能够像字典一样访问,如perry.name。且比字典快,和普通元组性能差不多。
同样,命名元组不能进行赋值。
命名元组可以使代码自文档,且向下兼容。可以像普通元组一样通过下标访问。
Enum枚举类型:
from collections import namedtuple
from enum import Enum
class Species(Enum):
cat = 1
dog = 2
horse = 3
aardvark = 4
# 但我们并不想关心同一物种的年龄,所以我们可以使用一个别名
kitten = 1 # (译者注:幼小的猫咪)
puppy = 2 # (译者注:幼小的狗狗)
Animal = namedtuple('Animal', 'name age type')
perry = Animal(name="Perry", age=31, type=Species.cat)
enumerate:
可以用在对list的for循环中,获取索引和元素,并且,可以传入参数,说明索引从几开始。
my_list = ['apple', 'banana']
for c, value in enumerate(my_list, 1):
print(c, value)
# 输出:
(1, 'apple') #无参数1时:(0,'apple')
(2, 'banana') #无参数1时:(1,'banana')
9、一行式
locals和globals函数:
locals展示当前作用区域的局部变量。用法如下:
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'})
上述代码省去了一行行赋值。locals展示的是变量键值对。
globals展示程序所有变量。较少会用到。
csv转为json:
python -c "import csv,json;print json.dumps(list(csv.reader(open('csv_file.csv'))))"
构建共享文件夹:
# Python 2
python -m SimpleHTTPServer
# Python 3
python -m http.server
脚本性能分析:
python -m cProfile my_script.py
flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
for item in container:
if search_something(item):
# Found it!
process(item)
break
else:
# Didn't find anything..
not_found_in_container()