《编写高质量代码 改善Python程序的91个建议》读后程序学习小结
来源:互联网 发布:兼职网络维护 编辑:程序博客网 时间:2024/05/21 09:05
# coding=utf-8# Language Reference'''参考书:《编写高质量代码 改善Python程序的91个建议》张颖,赖勇浩 著 2014.6'''from __future__ import with_statement# assertx, y = 1, 1assert x == y, "not equals"# time计时的两种方式import timeitt = timeit.Timer('x,y=y,x','x=1;y=2')print(t.timeit()) # 0.110494892863import timet = time.time()sum = 0while True: sum += 1 if sum > 100000: breaktime.sleep(1)print(time.time()-t) # 1.02999997139# itertools 结合 yieldfrom itertools import islicedef fib(): a, b = 0, 1 while True: yield a a, b = b, a+bprint(list(islice(fib(),10))) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]# class 定义变量 和 nametuple 定义变量class Seasons: Sprint, Summer, Autumn, Winter = range(4)print(Seasons.Winter) # 3from collections import namedtupleSeasons0 = namedtuple('Seasons0','Spring Summer Autumn Winter')._make(range(4))print(Seasons0.Winter) # 3# isintance 可以设置多种类型的判断print(isinstance((2,3),(str, list, tuple))) # True# eval的漏洞,能够处理的范围太大,导致系统文件被读取,谨慎使用str0 = '__import__("os").system("dir")'eval(str0) # 2017/09/28 09:31 <DIR> 。。。# 生成器 yield 与 迭代器 iteritemsdef myenumerate(seq): n = -1 for elem in reversed(seq): yield len(seq) + n, elem n = n -1e = myenumerate([1,2,3,4,5])print(e.next()) # (4, 5)dict0 = {'1':1, '2':2}d = dict0.iteritems()print(d.next()) # ('1', 1)# 字符串驻留机制:对于较小的字符串,为了提高系统性能保留其值的一个副本,当创建新的字符串时直接指向该副本。a = 'hello'b = 'hello' # b 是 a 的引用print(id(a), id(b), a is b, a == b) # (53383488, 53383488, True, True)# 可变对象list 与 不可变对象strlist1 = [1,2,3]list2 = list1list3 = list1[:] # 浅拷贝list1.append(4)print(list1, list2, list3) # ([1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3]) - list2可变str1 = '123'str2 = str1str3 = str1[:]str1 += '4'print(str1, str2, str3) # ('1234', '123', '123') - str2不可变# 浅拷贝, 深拷贝# 浅拷贝和深拷贝的不同仅仅是对组合对象来说,# 所谓的组合对象就是包含了其它对象的对象,如列表,类实例。# 而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。# 浅拷贝: 创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)# 浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。# 深拷贝: 创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。# 深拷贝: 虽然实际上会共享不可变的子对象,但不影响它们的相互独立性。# 深拷贝只有一种方式:copy模块中的deepcopy函数。a = [[1,2]] # 组合对象import copyb = copy.copy(a)print(id(a), id(b), a is b, a == b) # (58740048, 59050864, False, True)for i, j in zip(a, b): print(id(i), id(j)) # (61090752, 61090752)子对象相同b = copy.deepcopy(a)print(id(a), id(b), a is b, a == b) # (58740048, 58737848, False, True)for i, j in zip(a, b): print(id(i), id(j)) # (61090752, 61071568)子对象不同# 再举一例class TestCopy(): def get_list(self, list0): self.list0 = list0 def change_list(self, str): self.list0 += str def print_list(self): print(self.list0)list0 = [1, 2, 3]a = TestCopy()a.get_list(list0)a.print_list() # [1, 2, 3]b = copy.copy(a) # 浅拷贝,子对象共享b.change_list('4')b.print_list() # [1, 2, 3, '4']a.print_list() # [1, 2, 3, '4']c = copy.deepcopy(a) # 深拷贝,子对象独立c.change_list('5')c.print_list() # [1, 2, 3, '4', '5']b.print_list() # [1, 2, 3, '4']a.print_list() # [1, 2, 3, '4']# 赋值操作a = [1, 2, 3]b = copy.copy(a) # 其实是赋值操作,不属于浅拷贝,赋值对象相互独立b.append(4)print(a, b) # ([1, 2, 3], [1, 2, 3, 4])# encode, decode, gbk, utf-8with open("test.txt", 'w') as f: f.write('python' + '中文测试')with open("test.txt", 'r') as f: # print(f.read()) # python中文测试 print((f.read().decode('utf-8')).encode('gbk')) # python���IJ���# --1 = 1 = ++1 = (1)print(+++1, ---1) # (1, -1)print (1), (1,) # 1 (1,)print(''.split(), ''.split(' ')) # ([], [''])# with 调用 class, 初始化调用__enter__,退出调用__exit__class MyContextManager(): def __enter__(self): print('entering...') def __exit__(self, exc_type, exc_val, exc_tb): print('leaving...') if exc_type is None: print('no exceptions') return False elif exc_type is ValueError: print('value error') return True else: print('other error') return Truewith MyContextManager(): print('Testing...') raise(ValueError) # entering... Testing... leaving... value error# else 结合 for 和 tryfor i in range(5): print(i),else: print('for_else') # 0 1 2 3 4 for_elsetry: print('try'),except: passelse: print('try_else') # try try_else# Nonea = Noneb = Noneprint(id(a), id(b), a is b, a==b) # (505354444, 505354444, True, True)a = 'a'b = u'b'print(isinstance(a,str), isinstance(b,unicode), isinstance(a, basestring), isinstance(b, basestring))# (True, True, True, True)# 对 class 操作,先调用 __init__()class A: def __nonzero__(self): print('A.__nonzero__()') return True def __len__(self): print('A.__len__()') return False def __init__(self): print('A.__init__()') self.name = 'I am A' def __str__(self): print('A.__str__()') return 'A.__str__{self.name}'.format(self=self)if A(): print('not empty') # A.__init__() A.__nonzero__() not emptyelse: print('empty')print(str(A())) # A.__init__() A.__str__() A.__str__I am A# 尽量采用''.join()(效率更高),而不是 str + strs1, s2 ,s3 = 'a', 'b', 'c'print(s1+s2+s3, ''.join([s1, s2, s3])) # ('abc', 'abc')# map 与 list 结合list0 = [('a','b'), ('c','d')]formatter = "choose {0[0]} and {0[1]}".formatfor item in map(formatter, list0): print(item) # choose a and b choose c and d# map 结合 typeproduct_info = '1-2-3'a, b, c = map(int, product_info.split('-'))print(a, b, c) # (1, 2, 3)# 格式化输出,尽量采用 format,采用 %s 输出元组时需要加逗号itemname = list0[0] + list0[1]print(itemname) # ('a', 'b', 'c', 'd')print('itemname is %s' % (itemname,)) # 必须有个逗号 itemname is ('a', 'b', 'c', 'd')print('itemname is {}'.format(itemname)) # itemname is ('a', 'b', 'c', 'd')# 格式化输出 %2.5f,小数点后5位优先级高print('data: %6.3f' % 123.456789123) # data: 123.457print('data: %2.5f' % 123.456789123) # data: 123.45679# class传参:__init__ 中传入可变对象 - 会在子类中继承该可变对象的值class ChangeA(): def __init__(self, list0 = []): # mutable 可变 self.list0 = list0 def addChange(self, content): self.list0.append(content)a = ChangeA()a.addChange('add change')b = ChangeA()print(a.list0, b.list0) # (['add change'], ['add change'])# 函数传参:传对象或对象的引用。若可变对象 - 共享, 若不可变对象 - 生成新对象后赋值def inc(n, list0): n = n + 1 list0.append('a')n = 3list0 = [1]inc(n, list0)print(n, list0) # (3, [1, 'a'])# 子类继承父类,传参举例class Father(): def print_fa(self): print(self.total) def set(self, total): self.total = totalclass SonA(Father): passclass SonB(Father): passa = SonA()a.set([1])a.print_fa() # [1]b = SonB()b.set([2])b.print_fa() # [2]# 在需要生成列表的时候使用列表解析# 对于大数据处理不建议用列表解析,过多的内存消耗会导致MemoryErrorprint([(a,b) for a in [1,2,3] for b in [2,3,4] if a != b])# [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 2), (3, 4)]# class 中的 装饰符 :类方法,静态方法,实例方法class CS(): def instance_method(self,x): print(x) @classmethod def class_method(cls,x): print('class',x) @staticmethod def static_method(x): print('static',x)CS().instance_method(1) # 1CS().class_method(2) # ('class', 2)CS().static_method(3) # ('static', 3)# itemgetter 字典排序,输出为元组dict0 = {'a':1, 'c':3, 'b':2}from operator import itemgetterprint(sorted(dict0.viewitems(), key = itemgetter(1))) # [('a', 1), ('b', 2), ('c', 3)]# Counter 计数from collections import Counterprint(Counter('success')) # Counter({'s': 3, 'c': 2, 'e': 1, 'u': 1})# 配置文件:优点:不需修改代码,改变程序行为,继承[DEFAULT]属性with open('format.conf', 'w') as f: f.write('[DEFAULT]' + '\n') f.write('conn_str = %(dbn)s://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s' + '\n') f.write('dbn = mysql' + '\n') f.write('user = root' + '\n') f.write('host = localhost' + '\n') f.write('port = 3306' + '\n') f.write('[db1]' + '\n') f.write('user = aaa' + '\n') f.write('pw = ppp' + '\n') f.write('db = example1' + '\n') f.write('[db2]' + '\n') f.write('host = 192.168.0.110' + '\n') f.write('pw = www' + '\n') f.write('db = example2' + '\n')from ConfigParser import ConfigParserconf = ConfigParser()conf.read('format.conf')print(conf.get('db1', 'conn_str')) # mysql://aaa:ppp@localhost:3306/example1print(conf.get('db2', 'conn_str')) # mysql://root:www@192.168.0.110:3306/example2# pandas - 大文件(1G)读取操作 - 需要安装 pandasf = open('large.csv', 'wb')f.seek(1073741824 - 1)f.write('\0')f.close()import osprint(os.stat('large.csv').st_size) # 1073741824import csvwith open('large.csv', 'rb') as csvfile: mycsv = csv.reader(csvfile, delimiter = ';') # for row in mycsv: # MemoryError # print(row)# import pandas as pd# reader = pd.read_table('large.csv', chunksize = 10, iterator = True)# iter(reader).next()# 序列化:把内存中的数据结构在不丢失其身份和类型信息的情况下,转成对象的文本或二进制表示。# pickle, json, marshal, shelveimport cPickle as picklemy_data = {'a':1, 'b':2, 'c':3}fp = open('picklefile.dat', 'wb')pickle.dump(my_data, fp) # class - __getstate__(self)fp.close()fp = open('picklefile.dat', 'rb')out = pickle.load(fp) # class - __setstate__(self, state)fp.close()print(out) # {'a': 1, 'c': 3, 'b': 2}pickle.loads("cos\nsystem\n(S'dir'\ntR.") # 列出当前目录下所有文件,不安全 - 解决:继承类并定制化内容# 编码器 json.JSONEncodertry: import simplejson as jsonexcept ImportError: import jsonimport datetimed = datetime.datetime.now()d1 = d.strftime('%Y-%m-%d %H:%M:%S')print(d1, json.dumps(d1, cls = json.JSONEncoder)) # 也可以继承修改指定编码器json.JSONEncoder# ('2017-09-28 11:00:46', '"2017-09-28 11:00:46"')# traceback:出错时查看 调用栈import sysprint(sys.getrecursionlimit()) # 最大递归深度:1000import tracebacktry: a = [1] print(a[1])except IndexError as ex: print(ex) # list index out of range # traceback.print_exc() # 会导致程序中断tb_type, tb_val, exc_tb = sys.exc_info()for filename, linenum, funcname, source in traceback.extract_tb(exc_tb): print("%-33s:%s '%s' in %s()" % (filename, linenum, source, funcname)) # H:/python/suggest0928.py :353 'print(a[1])' in <module>()# LOG的五个等级:DEBUG, INFO, WARNING(默认), ERROR, CRITICAL# Logger, Handler, Formatter, Filterimport logginglogging.basicConfig( level = logging.DEBUG, filename = 'log.txt', filemode = 'w', format = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',)logger = logging.getLogger()logger.info('[INFO]:I am a tester')logger.debug('test logging module')logger.error('this is error')logger.critical('this is critical')# thread: 多线程底层支持,以低级原始的方式处理和控制线程,较复杂# threading: 基于thread,操作对象化,提供丰富特性import threadingimport timedef myfunc(a, delay): print('calculate %s after %s' % (a, delay)) time.sleep(delay) print('begin') res = a*a print('result:', res) return rest1 = threading.Thread(target = myfunc, args = (2, 5))t2 = threading.Thread(target = myfunc, args = (6, 8))print(t1.isDaemon()) # False 守护线程,默认Falseprint(t2.isDaemon())# t2.setDaemon(True) # True 表示 线程全部执行完成后,主程序才会退出t1.start()t2.start()# lock, mutex, condition, event, with lock, put,get# 生产者消费者模型import Queueimport threadingimport randomwrite_lock = threading.Lock()class Producer(threading.Thread): def __init__(self, q, con, name): super(Producer, self).__init__() self.q = q self.name = name self.con = con print('Producer ', self.name, ' started') def run(self): while(1): global write_lock # self.con.acquire() if self.q.full(): with write_lock: print('Queue is full, producer wait') # self.con.wait() else: value = random.randint(0,10) with write_lock: print(self.name, 'put value:', self.name+':'+str(value), 'into queue') self.q.put(self.name+':'+str(value)) # self.con.notify() # self.con.release()class Consumer(threading.Thread): def __init__(self, q, con, name): super(Consumer, self).__init__() self.q = q self.name = name self.con = con print('Consumer ', self.name, ' started') def run(self): while(1): global write_lock # self.con.acquire() if self.q.empty(): with write_lock: print('Queue is empty, consumer wait') # self.con.wait() else: value = self.q.get() with write_lock: print(self.name, 'get value:', value, 'from queue') # self.con.notify() # self.con.release()q = Queue.Queue(10) # 先进先出,循环队列大小10con = threading.Condition()p1 = Producer(q, con, 'P1')p2 = Producer(q, con, 'P2')c1 = Consumer(q, con, 'C1')p1.setDaemon(False)p2.setDaemon(False)c1.setDaemon(False)# p1.setDaemon(True)# p2.setDaemon(True)# c1.setDaemon(True)# p1.start()# p2.start()# c1.start()'''设计模式,静态语言风格单例模式,保证系统中一个类只有一个实例而且该实例易于被外界访模板方法:在一个方法中定义一个算法的骨架,并将一些事先步骤延迟到子类中。 子类在不改变算法结构的情况下,重新定义算法中的某些步骤。 混入mixins模式:基类在运行中可以动态改变(动态性)。'''# 发布 publish 订阅 subscribe 松散耦合 - 中间代理人 Broker# blinker - python-message# 库函数:关注日志产生,不关注日志输出;# 应用:关注日志统一放置,不关注谁产生日志。from collections import defaultdictroute_table = defaultdict(list)def sub(topic, callback): if callback in route_table[topic]: return route_table[topic].append(callback)def pub(topic, *a, **kw): for func in route_table[topic]: func(*a, **kw)def greeting(name): print('hello, %s' % name)sub('greet', greeting) # 订阅的时候将待调用的greeting放入dict中pub('greet', 'tester') # hello, tester 发布的时候调用greeting函数# 类的状态转移,例,当telnet\注册成功后,就不再需要登录\注册了。def workday(): print('work hard')def weekend(): print('play harder')class People(): passpeople = People()while True: for i in range(1,8,1): if i == 6: people.day = weekend if i == 1: people.day = workday people.day() break# 工厂模式# __init__(): 在类对象创建好后,进行变量的初始化# __new__(): 创建实例,类的构造方法,需要返回object.__new__()class TestMode(object): def __init__(self): print('i am father') def test(self): print('test is father')class A(TestMode): def __init__(self): print('i am A') def test(self): print('test is A')class B(TestMode): def __init__(self): print('i am B') def test(self): print('test is B')class FactoryTest(object): content = {'a':A, 'b':B} def __new__(cls, name): if name in FactoryTest.content.keys(): print('create old %s' % name) return FactoryTest.content[name]() else: print('create new %s' % name) return TestMode()FactoryTest('a').test() # create old a - i am A - test is AFactoryTest('A').test() # create new A - i am father - test is father# 局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域a = 1def foo(x): global a a = a * x def bar(): global a b = a * 2 a = b + 1 print(a) return bar()foo(1) # 3# self 隐式传递 -- 显式 优于 隐式# 当子类覆盖了父类的方法,但仍然想调用父类的方法class SelfTest(): def test(self): print('self test')SelfTest.test(SelfTest()) # self testassert id(SelfTest.__dict__['test']) == id(SelfTest.test.__func__)# 古典类 classic classclass A: pass# 新式类 new style classclass B(object): passclass D(dict): pass# 元类 metaclassclass C(type): passa = Ab = B()c = C(str)d = D()print(type(a)) # <type 'classobj'>print(b.__class__, type(b)) # (<class '__main__.B'>, <class '__main__.B'>)print(c.__class__, type(c)) # (<type 'type'>, <type 'type'>)print(d.__class__, type(d)) # (<class '__main__.D'>, <class '__main__.D'>)# 菱形继承 - 应避免出现try: class A(object): pass class B(object): pass class C(A, B): pass class D(B, A): pass class E(C, D): passexcept: print('菱形继承 - '+'order (MRO) for bases B, A')# __dict__[] 描述符,实例调用方法为bound,类调用方法为unboundclass MyClass(object): def my_method(self): print('my method')print(MyClass.__dict__['my_method'], MyClass.my_method)# (<function my_method at 0x03B62630>, <unbound method MyClass.my_method>)print(MyClass.__dict__['my_method'](MyClass()), MyClass.my_method(MyClass()))a = MyClass()print(a.my_method, MyClass.my_method)# (<bound method MyClass.my_method of <__main__.MyClass object at 0x038D3650>>, <unbound method MyClass.my_method>)print(a.my_method.im_self, MyClass.my_method.im_self)# (<__main__.MyClass object at 0x0391D650>, None)# __getattribute__()总会被调用,而__getattr__()只有在__getattribute__()中引发异常的情况下才会被调用class AA(object): def __init__(self, name): self.name = name self.x = 20 def __getattr__(self, name): print('call __getattr__:', name) if name == 'z': return self.x ** 2 elif name == 'y': return self.x ** 3 def __getattribute__(self, attr): print('call __getattribute__:', attr) try: return super(AA, self).__getattribute__(attr) except KeyError: return 'default'a = AA("attribute")print(a.name) # attributeprint(a.z) # 400if hasattr(a, 'test'): # 动态添加了 test 属性,但不会在 __dict__ 中显示 c = a.test print(c) # Noneelse: print('instance a has no attribute t')print(a.__dict__) # {'x': 20, 'name': 'attribute'} 没有‘test’# 数据描述符:一个对象同时定义了__get__()和__set__()方法,高级 - property装饰符# 普通描述符:一种较为低级的控制属性访问机制class Some_Class(object): _x = None def __init__(self): self._x = None @property def x(self): return self._x @x.setter def x(self, value): self._x = value @x.getter def x(self): return self._x @x.deleter def x(self): del self._xobj = Some_Class()obj.x = 10print(obj.x + 2) # 12print(obj.__dict__) # {'_x': 10}del obj.xprint(obj.x) # Noneprint(obj.__dict__) # {}# metaclass元类是类的模板,元类的实例为类# 当你面临一个问题还在纠结要不要使用元类时,往往会有其他更为简单的解决方案# 元方法可以从元类或者类中调用,不能从类的实例中调用。# 类方法可以从类中调用,也可以从类的实例中调用class TypeSetter(object): def __init__(self, fieldtype): print('TYpeSetter __init__', fieldtype) self.fieldtype = fieldtype def is_valid(self, value): return isinstance(value, self.fieldtype)class TypeCheckMeta(type): # type为父类,是对type的重写,作为一个元类 def __new__(cls, name, bases, dict): print('TypeCheckMeta __new__', name, bases, dict) return super(TypeCheckMeta, cls).__new__(cls, name, bases, dict) def __init__(self, name, bases, dict): self._fields = {} for key,value in dict.items(): if isinstance(value, TypeSetter): self._fields[key] = value def sayHi(cls): print('HI')class TypeCheck(object): __metaclass__ = TypeCheckMeta # 所有继承该类的子类都将使用元类来指导类的生成 # 若未设置__metaclass__,使用默认的type元类来生成类 def __setattr__(self, key, value): print('TypeCheck __setattr__') if key in self._fields: if not self._fields[key].is_valid(value): raise TypeError('Invalid type for field') super(TypeCheck, self).__setattr__(key, value)class MetaTest(TypeCheck): # 由元类 TypeCheckMeta 指导生成 name = TypeSetter(str) num = TypeSetter(int)mt = MetaTest()mt.name = 'apple'mt.num = 100MetaTest.sayHi() # 元方法可以从元类或者类中调用,不能从类的实例中调用。# ('TypeCheckMeta __new__', 'TypeCheck', (<type 'object'>,), {'__module__': '__main__', '__metaclass__': <class '__main__.TypeCheckMeta'>, '__setattr__': <function __setattr__ at 0x0393DA70>})# ('TYpeSetter __init__', <type 'str'>)# ('TYpeSetter __init__', <type 'int'>)# ('TypeCheckMeta __new__', 'MetaTest', (<class '__main__.TypeCheck'>,), {'__module__': '__main__', 'num': <__main__.TypeSetter object at 0x03951D50>, 'name': <__main__.TypeSetter object at 0x03951CF0>})# TypeCheck __setattr__# TypeCheck __setattr__# HI# 协议:一种松散的约定,没有相应的接口定义。# 迭代器:统一的访问容器或集合 + 惰性求值 + 多多使用,itertoolsfrom itertools import *# print(''.join(i) for i in product('AB', repeat = 2))for i in product('ABCD', repeat = 2): print(''.join(i)), # AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DDprintfor i in combinations('ABCD', 2): # AB AC AD BC BD CD print(''.join(i)),print# 生成器:按一定的算法生成一个序列。# 生成器函数:使用了 yield,返回一个迭代器,以生成器的对象放回。def fib(n): a, b = 1, 1 while a < n: test = (yield a) print('test:', test) a, b = b, a+bfor i, f in enumerate(fib(10)): print(f), # 1 1 2 3 5 8# 调用生成器函数时,函数体并不执行,当第一次调用next()方法时才开始执行,并执行到yield表达式后中止。generator = fib(10)print(generator, generator.next(), generator.next()) # (<generator object fib at 0x03A39EB8>, 1, 1)print(generator.send(3)) # ('test:', 3)# yield 与 上下文管理器 结合from contextlib import contextmanager@contextmanagerdef tag(name): print('<%s>' % name) yield print('<%s>' % name)with tag('hi'): print('hello')# <hi># hello# <hi># GIL : Global Interpreter Lock 全局解释器锁# sys.setcheckinterval 自动线程间切换,默认每隔100个时钟# 单核上的多线程本质上是顺序执行的# 多核的效率比较低,考虑 multiprocessing'''无论使用何种语言开发,无论开发的是何种类型,何种规模的程序,都存在这样一点相同之处。即:一定比例的内存块的生存周期都比较短,通常是几百万条机器指令的时间,而剩下的内存块,起生存周期比较长,甚至会从程序开始一直持续到程序结束。'''# 引用计数算法 - 无法解决循环引用问题 - 设置threshold阈值 gc 模块import gcprint(gc.isenabled()) # Trueprint(gc.get_threshold()) # (700, 10, 10)print(gc.garbage) # []# 循环引用可以使一组对象的引用计数不为0,然而这些对象实际上并没有被任何外部对象所引用,# 它们之间只是相互引用。这意味着不会再有人使用这组对象,应该回收这组对象所占用的内存空间,# 然后由于相互引用的存在,每一个对象的引用计数都不为0,因此这些对象所占用的内存永远不会被释放。a = []b = []a.append(b)b.append(a)print(a, b) # ([[[...]]], [[[...]]])# python解决方案:当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,# 而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,# 而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。# 在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,# 当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。# 在Python中,总共有3“代”,也就是Python实际上维护了3条链表# PyPI : Python Package Index - Python包索引# https://pypi.python.org/pypi/{package}# python setup.py install# PyUnit unittest模块 - 测试代码先于被测试的代码,更有利于明确需求。# import unittest# unittest.main()# 使用 Pylint 检查代码风格# 代码审查工具:review board# 将包发布到PyPI,供下载使用 - 这个流程需要走一遍# 代码优化:# 优先保证代码是可工作的# 权衡优化的代价# 定义性能指标,集中力量解决首要问题# 不要忽略可读性# 定位性能瓶颈问题 - CProfileimport cProfiledef foo(): sum = 0 for i in range(100): sum += i return sumcProfile.run('foo()') # 针对 foo() 函数的运行时间分布统计# 算法的评价 = 时间复杂度(重点) + 空间复杂度(硬件),一般采用以空间换时间的方法# O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(cn)<O(n!)<O(nn)# 循环优化:减少循环过程中的计算量,将内层计算提到上一层# 使用不同的数据结构优化性能# 列表 list# 栈和队列 deque# heapify()将序列容器转化为堆 heapqimport heapqimport randomlist0 = [random.randint(0,100) for i in range(10)]print(list0) #[55, 62, 17, 56, 82, 45, 87, 48, 65, 32]heapq.heapify(list0)print(list0) # [17, 32, 45, 48, 62, 55, 87, 56, 65, 82]import arraya = array.array('c', 'string')print(a.tostring()) # stringimport sysprint(sys.getsizeof(a)) # 28print(sys.getsizeof(list('string'))) # 72import timeitt = timeit.Timer("''.join(list('string'))")print(t.timeit()) # 0.688437359057t = timeit.Timer("a.tostring()", "import array; a = array.array('c', 'string')")print(t.timeit()) # 0.163860804606# set 集合的使用list0 = [i for i in range(10)]list1 = [i for i in range(20)]print(set(list0)&set(list1)) # set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])# 进程同步:multiprocessing - Pipe, Queue - 解决多核下的GIL效率问题# 线程同步:threading - Lock, Event, Condition, Semaphore# 线程的生命周期:创建,就绪,运行,阻塞,终止# 避免多次创建线程 - 线程池 threadpool
阅读全文
0 0
- 《编写高质量代码 改善Python程序的91个建议》读后程序学习小结
- 编写高质量代码 改善Python程序的91个建议
- 『编写高质量代码——改善 Python 程序的 91 个建议』
- 【备注】【C42】《编写高质量代码:改善Python程序的91个建议》PDF
- 《编写高质量代码改善C#程序的157个建议》学习
- 编写高质量代码:改善Java程序的151个建议-学习笔记(1-4章)
- 编写高质量代码:改善Java程序的151个建议-学习笔记(5-8章)
- 编写高质量代码:改善Java程序的151个建议-学习笔记(9-12章)
- 编写高质量代码:改善Java程序的151个建议-学习笔记(1-4章)
- 读编写高质量代码--改善java程序的151个建议笔记
- 读-秦小波-编写高质量代码:改善java程序的151个建议
- 读-秦小波-编写高质量代码:改善java程序的151个建议
- 读《编写高质量代码改善python的91个建议》笔记 建议7:
- 《编写高质量代码:改善Java程序的151个建议》 建议1
- 《编写高质量代码:改善Java程序的151个建议》 建议2
- 《编写高质量代码:改善Java程序的151个建议》 建议3
- 《编写高质量代码:改善Java程序的151个建议》 建议4
- 《编写高质量代码:改善Java程序的151个建议》 建议5
- tomcat 多实例部署
- 我的第一篇博客
- Python:入门到实现网络爬虫 Day3
- bzoj2654 tree(kruskal+二分)
- 软件过程改进笔记(9/28 )-----第一章
- 《编写高质量代码 改善Python程序的91个建议》读后程序学习小结
- ubuntu关机卡死
- spring mvc 环境Jackson转换器jsonp请求=方式2
- --author 'yidasanqian' is not 'Name <email>' and matches no existing author
- [Linux] 总结各系统 添加路由
- EasyTCP
- 如何在OneNote 4 mac上添加Notebook
- Spring的依赖注入方式
- nodejs做服务端多功能的简单实现