Effective Python
kang0709
这个作者很懒,什么都没留下…
展开
-
第40条 考虑协程来并发运行多个函数
Python可以使用线程运行多个函数,使得这些函数看上去好像是在同一时间得到执行。然后,线程有三个显著的缺点:为了确保数据安全,我们必须使用特殊的工具来协调这些线程。便使得线程代码变得难于扩展和维护;线程需要占用大量内存,每个正在执行的线程,大约占据8MB的内存,如果在程序中运行上万的函数线程时,会导致计算机内存无法承受;线程启动时的开销比较大。如果程序不停地以靠新线程来同时执行多个函数,...原创 2020-02-28 12:37:26 · 542 阅读 · 0 评论 -
第39条 用Queue来协调各个线程之间的工作
Python中使用Queue实现多个线程之间的通讯。例如,现在要构建一个照片处理系统,其分为三个阶段:download、resize、和upload阶段。属于典型的生产者-消费者模型。首先,创建一个自定义的队列数据结构MyQueue。class MyQueue(object): def __init__(self): self.items = deque() ...原创 2020-02-27 16:51:40 · 232 阅读 · 0 评论 -
第38条 线程中使用Lock来防止数据竞争
Python在内置的threading模块中提供了Lock类,该类相当于互斥锁,可以保护各线程数据结构不被破坏。案例:新建一个Counter类,统计传感器采样获得的样本数量。### 计数器class Counter(object): def __init__(self): self.count = 0 def increment(self,o...原创 2020-02-27 14:20:57 · 233 阅读 · 0 评论 -
第37条 线程执行阻塞式I/O,但不能用来做平行计算
标准的Python实现叫做CPython。CPython分两步用来运行Python程序:1.首先,将文本形式的源代码解析并编译成字节码;2.然后,用一种基于栈的解释器运行这份字节码。执行Python程序时,字节码解释器必须保持协调一直的状态。Python采用全局解释器锁(GIL)机制来实现这种协调性。GIL实际上是一把互斥锁,用来防止CPython受到抢占式多线程切换操作的干扰。但是,...原创 2020-02-27 13:44:24 · 130 阅读 · 0 评论 -
第33/34条 用元类验证和注册子类
1.元类的定义Python定义元类时,需要从type类中继承,然后重写__new__方法,便可以实现意想不到的功能。class Meta(type): def __new__(meta,name,bases,class_dict): #...各种逻辑实现1 cls = type.__new__(meta,name,bases,class_dict) ...原创 2020-02-26 16:33:51 · 179 阅读 · 0 评论 -
第31条 用描述符改写需要复用的@property方法
Python内置的@property修饰器,有个明显的缺点,就是不便于复用。受它修饰的方法,无法为同一个类中的其他属性所复用,而且与之无关的类也无法复用这些方法。例如,要编写一个类,验证学生的家庭作业成绩在0~100之间。class Homwork(object): def __init__(self) -> None: self._grade = 0 ...原创 2020-02-26 11:40:05 · 198 阅读 · 0 评论 -
第29条 用纯属性@property取代get和set方法
在Java等语言的属性访问和设置中,通常会在类的代码中添加getter和setter方法,以实现属性的设置与获取。class OldResistor(object): def __init__(self,ohms): self._ohms = ohms def get_ohms(self): return self._ohms def se...原创 2020-02-25 16:11:59 · 378 阅读 · 0 评论 -
第27条 多使用public属性,少用private属性
Python类中属性的访问权限分为:public和private两种,然后对于C++类来说有:public、protected和private三种类型。class MyObject(object): def __init__(slef): self.public_field = 5 self.__private_field = 10 def get...原创 2020-02-25 12:56:16 · 261 阅读 · 0 评论 -
第25条 用super初始化父类
在Python中初始化父类的方法,是在子类继承的构造函数中调用父类的init方法。class Person(object): def __init__(self,name,age): self.name = name self.age = age class Student(Person): def __init__(self,name,age...原创 2020-02-25 12:12:56 · 560 阅读 · 0 评论 -
第24条 以@classmethod形式的多态通用地构建对象
在Python中,不仅对象支持多态,类也支持多态。多态,使得继承体系中的多个类能够以各自独有的方式来实现某个方法。这些类,都满足相同的接口或继承自相同的抽象类,但却有着各自不同的功能。案例1:实现MapReduce流程,定义表示输入数据的公共基类。class InputData(object): def read(self): raise NotImplemented...原创 2020-02-25 10:38:42 · 440 阅读 · 1 评论 -
第20条 用None和文档字符串来描述具有动态默认值的参数
有时候我们像采用一种非静态的类型,来做关键字参数的默认值。案例1:打印日志消息的时候,要把相关事件的时间也标注在信息中。import datetimefrom time import sleepdef log(message,when=datetime.datetime.now()): print("%s:%s"%(when,message))if __name__=='__ma...原创 2020-02-24 19:53:42 · 144 阅读 · 0 评论 -
第18/19条 位置参数/关键字参数的应用
令函数接收可变的位置参数(*args),能够让代码更加清晰。案例1:定义log函数打印输出信息,如果参数个数固定,那么必须将参数打包成列表传进去。def log(message,values): if not values: print(message) else: values_str = ', ' .join(str(x) for x in ...原创 2020-02-24 19:33:37 · 507 阅读 · 0 评论 -
第17条 在参数上迭代时,要多加小心
如果函数接收的参数是个对象列表,那么很有可能要在这个列表上进行迭代。案例1:统计每个城市旅游的人数,以及百分比### 标准化函数def normalize(number): total = sum(number) result = [] for value in number: percent = value * 100 / total ...原创 2020-02-23 15:04:17 · 183 阅读 · 0 评论 -
第16条 考虑用生成器来改写直接返回列表的函数
前面提到,对于数据量很大时,可以用生成器表达式代替列表推导,同样,当一个函数返回列表且数据量很大时,应该考虑使用生成器。案例1:获取字符串中每个单词的首字母def index_words(text): result = [] if text: result.append(0) for index,letter in enumerate(text): ...原创 2020-02-23 13:47:16 · 187 阅读 · 0 评论 -
第15条 闭包内使用外围作用域的变量
Python的闭包:是一种定义在某个作用域D中的函数F,这种函数F引用了作用域D里面的变量。案例1:将values列表中的数字进行排序,同时位于group中的数字放在不属于group中元素之前。def sort_priority(values,group): def helper(x): if x in group: #引用了上层作用域中的变量 ...原创 2020-02-23 10:46:00 · 297 阅读 · 0 评论 -
第13条 合理利用try/except/else/finally结构中的每个代码块
Python程序的异常处理可能要考虑四种不同的时机,分别为:try、except、else、finally块来表述。1.finally 块try/finally 结构,可以保证无论try是否抛出异常,都能保证finally块得到执行。handle = open('./test.txt')try: data = handle.read()finally: handle.cl...原创 2020-02-22 20:31:11 · 203 阅读 · 0 评论 -
第10条 enumerate 代替range & zip同时遍历两个迭代器
1. enumerate代替rangePython提供的enumerate函数可以同时获取元素的index和value.array = [1,2,3,4,5]for index, value in enumerate(array): print(index) print(value)同时,可以给enumerate提供第二个参数,指定开始计数时所用的值(默认为0)for ...原创 2020-02-22 20:03:06 · 2016 阅读 · 0 评论 -
第9条 用生成器表达式改写数据量比较大的列表推导
当数据量比较大时,使用列表推导需要把数据全部加载到内存当中,会消耗大量内存,导致程序崩溃。下面读取文件中的数据,此种方式只适合文件小的情况下,当文件较大时,open()操作返回的文件对象会保存在内存中,再使用列表推导取出数据。value = [x for x in open('./test.txt')]print(value)1.生成器表达式为了解决此类问题Python提供了生成器表达...原创 2020-02-22 19:29:07 · 173 阅读 · 0 评论 -
第7条 用列表推导来代替map和filter
第7条 用列表推导来代替map和filterPython提供了一种精简的方法,可以根据一份列表来生成另外一份列表,即为列表推导。实例1:生成每个元素的平方列表推导形式:a = [1,2,3,4,5,6,7]squares = [x**2 for x in a]print(squares)通常的map写法需要创建lambda函数,如下:a = [1,2,3,4,5,6,7]...原创 2020-02-22 16:01:25 · 372 阅读 · 0 评论 -
第5条了解切割序列的方法
文章目录第5条了解切割序列的方法1. 当`start==0`或者`end==序列长度`时,可以省略2.在赋值时,对左侧列表使用切割操作,会将该列表中处在指定范围内的对象替换为新值;如果左侧切片没有指定索引,那么则会被右侧列表替换掉(即使长度不同)3.如果在切割时,右侧列表的起止索引未指定,那么会产生一个原列表的拷贝4.在同一切片操作中,不要同时使用`start`、`end`和`stride`第5...原创 2020-02-22 15:44:07 · 640 阅读 · 0 评论 -
第3条了解bytes、str和unicode的区别
第3条了解bytes、str和unicode的区别Python3中有两种表示字符序列的类型:str:包含Unicode字符bytes:包含原始8位而Python2也有两种表示字符序列的类型:str:包含原始8位unicode:代表Unicode编码需要注意的是,Python2和Python3的Unicode和str实例都没有和特定的二进制编码相关联,因此想要把Unicode...原创 2020-02-22 11:39:01 · 223 阅读 · 0 评论