Python入门-面向对象-装饰器

 1.变量作用域

全局变量和局部变量

#变量是有作用域的,分为全局变量和局部变量
num = 100 #这是全局变量
def change():
    """
    查看变量作用域
    """
    num = 30 #这是局部变量
    print("change函数内部的,局部变量:",num)
change()
print("全局变量:",num)
"""
change内部的变量: 30
全局变量: 100
"""

全局变量和局部变量互相转换

#global:局部变量转换为全局变量
num = 100
def change():
    """
    修改全局变量内容
    """
    global num
    num = 30
    print("change内部的变量:",num)
change()
print("全局变量:",num)
"""
change内部的变量: 30
全局变量: 30
"""

#nonlocal:全局变量转换为局部变量 【只能使用在闭包中】
#全局作用域
x = 0

def outter():
 #函数作用域
    x = 1
    def inner():
     #局部作用域
        nonlocal x
        x = 2
        print("inner:",x)
    inner()
    print("outter:", x)

f = outter()
print("global:",x)
"""
inner: 2
outter: 1  ---- >2
global: 0
"""

#总结:当变量重名的前提下,修改内部函数的局部作用域为函数作用域,nonlocal扩大作用域

 

2.闭包

def p(count):
    def out(data):
        nonlocal count
        count += 1
        return "第{}次输出数据:{}".format(count,data)
    return out
oa = p(0)
print(oa("tom"))
print(oa("hello"))
print(oa("ok"))
"""
第1次输出数据:tom
第2次输出数据:hello
第3次输出数据:ok
"""

lambda与闭包

#lambda实现闭包
def add(n1):
    return lambda n2: n1 + n2
hello = add(100)
print(hello(200))

3.装饰器-带参数的装饰器-log装饰器演示

# 方法四:定义一个装饰器接收操作函数,是由python传递
def log_logging(func):
    def wrapper(*args, **kwargs):
        #获取包装函数的名称
        print("方法四:这是装饰器的日志方法,当前函数为:{}".format(func.__name__))
     # 函数真正开始执行的地方
return func(*args, **kwargs) return wrapper # 返回装饰器函数,就是闭包 class Message: @log_logging #方法四 def print_title(self): print("方法一:这是print方法直接输出的日志") logging() log() #方法二:定义一个日志函数 def logging(): print("方法二:这是使用logging函数,输出的日志!!") #方法三:使用inspet模块方法,获取方法名称 def log(): import inspect res = inspect.stack()[1][3] print("方法三:这是使用inspect模块,输出的日志!当前方法为:{}".format(res)) if __name__ == '__main__': m = Message() m.print_title()

4.完整的日志装饰器

def log_logging(level="info"):
    def wrapper(func):
        def inner(*args, **kwargs):
            #获取包装函数的名称
            print("【logging-{}】的日志,当前函数为:{}".format(level,func.__name__))
            return func(*args, **kwargs)
        return inner # 返回装饰器函数,就是闭包
    return wrapper
class Message:
    @log_logging(level="DEBUG")  # 设置参数
    def print_title(self):
        print("正在使用print——title方法!")

if __name__ == '__main__':
    m = Message()
    m.print_title()

5.基于类定义,实现的带参数装饰器

# 使用call方法,init方法

class logging:
    def __init__(self, level = "INFO"):
        self.__level = level
    def __call__(self, func):
        def inner(*args, **kwargs):
            # 获取包装函数的名称
            print("【logging-{}】的日志,当前函数为:{}".format(self.__level, func.__name__))
            return func(*args, **kwargs)

        return inner  # 返回装饰器函数,就是闭包
class Message:
    @logging(level="DEBUG")
    def print_info(self):
        print("正在使用print_info的方法。")

if __name__ == '__main__':
    m = Message()
    m.print_info()
"""

【logging-DEBUG】的日志,当前函数为:print_info
正在使用print_info的方法。

"""

 

6.wrapt模块

#wrapt减少嵌套层数
#先安装:pip install wrapt

import  wrapt
@wrapt.decorator()
def logging(wrapped, insrance, args, kwargs):
    print("【方法一:logging】的日志,当前函数为:{}".format(wrapped.__name__))

def log_log(level="INFO"):
    @wrapt.decorator()
    def log_wrapper(wrapped, insrance, args, kwargs):
        print("【方法二:logging-{}】的日志,当前函数为:{}".format(level,wrapped.__name__))
        return wrapped(*args, **kwargs)
    return log_wrapper

class Message:
    # @logging                #这是方法一,两个装饰器,不能同时使用
    @log_log(level="DEBUG")   #这是方法二
    def print_info(self):
        print("正在使用print_info的方法")

if __name__ == '__main__':
    m = Message()
    print(m.print_info())

【方法二:logging-DEBUG】的日志,当前函数为:print_info
 正在使用print_info的方法
 None

内置装饰器

静态方法

# 静态方法:类中没有提供任何实例属性,python没有提供静态方法,由装饰器实现
# 类中的静态方法,不需要产生实例化对象可以在没有实例化对象的前提下调用,
# 但是类中的普通方法,必须在实例化对象后才可以调用
# 实际开发中,首选还是普通方法,需要实例化,不需要实例化对象的才使用静态方法。
class Message:
    title = "百度一下"
    # def get_info(self):  #普通方法
    @staticmethod   # 使用内部装饰器
    def get_info():  #类中不带self的,静态方法
        Message().hello()  # 类中的普通方法,必须在实例化对象后才可以调用
        return "www.baidu.com"

    #普通方法,装饰器无法调用,运行直接报错
    def hello(self):   #类中的,带self的普通方法
        print("【hello方法】这是错误调用!")

if __name__ == '__main__':
    print("静态装饰方法:",Message.title, Message.get_info())

类方法classticmethod

# 类方法,是为了弥补,init构造方法的缺陷问题
# 假如init构造方法,定义了俩参数,但是临时需要接收一个复核参数,
class Message:
    @classmethod
    def get_info(info):
        info().hello() #本类对象,调用本类方法
    def hello(self):  #类中的普通方法
        print("这是方法:hello")

class Me:
    def __init__(self, title, url):
        self.__title = title
        self.__url = url
    def __str__(self):
        return  "{},{}".format(self.__title, self.__url)
    @classmethod
    def get_instance(cls, info):
        res = info.split("-")
        return cls(res[0], res[1])

if __name__ == '__main__':
    print("=======classticmethod静态方法演示:=======")
    Message.get_info()
    print("===========init构造方法使用后演示:=========")
    m = Me("百度", "www.baidu.com")
    print(m)
    print("类方法演示")
    m2 = Me.get_instance("谷歌-www.google.com")
    print(m2)

=======classticmethod静态方法演示:=======
这是方法:hello
===========init构造方法使用后演示:=========
百度,www.baidu.com
类方法演示
谷歌,www.google.com

property装饰器

#优化属性访问

class Message:
    def __init__(self, info):
        self.__info = info
    def set_info(self, info):
        self.__info = info
    def get_info(self):
        return self.__info
    def del_info(self):
        del self.__info

class Me:
    #属性装饰器,简化操作
    def __init__(self,info):
        self.__info = info
    @property
    def info(self):
        return self.__info
    @info.setter  #修改属性,下面方法名,必须和上面保持一致
    def info(self,info):
        self.__info = info
    @info.deleter
    def info(self):
        del self.__info

if __name__ == '__main__':
    m = Message("百度一下")
    print(m.get_info())
    m.set_info("还是谷歌去吧")
    print(m.get_info())
    m.del_info()      #删除info属性
    print("===========property装饰器演示==========")
    me = Me("www.baidu.com")
    print(me.info)  # 直接访问属性
    me.info = "百度一下:www.baidul.com"  #直接修改属性
    print((me.info))
    del me.info     #删除属性

百度一下
还是谷歌去吧
===========property装饰器演示==========
www.baidu.com
百度一下:www.baidul.com

 使用偏函数,与类实现装饰器

import time
import functools
class DelayFunc: def __init__(self, duration, func): self.durution = duration self.func = func def __call__(self, *args, **kwargs): print(f"等待{self.durution} seconds...") time.sleep(2) return self.func(*args, **kwargs) def hello(self, *args, **kwargs): print("hello方法") return self.func(*args, **kwargs) def delay(duration): return functools.partial(DelayFunc, duration) @delay(duration=2) def add(a, b): return a + b add(2, 3) """ 等待2 seconds... 5 """

单例模式和装饰器-能装饰类

# 单例模式,装饰器

instances = {}

def single(cls):
    def get_instance(*args, **kwargs):
        cls_name = cls.__name__
        print('===== 1 ====')
        if cls_name not in instances:
            print('===== 2 ====')
            instance = cls(*args, **kwargs)
            instances[cls_name] = instance
        return instances[cls_name]
    return get_instance


@single
class User:
    _instance = None
    def __init__(self, name):
        print('===== 3 ====')
        self.name = name
u1 = User("tom")
u2 = User("jeery")
u1 is u2
"""
===== 1 ====
===== 2 ====
===== 3 ====
===== 1 ====
True
"""

 

posted @ 2021-08-20 16:20  zwx901323  阅读(56)  评论(0)    收藏  举报