两个集合a, b:
a & b 交集
a | b 合集
a - b 差集
比直接for循环省时间
setdefault更新value且避免重复搜索
dict查找key非常快,同时很消耗内存
不要对字典同时进行迭代和修改。如果想扫描并修改一个字典,最好:
1.迭代,找出需要添加的内容,放入一个新字典
2.迭代结束后对原有字典进行更新
原因:往dict添加新key时,py解释器可能会为dict扩容,导致新建一个更大的散列表。将已有元素加入新表时可能发生的散列冲突,会导致dict顺序改变。因此若边遍历边修改,很有可能跳过一些key。
装饰器的一个关键特性是,它们在被装饰的函数定义后立刻运行。这通常是在导入时(即python模块加载时)。
functools.lru_cache
会把结果缓存,传入参数相同时直接返回结果。
被该装饰器装饰的函数,所有参数必须是可散列的
functools.lru_cache(maxsize=128, typed=False)
maxsize: 指定缓存的结果数,缓存慢了后旧的结果会被扔掉
typed: 设为True时,会把不同参数类型得到的结果分开保存
(即把通常认为相等的整数参数与浮点数参数1/1.0区分开
functools.singledispatch
对于 Python 来说是不支持方法的重载的,不过它为我们提供了一个装饰器,能将普通函数变为泛函数(generic function)
# 针对不同类型的数据进行不同的处理,而又不想将它们写到一起
@functools.singledispatch
def typecheck():
pass
@typecheck.register(str)
def _(text):
print(type(text))
print("str--")
@typecheck.register(list)
def _(text):
print(type(text))
print("list--")
@typecheck.register(int)
def _(text):
print(type(text))
print("int--")
# 测试
a = 1
typecheck(a)
>>>
int--
a = "check"
typecheck(a)
>>>
str--
== 比较两个对象的值(对象中保存的数据
is 比较两个对象的标识
a = 1
b = a
c = 1
a == c >>> True
c is a >>> False
b == a >>> True
b is a >>> True
copy做浅拷贝
deepcopy做深拷贝
若对象有循环引用,深拷贝会进入无线循环,deepcopy会记住已经复制的对象,因此能优雅处理循环引用。
a = [10, 20]
b = [a, 30]
a.append(b) >>> a: [10, 20, [[...], 30]]
from copy import deepcopy
c = deepcopy(a) >>> c: [10, 20, [[...], 30]]
del语句删除名称,而不是对象。只有当一个对象的所有引用都被删除,或者无法获得该对象时,他才会被销毁回收。(重新绑定也会改变对象的引用数)
s1 = {1, 2, 3}
s2 = s1 >>> s1,s2都指向 {1, 2, 3}
del s1 >>> 删除变量s1,但此时{1,2,3}还存在引用,不被回收
s2 = '123' >>> s2改变引用,此时{1,2,3}被销毁回收
修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数。然后可以直接调用。
class A(object):
bar = 1
def func1(self):
print ('fun1')
@classmethod
def func2(cls):
print ('func2')
print (cls.bar)
cls().func1() # 调用 foo 方法
A.func2() # 不需要实例化
如果在方法中不需要访问任何实例方法和属性,纯粹地通过传入参数并返回数据的功能性方法,那么它就适合用静态方法来定义。它节省了实例化对象的开销成本,往往这种方法放在类外面的模块层作为一个函数存在也是没问题的,而放在类中,仅为这个类服务。
class C(object):
@staticmethod
def func(n):
print('func:' + n);
C.f(); # 静态方法无需实例化
cobj = C()
cobj.f() # 也可以实例化后调用
functools.reduce(lambda a,b: a b, range(1, 6))
>>> 120
functools.reduce(operator xor, range(6))
>>> 1
functools.reduce(operator xor, [], 0)
>>> 0
>>> list(zip([1, 2, 3], [4, 5, 6]))
[(1, 4), (2, 5), (3, 6)]
>>> x2, y2 = zip(*zip(x, y))
>>> x == list(x2) and y == list(y2)
True
>>> list(zip([1.0, 2.0, 3.0, 4.0], 'abc', range(3)))
[(1.0, 'a', 1), (2.0, 'b', 2), (3.0, 'c', 3)]
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
序列可以迭代的原因:iter函数
若实现了则直接调用;若没有实现__iter__方法,但是实现了__getitem__方法,python会创建一个迭代器,尝试按顺序(从索引0开始)获取元素;否则抛出TypeError异常。
迭代器
迭代器是这样的对象:实现了无参数的__next__方法,返回序列中的下一个元素。没有元素时抛出StopIteration异常。python的迭代器还实现了__iter__方法,因此迭代器也可以迭代。
注:可迭代的对象不是迭代器。且可迭代的对象一定不能是自身的迭代器,其可以实现__iter__方法,但不能实现__next__方法
以下三种的else当做‘then’会更好理解
for/else
仅当for循环运行完毕时(即for循环没有被break中止)才运行else块
while/else
仅当while循环因为条件为假值而退出时(即while循环没有被break中止)才运行else块
try/while
仅当try块中没有抛出异常时才运行else块
上下文管理器协议包含__enter__
和__exit__
方法。with语句开始运行时,会在上下文管理器对象上调用__enter__
方法,结束时调用__exit__
方法
class Sample:
def __enter__(self):
print "In __enter__()"
return "Foo"
def __exit__(self, type, value, trace):
print "In __exit__()"
def get_sample():
return Sample()
with get_sample() as sample:
print "sample:", sample
输出:
In __enter__()
sample: Foo
In __exit__()
协程状态
当前状态可用inspect.getgeneratorstatus(...)
确定
GEN_CREATED:等待执行开始
GEN_RUNNING:解释器正在执行
GEN_SUSPENDED:在yield表达式处暂停
GEN_CLOSED:执行结束
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total / count
输出:
>>>mie = averager()
>>>next(mie)
>>>mie.send(10)
10.0
>>>mie.send(30)
20.0
>>>mie.send(5)
15.0
coroutine装饰器
不预激的协程没什么用(初始调用mie.send(x)
之前一定要调用next(mie)
),为了简化协程用法,会使用一些预激装饰器。
from coroutil import coroutine
@coroutine
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total / count
输出:
>>>mie = averager()
>>>from inspect import get generatorstatus
>>>generatorstatus(mie)
'GEN_SUSPENDED'
>>>mie.send(10)
10.0
>>>mie.send(30)
20.0
>>>mie.send(5)
15.0
期物 :https://www.jianshu.com/p/6be8f184feda