@spiritnotes
2016-01-31T09:20:08.000000Z
字数 20760
阅读 7197
Python 读书笔记
如何使用常量
#filename const.pyclass _const:def __setattr__(self, name, value):if name in self.__dict__:#禁止修改raise Exceptionif not name.isupper():#要求必须大写raise Exceptionself.__dict__[name] = valueimport syssys.modules[__name__] = _const()
使用
import constconst.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 aa != a
# coding=utf-8#-*- coding:utf-8 -*-
import原理
1. 搜索sys.modules是否已经存在该模块
2. 未找到,为模块创建字典对象插入sys.modules
3. 根据需要对模块对应文件进行编译
4. 执行动态加载,在当前模块的命名空间执行编译后的字节码,并将其中所有的对象放入模块对应的字典中
from...import的缺点
- 命名空间冲突
- 循环嵌套导入
#c1.pyfrom c2 import gdef x():pass
#c2.pyfrom c1 import xdef 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.contextmanagerdef work():print('First part!')yieldprint('last part!')with work():print('middle part')
## whilewhile True:passelse: #break未执行时执行else语句,循环自然结束pass## forfor i in range(x):passelse: #break未执行时执行else语句,循环自然结束pass## trytry:passexcept:passelse: #未抛出异常时执行else语句pass
while True:try:k = 1/0finally:break #导致丢失异常,没有break则异常会被重新抛出
def test(n):try:if n <= 0: raise Exceptionelse: return nfinally:return -99test(-1) # 返回 -99test(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())# 多维listl =[ ['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 jsonexcept ImportError:import json
# 继承并重写 runclass MyThread(thread.Thread):def run(self):pass# 调用对象创建传入 可执行对象thread_ = threading.Thread(fuc_)
Queue本身是线程安全的
class _Singleton:passSingleton = _Singleton()del _Singleton_Singleton_class = Singleton.\_\_class\_\_
class Singleton():_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)return cls._instances1 = 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.pyfrom collections import defaultdictclass Broker():route_table = defaultdict(list)def sub(self, topic, callback):if callback in route_table[topic]:returnroute_table[topic].append(callback)def pub(self, topc, *a, **kw):for func in route_table[topic]:func(*a, **kw)## usedef greeting(name):print(name, ' hello ')broker.sub('greet', greeting)broker.pub('are you ok')
状态模式: 当一个对象的内在状态改变时允许改变其行为,但这个对象看上去像改变了其类。主要用于控制一个对象的状态的条件表达式过于复杂的情况,其可把状态的判断逻辑转移到表示不同状态的一系列类中,进而把复杂的判断逻辑简化
def workday() : passdef weekday() : passpeople = People()while True:for i in range(1, 8):if i == 6:people.day = workdayif i == 1:people.day = weekday
@statefulclass People():class Workday(State):default = True@behaviordef day(self): passclass Weekday(State):@behavior # 为静态函数,self是指的peopledef day(self): passpeople = 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 UnkonwnTypeErrorb = ShapeFactory('B')
初始化的 init 函数
LEGB
赋值语句
def len(a):passclass A():passA.len = lenA().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): passclass D(B, A): passclass E(C, D): pass
class Property():def __init__(self, fget=None,...):self.fget = fgetself.__doc__ = docdef __get__(self, obj, objtype):if obj is None:return selfif 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@propertydef 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 AttributeErrorelse:print('return x when is not int')return self.x@a.setterdef a(self, value):self.x = valuedef __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 = 1print(a1.a)print('----')a1.a = 'c'print(a1.a)print('----')print(a1._c)print('----')print(A._c)getattribute to get ause property to get!getattribute to get xreturn a when x is None!a----getattribute to get ause property to get!getattribute to get xgetattribute to get xgetattribute to get xError x is int 1getattr to get agetattribute to get x1----getattribute to get ause property to get!getattribute to get xgetattribute to get xreturn x when is not intgetattribute to get xc----getattribute to get _ctest----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():passreturn AA_ = dynamic_class()type(A_) == <type, 'type'>
A = type('A', (<父类元组>), dict_<属性字典,名称和值>)
class Apython2:__metaclass__ = MyTypeClasspassclass Bpython3(metaclass=MyTypeClass):pass
class TypeSetter():def __init__(self, type):self.type = typedef 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] = valueclass TypeCheck(metaclass=TypeCheckMeta):def __setattr__(self, key, value):if key in self._fields:if not self._fields[key].is_valid(value):raise Exceptionsuper(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 = Nonedef __call__(cls, *a, **kw):if cls.instance is None:cls.instance = super(Singleton, cls).__call__(*a, **kw)return cls.instanceclass MySingleton():__metaclass__ = Singleton
注意点:
class M1(type): passclass M2(type): passclass C1(metaclass=M1): passclass C2(metaclass=M2): passclass C3(C1, C2): pass # 会产生异常,Python不能确认两个元类是否兼容class M3(M1, M2): passclass C4(metaclass=M3): pass #现在可以了
Python各种操作是通过各种预定义函数实现
pipe库实现原理
class Pipe():def __init__(self, function):self.function = functiondef __ror__(self, other):return self.function(other)def __call__(self, *a, **kw):return Pipe(lambda x: self.function(x, *a, **kw))@Pipedef 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 = yieldprint(word.upper())def producter(line):for word in line.split():yield wordc = 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 = BB.a = AA, B = None, None
gc.isenabled()gc.get_threshold()gc.collect() #手动调用垃圾清理gc.garbage #返回由于循环引用而产生的不可达的垃圾对象的列表
如何看待代码审查