当前位置 : 主页 > 编程语言 > python >

编写高质量代码——改善Python程序的91个建议(Ⅴ)

来源:互联网 收集:自由互联 发布时间:2022-06-24
建议50:利用模块实现单例模式 建议51:用mixin模式让程序更加灵活 建议52:用发布订阅模式实现松耦合 建议53:用状态模式美化代码 建议54:理解built-in objects 建议55:__init__不是构造方
  • 建议50:利用模块实现单例模式
  • 建议51:用mixin模式让程序更加灵活
  • 建议52:用发布订阅模式实现松耦合
  • 建议53:用状态模式美化代码
  • 建议54:理解built-in objects
  • 建议55:__init__不是构造方法
  • 建议56:理解名字查找机制
  • locals()局部变量、globals()全局变量。
  • python作用域:
  • 局部作用域。函数的每次调用都会创建一个新的本地作用域,拥有新的命名空间。
  • 全局作用域。全局仅局限于单个文件。
  • 嵌套作用域。一般在多重函数嵌套的情况下才会考虑到。如果想在嵌套的函数内修改外层函数中定义的变量,即使使用global进行申明也不能达到目的。
In [17]: def ex2():
...: var = 'a'
...: def inner():
...: global var
...: var = 'b'
...: print(var)
...: inner()
...: print(var)
...:

In [18]: ex2()
b
a
  • 内置作用域。1.在最内层(函数内部,locals()中)查找。2.在模块内查找(globals()中)。3.在外层查找(在__builtin__()中)。
In [19]: def foo(x):
...: a = x
...: def bar():
...: nonlocal a
...: b = a * 2
...: a = b + 1
...: print(a)
...: return bar
...:

In [20]: foo(1)
Out[20]: <function __main__.foo.<locals>.bar()>

In [21]: print(foo(1))
<function foo.<locals>.bar at 0x000002186D48F488>

In [22]: print(foo(1)())
3
None


  • 建议57:为什么需要self参数
    self本身并不是Python的关键字(cls也不是),可以将self替代成任何你喜欢的名称。
  • 建议58:理解MRO与多继承
  • 建议59:理解描述符机制
  • 建议60:区别__getattr__()和__getattribute__()方法
  • 建议61:使用更为安全的property
  • 建议62:掌握metaclass
  • 建议63:熟悉Python对象协议
  • 用以比较大小的协议。
  • 数值类型相关的协议。
  • 容器类型协议。
  • 可调用对象协议。
  • 可哈希协议。
  • 上下文管理器协议。
  • 建议64:利用操作符重载实现中缀语法
class Pipe:
def __init__(self, function):
self.function = function
def __ror__(self, other):
return self.function(other)
def __call__(self, *args, **kwargs):
return Pipe(lambda x: self.function(x, *args, **kwargs))

@Pipe
def where(iterable, predicate):
return (x for x in iterable if (predicate(x)))
  • 熟悉Python的迭代器协议 - iter
    *迭代器最大的好处就是定义了统一的访问容器的统一接口,所以程序员可以随时定义自己的迭代器。迭代器还有惰性求值的特性,它仅在可以在迭代至当前元素时才计算该元素的值。非常适合遍历无穷个元素的集合或巨大的事物。

函数

意义

product()

计算m个序列的n次笛卡尔积

permutations()

产生全排列

combinations()

产生无重复元素的组合

combinations_with_replacement()

产生有重复元素的集合

  • 建议66:熟悉Python的生成器 - yield
    迭代器虽然在某些场合表现得想生成器,但它绝非生成器,反而是生成器实现了迭代器协议的,可以在一定程度上看作迭代器。
    每一个生成器函数调用后,它的函数体并不执行,而是到第一次调用next()的时候才开始执行,执行到yield()为止。
  • 建议67:基于生成器的协程及greenlet
  • 建议68:理解GIL的局限性
  • 建议69:对象的管理与垃圾回收

- 《编写高质量代码 改善Python程序的91个建议》张颖 赖勇浩 著。


网友评论