美文网首页
python单例和装饰器

python单例和装饰器

作者: 随侯珠 | 来源:发表于2019-04-17 13:55 被阅读0次

Python相关分享

单例

单例的定义:

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例。

优点:

1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例

2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。

3.提供了对唯一实例的受控访问。

4.由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。

5.允许可变数目的实例。

6.避免对共享资源的多重占用。

缺点:

1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。

2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。

3.单例类的职责过重,在一定程度上违背了“单一职责原则”。

4.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。

以上资料来自互联网

python单例 实现如下:(非线程安全的方式)

# -*- coding: utf-8 -*-
class Person(object):
  __singleton = None
  
  def __new__(cls, *args, **kwargs):
    if not cls.__singleton:
      cls.__singleton = super(Person, cls).__new__(cls, *args, **kwargs)
    return cls.__singleton

  def __init__(self, name, age):
    self.name = name
    self.age = age

  def say(self):
    print self.name, self.age

sui = Person("suihouzhu", 28)
fan = Person("fansizhe", 27)

print id(sui) == id(fan)
print sui.name

装饰器 - 装饰没有参数的方法

@ 是python装饰器的语法糖,被@装饰的方法称为装饰器,装饰器可作用的对象包括方法、类、类方法,针对不同的作用对象,装饰器的语法会有些许差别。装饰器方法的返回值类型一定要于被装饰对象的类型一致,即:装饰方法或者类方法的装饰器,返回的需要是一个方法;装饰类的装饰器,返回的需要是一个类对象。
直接看一个最简单的方法装饰器:

# -*- encoding:utf-8 -*-
# 定义方法装饰器 test_deco, 返回一个内部方法_deco
def test_deco(func):
  def _deco():
    print "[方法前执行]"
    func()
    print "[方法后执行]"
  return _deco

@test_deco
def myfunc():
  print "------method run"

myfunc()

一眼看上去不知道装饰器是怎么工作的,不过不用担心,其实上述代码在执行时,等价于:

# 1.执行myfunc时,python执行器会将myfunc方法当做参数传给装饰器方法(test_deco)
tmp_func = test_deco(myfunc)  
# 2.执行返回的方法
tmp_func()  

装饰器 — 装饰带有参数的方法

# -*- encoding:utf-8 -*-
import time
def timeit(method):
  def _deco(*args, **kwargs):
    start = time.time()
    method(*args, **kwargs)
    end = time.time()
    print "方法执行耗时:", end - start

  return _deco

@timeit # 统计方法的执行耗时
def timeit_method(name, age):
  print name, age

timeit_method("suihouzhu", 27)

装饰器 - 有参数的装饰器,装饰带参数的方法

def retry(count):
  def _deco(method):
    def _anything(*args, **kwargs):
      for i in range(count):
        try:
          method(*args, **kwargs)
          break
        except:
          pass
    return _anything
  return _deco

@retry(3) # 如果方法执行失败则重试,重试次数3次
def retry_method(name, age):
  print name, age

retry_method("suihouzhu", 27)

装饰器 - 类装饰器

# -*- encoding:utf-8 -*-

def Tracker(TrackedClass):
  class Tmp(TrackedClass):
    def __init__(self, *args, **kwargs):
      super(Tmp, self).__init__(*args, **kwargs)

    # 给被装饰的类增加了一个say_hello的方法
    def say_hello(self):
      print "hello, world"

  return Tmp

@Tracker
class Human(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age

suihouzhu = Human("suihouzhu", 27)
print suihouzhu.name, suihouzhu.age
suihouzhu.say_hello()

装饰器 - 类方法装饰器(与装饰普通的带参数方法一样,只是返回方法的多一个参数self)

import time

def timeit(func):
  def _deco(self, *args, **kwargs):
    start = time.time()
    value = func(self, *args, **kwargs)
    end = time.time()
    print "执行耗时:", end - start
  return _deco

class People(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age

  @timeit
  def say(self, words):
    print words

  def __repr__(self):
    return "<People name='%s' age=%s" % (self.name, self.age)

suihouzhu = People("suihouzhu", 28)
suihouzhu.say("python is fun")

通过装饰器注册函数

class TestClass(object):
    def __init__(self):
        self.func_dict = {}

    def deco(self, func_type):
        def wrapper(func):
            if func_type == 'A':
                self.func_dict[func_type] = func
            if func_type == 'B':
                self.func_dict[func_type] = func
            else:
                self.func_dict['other'] = func
            return func

        return wrapper

    def run(self):
        print('hello')
        self.func_dict['A']('Hi mark this is Func-A ')
        self.func_dict['B']('Hi mark this is Func-B ')

test = TestClass()

@test.deco('A')
def my_func(msg):
    print(f'this is the message from run: {msg}' )

@test.deco('B')
def my_func2(msg):
    print(f'this is the message from run: {msg}')

test.run()

相关文章

网友评论

      本文标题:python单例和装饰器

      本文链接:https://www.haomeiwen.com/subject/tvxnwqtx.html