@spiritnotes
2016-01-31T09:20:08.000000Z
字数 20760
阅读 6867
Python
读书笔记
如何使用常量
#filename const.py
class _const:
def __setattr__(self, name, value):
if name in self.__dict__:#禁止修改
raise Exception
if not name.isupper():#要求必须大写
raise Exception
self.__dict__[name] = value
import sys
sys.modules[__name__] = _const()
使用
import const
const.COMPANY = "IBM"
捕获用户定义约束,而非程序本身错误
注意点:
避免不必要的计算,带来性能上的提升
#words都是以.结尾,这里先判断最后一个字符是否为.,提升性能
if w[-1]=='.' and w in word:
节省空间,使得无限循环的数据结构成为可能(生成器等)
class Seasons:
Spring, Summer, Autumn, Winter = range(4)
def enum(*posarg, **keyarg):
return type("Enum", (object), dict(zip(posarg, xrange(len(posarg))),**keyarg))
Seasons = enum("Spring", "Summer", "Autumn", Winter=3)
if type(a) is types.ListType: pass
__import__("os").system("dir")
[c for c in ().__class__.__base__[0].__subclasses__() if c.__name__ == 'Quitter'][0](0)()]
可以使用 ast.literal_eval
a = float('NaN')
a is a
a != a
# coding=utf-8
#-*- coding:utf-8 -*-
import原理
1. 搜索sys.modules是否已经存在该模块
2. 未找到,为模块创建字典对象插入sys.modules
3. 根据需要对模块对应文件进行编译
4. 执行动态加载,在当前模块的命名空间执行编译后的字节码,并将其中所有的对象放入模块对应的字典中
from...import的缺点
- 命名空间冲突
- 循环嵌套导入
#c1.py
from c2 import g
def x():
pass
#c2.py
from c1 import x
def g():
pass
++i在python中被解析为+(+i)),为两个正号,对于----也是一样的
with exp1 as a, exp2 as b:
pass
# 相当于
with exp1 as a:
with exp2 as b:
pass
import contextlib
@contextlib.contextmanager
def work():
print('First part!')
yield
print('last part!')
with work():
print('middle part')
## while
while True:
pass
else: #break未执行时执行else语句,循环自然结束
pass
## for
for i in range(x):
pass
else: #break未执行时执行else语句,循环自然结束
pass
## try
try:
pass
except:
pass
else: #未抛出异常时执行else语句
pass
while True:
try:
k = 1/0
finally:
break #导致丢失异常,没有break则异常会被重新抛出
def test(n):
try:
if n <= 0: raise Exception
else: return n
finally:
return -99
test(-1) # 返回 -99
test(2) # 返回 -99
join只计算一次内存,而+使用多次
a = ['aa','aaa']
b = ['bb','bbb']
[(i+j) for i in a for j in b]
>>>['aabb', 'aabbb', 'aaabb', 'aaabbb']
[[j for j in i]for i in a]
>>>[['a', 'a'], ['a', 'a', 'a']]
[j for i in a for j in i]
>>>['a', 'a', 'a', 'a', 'a']
传递对象,或者说传递对象的引用
*args, **kwargs
缺点
- 使用过于灵活
- 使用变长参数一般说明函数可以更好的实现,应该被重构
适用
- 为函数添加装饰器
- 参数的数目不确定
- 用来实现函数的多态,或者在继承的情况下子类需要调用父类的某些方法
obj = eval(repr(obj))
a = ("a" 'b'
'c')
a.startswith(('ab', 'b'))
a = ' b c d '
a.split(' ')
>>>['', 'b', '', '', 'c', 'd', '', '']
a.split() #去掉左右空白字符,以任意个空白字符作为分割
>>>['b', 'c', 'd']
sorted(iterable, cmp, key, reverse)
s.sort(cmp, key, reverse)
区别
sorted(dict_)/sorted(dict_.items())
# 多维list
l =[ ['12', '43'], ['02', '44'], ['00', '41']]
print([i for i in sorted(l, key=operator.itemgetter(1,1))])
>>>[['00', '41'], ['12', '43'], ['02', '44']]
# 字典中混合 list(value为list)
sorted(dict_.items(),key=lamda(k,v): operator.itemgetter(1)(v))
# list 中 字典
sorted(list_, key=operator.itemgetter("rating","name"))
[section1]
option1 = 1
getopt / optparse / argparse / docopt
序列化: 将内存中的数据结构在补丢失身份和类型信息的情况转成对象的文本或者二进制表示的过程
try:
import simplejson as json
except ImportError:
import json
# 继承并重写 run
class MyThread(thread.Thread):
def run(self):
pass
# 调用对象创建传入 可执行对象
thread_ = threading.Thread(fuc_)
Queue本身是线程安全的
class _Singleton:
pass
Singleton = _Singleton()
del _Singleton
_Singleton_class = Singleton.\_\_class\_\_
class Singleton():
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
s1 = Singleton()
s2 = Singleton()
assert id(s1) == id(s2)
带锁多线程版本:
class Singleton():
objs = {}
obj_locker = threading.Lock()
def __new__(cls, *args, **kwargs):
if cls in cls.objs:
return cls.objs[cls]
cls.obj_locker.acquire()
try:
if cls in cls.objs:
return cls.objs[cls]
cls.objs[cls] = object.__new__(cls)
finally:
cls.obj_locker.release()
问题:
1. 子类若重载了 new 方法,则可能会覆盖或者干扰父类的 new 的执行,必须要求子类必须调用父类的 new 方法
2. 子类若有 init 方法,则会被调用多次,解决方法:换掉子类的 init 方法
模块实现单例模式,单例成为一个模块文件
BORG 模式: 比起实例的唯一性,应该关注实例的状态,所有的实例共享状态,行为一致
class BROG():
_shared_state = {}
def __init__(self):
self.__dict__ = self._shared_state
__base__ += (mixin_class1, mixin_class2, ...)
## Broker.py
from collections import defaultdict
class Broker():
route_table = defaultdict(list)
def sub(self, topic, callback):
if callback in route_table[topic]:
return
route_table[topic].append(callback)
def pub(self, topc, *a, **kw):
for func in route_table[topic]:
func(*a, **kw)
## use
def greeting(name):
print(name, ' hello ')
broker.sub('greet', greeting)
broker.pub('are you ok')
状态模式: 当一个对象的内在状态改变时允许改变其行为,但这个对象看上去像改变了其类。主要用于控制一个对象的状态的条件表达式过于复杂的情况,其可把状态的判断逻辑转移到表示不同状态的一系列类中,进而把复杂的判断逻辑简化
def workday() : pass
def weekday() : pass
people = People()
while True:
for i in range(1, 8):
if i == 6:
people.day = workday
if i == 1:
people.day = weekday
@stateful
class People():
class Workday(State):
default = True
@behavior
def day(self): pass
class Weekday(State):
@behavior # 为静态函数,self是指的people
def day(self): pass
people = People()
while True:
for i in range(1, 8):
if i == 6:
switch(people, people.Weekday)
if i == 0:
switch(people, people.Workday)
people.day()
对象 | type<*> | *.__class__ | *.__bases__ | isinstance(*,object) | isinstance(*,type) |
---|---|---|---|---|---|
object | 'type' | 'type' | () | true | true |
type | 'type' | 'type' | (object,) | true | true |
旧式类A实例a | 'instance' | A | () | true | false |
B(objet);b=B() | B | B | (obejct,) | true | false |
C(type);c=C() | C | C | ('type',) | true | true |
D(dict);d=D() | D | D | (dict,) | true | false |
# 旧类转变为新类
class TestNewClass:
__metaclass__ == type
古典类元类: types.ClassType
新类元类: type
__new__ 真正创建类的实例,是类的构造函数
__init__ 是实例的初始化函数
.__new__(cls[, args...])
.__init__(self[, args...])
差别
何时需要重写 new
class UserSet(frozenset):
def __new__(cls, *args):
if isinstance(args[0], str):
args = (args[0].split(),) + args[1:]
return super(UserSet, cls).__new__(cls, *args)
print(UserSet('I am a boy'))
>>>UserSet({'boy', 'a', 'am', 'I'})
class ShapeFactory():
shapes={'A':A, 'B':B}
def __new__(cls, type_):
if type_ in cls.shapes:
return cls.shapes[type_]()
else:
raise UnkonwnTypeError
b = ShapeFactory('B')
初始化的 init 函数
LEGB
赋值语句
def len(a):
pass
class A():
pass
A.len = len
A().len()
多种方法调用类
A.m(a, 2)
a.m(2)
A.__dict__['m'](a, 2)
调用父类方法时
base_.method_(self, <arg_list>)
super(cls, self).method_(<arg_list>)
MRO: method resolution order方法解析顺序
古典类: 深度优先
新式类: C3
class C(A, B): pass
class D(B, A): pass
class E(C, D): pass
class Property():
def __init__(self, fget=None,...):
self.fget = fget
self.__doc__ = doc
def __get__(self, obj, objtype):
if obj is None:
return self
if self.fget is None:
rasie ...
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
raise ...
self.fset(obj, value)
def __delete__(self, obj):
if self.fdel is None:
raise ...
self.fdel(obj)
均可以用作 实例 属性的获取与拦截,非 类属性
注意事项
调用次序
class A():
_c = 'test'
def __init__(self):
self.x = None
@property
def a(self):
print('use property to get!')
if self.x is None:
print('return a when x is None!')
return 'a'
else:
if isinstance(self.x, int):
print('Error x is int', self.x)
raise AttributeError
else:
print('return x when is not int')
return self.x
@a.setter
def a(self, value):
self.x = value
def __getattr__(self, name):
print('getattr to get', name)
return str(self.x)
def __getattribute__(self, name):
print('getattribute to get', name)
return object.__getattribute__(self, name)
a1 = A()
print(a1.a)
print('----')
a1.a = 1
print(a1.a)
print('----')
a1.a = 'c'
print(a1.a)
print('----')
print(a1._c)
print('----')
print(A._c)
getattribute to get a
use property to get!
getattribute to get x
return a when x is None!
a
----
getattribute to get a
use property to get!
getattribute to get x
getattribute to get x
getattribute to get x
Error x is int 1
getattr to get a
getattribute to get x
1
----
getattribute to get a
use property to get!
getattribute to get x
getattribute to get x
return x when is not int
getattribute to get x
c
----
getattribute to get _c
test
----
test
x = property(get_v, set_v, del_v, doc)
@property @x.setter @x.deleter
优势
代码更简洁,可读性更强
obj.x += 1 # 简洁
obj.set_v(obj.get_v() + 1) # 复杂
更好的管理属性的访问
代码可维护性更好,对属性进行再包装,以接口形式呈现用户,以统一语法访问属性
元类
def dynamic_class():
class A():
pass
return A
A_ = dynamic_class()
type(A_) == <type, 'type'>
A = type('A', (<父类元组>), dict_<属性字典,名称和值>)
class Apython2:
__metaclass__ = MyTypeClass
pass
class Bpython3(metaclass=MyTypeClass):
pass
class TypeSetter():
def __init__(self, type):
self.type = type
def is_valid(self, value):
return isinstance(value, self.type)
class TypeCheckMeta(type):
def __new__(cls, name, bases, dict):
print('aloc class memory', dict) ## name,age等会在该dict中
return super(TypeCheckMeta, cls).__new__(cls, name, bases, dict)
def __init__(cls, name, bases, dict):
cls._fields = {}
for key, value in dict.items():
cls._fields[key] = value
class TypeCheck(metaclass=TypeCheckMeta):
def __setattr__(self, key, value):
if key in self._fields:
if not self._fields[key].is_valid(value):
raise Exception
super(TypeCheck, self).__setattr__(key, value)
class Test(TypeCheck):
name = TypeSetter(str) ### 该属性会被写入 dict 中然后调用元类
age = TypeSetter(int)
t = Test()
t.name = 'test'
t.age = '16'
元类选择
元类中定义的方法属于其创建的类的类方法,并不属于该类的对象
元类的使用场景
class Singleton(type):
def __init__(cls, name, bases, dic):
super(Singleton, cls).__init__(name, bases, dic)
cls.instance = None
def __call__(cls, *a, **kw):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*a, **kw)
return cls.instance
class MySingleton():
__metaclass__ = Singleton
注意点:
class M1(type): pass
class M2(type): pass
class C1(metaclass=M1): pass
class C2(metaclass=M2): pass
class C3(C1, C2): pass # 会产生异常,Python不能确认两个元类是否兼容
class M3(M1, M2): pass
class C4(metaclass=M3): pass #现在可以了
Python各种操作是通过各种预定义函数实现
pipe库实现原理
class Pipe():
def __init__(self, function):
self.function = function
def __ror__(self, other):
return self.function(other)
def __call__(self, *a, **kw):
return Pipe(lambda x: self.function(x, *a, **kw))
@Pipe
def where(iterable, predicate):
return (x for x in iterable if predicate(x))
fib() | take_while(lambda x: x < 10000) \
| where(lambda x: x%2) \
| sum()
解释:
迭代器协议:
# 消费者生成者实例
def consumer():
while True:
word = yield
print(word.upper())
def producter(line):
for word in line.split():
yield word
c = consumer()
p = producter('i am very okay')
next(c)
for word in p:
c.send(word)
全局解释器锁(GIL: Global Interpreter Lock)
while True:
A = Leak()
B = Leak()
A.b = B
B.a = A
A, B = None, None
gc.isenabled()
gc.get_threshold()
gc.collect() #手动调用垃圾清理
gc.garbage #返回由于循环引用而产生的不可达的垃圾对象的列表
如何看待代码审查