跳转至

Python 基础

对象拷贝

导入内置模块 copy

  • 浅拷贝:y = copy.copy(x)
  • 深拷贝:y = copy.deepcopy(x)

列表浅拷贝也可以用切片:y = x[::]

实例方法、类方法、静态方法

class A(object):
    # 实例方法,第一个参数 self 的值为当前的对象
    def m1(self, n):
        print("self:", self)

    # 类方法,第一个参数 cls 的值为当前的类
    @classmethod
    def m2(cls, n):
        print("cls:", cls)
        print(cls()) # 创建当前类的对象

    # 静态方法,没有特殊的参数
    @staticmethod
    def m3(n):
        pass

守护线程

如果线程的 daemon=True,那么它就是一个「守护线程」。守护线程(Daemon Thread)不会阻止 Python 程序的退出,就像 C# 中的 Background Thread。

在创建线程时,如果不显式指定,daemon 的值默认是 None,表示使用创建它的线程的 daemon 的值。

守护线程在程序关闭时会突然关闭。他们的资源(例如已经打开的文档,数据库事务等等)可能没有被正确释放。如果你想你的线程正常停止,设置他们成为非守护模式并且使用合适的信号机制,例如:Event1

在文件前面添加内容

with open(file, 'r+', encoding='utf8') as fp:
    text = fp.read()
    fp.seek(0)
    fp.write('foo\n' + text)

常见错误

with open(file, 'r+', encoding='utf8') as fp:
    fp.seek(0)
    fp.write('foo\n') # 会把文件开头的部分覆盖掉!

装饰器

装饰器的 Parsing Expression Grammar (PEG):

named_expression:
    | assignment_expression
    | expression !':='

# 装饰器
decorators: ('@' named_expression NEWLINE )+

从语法上看,@ 后面 几乎能跟各种表达式。表达式的结果最后会被调用。

示例

装饰器写法

# 无参
@test1
def func1():
    pass

# 无参
@test2()
def func2():
    pass

# 有参
@test3(...)
def func3():
    pass

# 少见的写法
@A()+B()
def func4():
    pass

等价写法

# 无参
def func1():
    pass
func1 = test1(func1)

# 无参
def func2():
    pass
func2 = test2()(func2)

# 有参
def func3():
    pass
func3 = test3(...)(func3)

# 少见的写法
def func4():
    pass
func4 = (A()+B())(func4)

使用 functools.wraps()

使用 functools.wraps() 可以保留被装饰函数的信息。

from functools import wraps

def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        print('Calling decorated function')
        return f(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """Docstring"""
    print('Called example function')
  • example.__name__: 'example'
  • example.__doc__: 'Docstring'

不用 functools.wraps() 的话,

  • example.__name__: 'wrapper'
  • example.__doc__: ''

这篇文章深入地介绍了原理:Python functools.wraps 深入理解 - 知乎