《编写高质量代码 改善Python程序的91个建议》

《编写高质量代码 改善Python程序的91个建议》读后程序学习小结 - BigDeng_2014的专栏 - CSDN博客


# coding=utf-8
# Language Reference
'''
参考书:《编写高质量代码 改善Python程序的91个建议》张颖,赖勇浩 著 2014.6
''' from __future__ import with_statement # assert
x, y = 1, 1
assert x == y, "not equals" # time计时的两种方式
import timeit
t = timeit.Timer('x,y=y,x','x=1;y=2')
print(t.timeit()) # 0.110494892863
import time
t = time.time()
sum = 0
while True:
sum += 1
if sum > 100000:
break
time.sleep(1)
print(time.time()-t) # 1.02999997139 # itertools 结合 yield
from itertools import islice
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
print(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) # 3
from collections import namedtuple
Seasons0 = 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 与 迭代器 iteritems
def myenumerate(seq):
n = -1
for elem in reversed(seq):
yield len(seq) + n, elem
n = n -1
e = 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 与 不可变对象str
list1 = [1,2,3]
list2 = list1
list3 = list1[:] # 浅拷贝
list1.append(4)
print(list1, list2, list3) # ([1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3]) - list2可变
str1 = '123'
str2 = str1
str3 = str1[:]
str1 += '4'
print(str1, str2, str3) # ('1234', '123', '123') - str2不可变 # 浅拷贝, 深拷贝
# 浅拷贝和深拷贝的不同仅仅是对组合对象来说,
# 所谓的组合对象就是包含了其它对象的对象,如列表,类实例。
# 而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。
# 浅拷贝: 创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)
# 浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。
# 深拷贝: 创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。
# 深拷贝: 虽然实际上会共享不可变的子对象,但不影响它们的相互独立性。
# 深拷贝只有一种方式:copy模块中的deepcopy函数。
a = [[1,2]] # 组合对象
import copy
b = 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-8
with 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 True
with MyContextManager():
print('Testing...')
raise(ValueError) # entering... Testing... leaving... value error # else 结合 for 和 try
for i in range(5):
print(i),
else:
print('for_else') # 0 1 2 3 4 for_else
try:
print('try'),
except:
pass
else:
print('try_else') # try try_else # None
a = None
b = None
print(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 empty
else:
print('empty')
print(str(A())) # A.__init__() A.__str__() A.__str__I am A # 尽量采用''.join()(效率更高),而不是 str + str
s1, 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]}".format
for item in map(formatter, list0):
print(item) # choose a and b choose c and d
# map 结合 type
product_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.457
print('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 = 3
list0 = [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 = total
class SonA(Father):
pass
class SonB(Father):
pass
a = SonA()
a.set([1])
a.print_fa() # [1]
b = SonB()
b.set([2])
b.print_fa() # [2] # 在需要生成列表的时候使用列表解析
# 对于大数据处理不建议用列表解析,过多的内存消耗会导致MemoryError
print([(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) # 1
CS().class_method(2) # ('class', 2)
CS().static_method(3) # ('static', 3) # itemgetter 字典排序,输出为元组
dict0 = {'a':1, 'c':3, 'b':2}
from operator import itemgetter
print(sorted(dict0.viewitems(), key = itemgetter(1))) # [('a', 1), ('b', 2), ('c', 3)] # Counter 计数
from collections import Counter
print(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 ConfigParser
conf = ConfigParser()
conf.read('format.conf')
print(conf.get('db1', 'conn_str')) # mysql://aaa:ppp@localhost:3306/example1
print(conf.get('db2', 'conn_str')) # mysql://root:www@192.168.0.110:3306/example2 # pandas - 大文件(1G)读取操作 - 需要安装 pandas
f = open('large.csv', 'wb')
f.seek(1073741824 - 1)
f.write('\0')
f.close()
import os
print(os.stat('large.csv').st_size) # 1073741824
import csv
with 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, shelve
import cPickle as pickle
my_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.JSONEncoder
try:
import simplejson as json
except ImportError:
import json
import datetime
d = 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 sys
print(sys.getrecursionlimit()) # 最大递归深度:1000
import traceback
try:
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, Filter
import logging
logging.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 threading
import time
def myfunc(a, delay):
print('calculate %s after %s' % (a, delay))
time.sleep(delay)
print('begin')
res = a*a
print('result:', res)
return res
t1 = threading.Thread(target = myfunc, args = (2, 5))
t2 = threading.Thread(target = myfunc, args = (6, 8))
print(t1.isDaemon()) # False 守护线程,默认False
print(t2.isDaemon())
# t2.setDaemon(True) # True 表示 线程全部执行完成后,主程序才会退出
t1.start()
t2.start() # lock, mutex, condition, event, with lock, put,get
# 生产者消费者模型
import Queue
import threading
import random
write_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) # 先进先出,循环队列大小10
con = 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 defaultdict
route_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(): pass
people = 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 A
FactoryTest('A').test() # create new A - i am father - test is father # 局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域
a = 1
def 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 test
assert id(SelfTest.__dict__['test']) == id(SelfTest.test.__func__) # 古典类 classic class
class A: pass
# 新式类 new style class
class B(object): pass
class D(dict): pass
# 元类 metaclass
class C(type): pass
a = A
b = 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): pass
except:
print('菱形继承 - '+'order (MRO) for bases B, A') # __dict__[] 描述符,实例调用方法为bound,类调用方法为unbound
class 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) # attribute
print(a.z) # 400
if hasattr(a, 'test'): # 动态添加了 test 属性,但不会在 __dict__ 中显示
c = a.test
print(c) # None
else:
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._x
obj = Some_Class()
obj.x = 10
print(obj.x + 2) # 12
print(obj.__dict__) # {'_x': 10}
del obj.x
print(obj.x) # None
print(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 = 100
MetaTest.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 # 协议:一种松散的约定,没有相应的接口定义。
# 迭代器:统一的访问容器或集合 + 惰性求值 + 多多使用,itertools
from 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 DD
print
for 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+b
for 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
@contextmanager
def 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 gc
print(gc.isenabled()) # True
print(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,供下载使用 - 这个流程需要走一遍
# 代码优化:
# 优先保证代码是可工作的
# 权衡优化的代价
# 定义性能指标,集中力量解决首要问题
# 不要忽略可读性
# 定位性能瓶颈问题 - CProfile
import cProfile
def foo():
sum = 0
for i in range(100):
sum += i
return sum
cProfile.run('foo()') # 针对 foo() 函数的运行时间分布统计 # 算法的评价 = 时间复杂度(重点) + 空间复杂度(硬件),一般采用以空间换时间的方法
# O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(cn)<O(n!)<O(nn) # 循环优化:减少循环过程中的计算量,将内层计算提到上一层
# 使用不同的数据结构优化性能
# 列表 list
# 栈和队列 deque
# heapify()将序列容器转化为堆 heapq
import heapq
import random
list0 = [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 array
a = array.array('c', 'string')
print(a.tostring()) # string
import sys
print(sys.getsizeof(a)) # 28
print(sys.getsizeof(list('string'))) # 72
import timeit
t = timeit.Timer("''.join(list('string'))")
print(t.timeit()) # 0.688437359057
t = 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

改善python程序的建议[转]的更多相关文章

  1. 编写高质量代码--改善python程序的建议(六)

    原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...

  2. 编写高质量代码--改善python程序的建议(八)

    原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...

  3. 编写高质量代码--改善python程序的建议(七)

    原文发表在我的博客主页,转载请注明出处! 建议三十四:掌握字符串的基本用法 编程有两件事,一件是处理数值,另一件是处理字符串,在商业应用编程来说,处理字符串的代码超过八成,所以需要重点掌握. 首先有个 ...

  4. 编写高质量代码–改善python程序的建议(五)

    原文发表在我的博客主页,转载请注明出处! 建议二十三:遵循异常处理的几点基本原则 python中常用的异常处理语法是try.except.else.finally,它们可以有多种组合,语法形式如下: ...

  5. 编写高质量代码--改善python程序的建议(四)

    原文发表在我的博客主页,转载请注明出处! 建议十八:有节制的使用from...import语句 python提供了三种方式引入外部模块: import语句 from...import... __imp ...

  6. 编写高质量代码--改善python程序的建议(三)

    原文发表在我的博客主页,转载请注明出处! 建议十三:警惕eval()的安全漏洞 相信经常处理文本数据的同学对eval()一定是欲罢不能,他的使用非常简单: eval("1+1==2" ...

  7. 编写高质量代码–改善python程序的建议(二)

    原文发表在我的博客主页,转载请注明出处! 建议七:利用assert语句来发现问题断言(assert)在很多语言中都存在,它主要为调试程序服务,能够快速方便地检查程序的异常或者发现不恰当的输入等,可防止 ...

  8. 编写高质量代码--改善python程序的建议(一)

    原文发表在我的博客主页,转载请注明出处! 初衷 python是一个入门十分容易的编程语言,但是想要写好python却是一件不容易的事情,如果不是专业使用python的人,只是将python作为一个脚本 ...

  9. (转)4年python,总结一些改善Python程序的建议

    自己写Python也有四五年了,一直是用自己的"强迫症"在维持自己代码的质量.都有去看Google的Python代码规范,对这几年的工作经验,做个简单的笔记,如果你也在学pythp ...

随机推荐

  1. 使用 FFT 分析周期性数据

    可以使用傅里叶变换来分析数据中的变化,例如一个时间段内的自然事件. 天文学家使用苏黎世太阳黑子相对数将几乎 300 年的太阳黑子的数量和大小制成表格.对大约 1700 至 2000 年间的苏黎世数绘图 ...

  2. 忘记Linux登录密码怎么办?

    1.启动虚拟机,出现下面倒计时界面时,按e键.进入启动前编辑. 2.进入如下界面,再按e键. 3.进入如下页面后,选中第二项kernel开头的项,选中后再按e键. 4.进入如下界面后,在最后面输入空格 ...

  3. shiro缓存管理

    一. 概述 Shiro作为一个开源的权限框架,其组件化的设计思想使得开发者可以根据具体业务场景灵活地实现权限管理方案,权限粒度的控制非常方便.首先,我们来看看Shiro框架的架构图:从上图我们可以很清 ...

  4. win10安装tensorflow-gpu1.13.1+cuda10.0+cudnn7.3.1

    一,本机配置 Win10 64bit NVIDIA GeForce GTX 960M Python3.7(Anaconda) 二,安装CUDA 亲测,TensorFlow-gpu1.13.1支持cud ...

  5. Dynamics CRM项目实例之七:站点地图修改,联系人-订单-积分管理

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复138或者20141229可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me!        前面文章发表后,不 ...

  6. Web API 持续集成:PostMan+Newman+Jenkins(图文讲解)

    本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 上篇文章我们已经完成了API测试工具选型,接下来是一系列周期性的开发 ...

  7. Linux安装配置Mariadb

    一.安装数据库Mariadb 参考:http://blog.51cto.com/12173069/2047746 从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自 ...

  8. java优先级队列的使用 leecode.703.数据流中的第K大元素

    //设计一个找到数据流中第K大元素的类(class). //注意是排序后的第K大元素,不是第K个不同的元素. class KthLargest { private PriorityQueue<I ...

  9. pipe size设置

    我所用的软件架构,使用pipe来实现线程之间的大量数据的传输.在实际操作中,pipe中传输的是数据的指针,而不是数据本身.  但是在调试过程中,我发现,如果我尝试往pipe里面write10000个指 ...

  10. Linux(CentOS7)下如何配置多个Tomcat容器

    一.Linux版本 二.上传并解压apache-tomcat-7.0.90压缩包,然后复制粘贴出来多个tomcat 解压缩 tar -xzvf apache-tomcat-7.0.90.tar.gz ...