Python基础与深入(六)

一.装饰器

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有计时统计、插入日志、缓存计算结果、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
装饰器的作用和功能:

  • 引入日志
  • 函数执行时间统计
  • 执行函数前预备处理
  • 执行函数后的清理功能
  • 权限校验等场景
  • 缓存

下面举例说明

1.装饰器用做日志记录

1
2
3
4
5
6
7
8
9
from functools import wrapper
def log(func):
@functools.wraps(func) # 将func的属性传递给wrapper
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
f=func(*args, **kw)
print('end call %s():' % func.__name__)
return f
return wrapper

2.如何定义带参数的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import functools

def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
# 同时支持@log和@log('execute')
def log2(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
if isinstance(text,str):
print('%s %s():' % (text, func.__name__))
else:
print('%s():' % func.__name__)
return func(*args, **kw)
return wrapper
if callable(text):
return decorator(text)
else:
return decorator

3.装饰器用做执行时间统计

1
2
3
4
5
6
7
8
9
10
11

from functools import wrapper
from time import time
def countTime(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
print("函数{0}执行时间为:{1}s".format(func.__name__, time.time() - start))
return func
return wrapper

4.装饰器用做缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def cache(func):
cache_dict = {}

@functools.wraps(func)
def wrapper(*args):
if args not in cache_dict:
cache_dict[args] = func(*args)
return cache_dict[args]
return wrapper

@cache
def fibonacci(n):
if n <= 1:
return 1
cache_dict = fibonacci(n - 1) + fibonacci(n - 2)
return cache_dict

二. __new____init__的区别

这个__new__确实很少见到,先做了解吧.

  1. __new__是一个静态方法,而__init__是一个实例方法.
  2. __new__方法会返回一个创建的实例,而__init__什么都不返回.
  3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
  4. 当创建一个新实例时调用__new__,初始化一个实例时用__init__.

三.单例模式

单例模式伯乐在线详细解释

1.使用__new__方法

1
2
3
4
5
6
7
8
9
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance

class MyClass(Singleton):
a = 1

2.装饰器版本

1
2
3
4
5
6
7
8
9
10
11
def singleton(cls):
instances = {}
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance

@singleton
class MyClass:
...

3.import方法

作为python的模块是天然的单例模式

1
2
3
4
5
6
7
8
9
10
11
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass

my_singleton = My_Singleton()

# to use
from mysingleton import my_singleton

my_singleton.foo()

4.使用元类

1
2
3
4
5
6
7
8
9
class Singleton(type):
_instances={}
def __call__(cls,*args,**kwargs):
if cls not in cls._instances:
cls._instances[cls]=super(Singleton,cls).__call__(*args,**kwargs)
return cls._instances[cls]

class MyClass(metaclass=Singleton):
pass

四.Python中的作用域

Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。

当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:

本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

坚持原创技术分享,您的支持将鼓励我继续创作!