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 """

浙公网安备 33010602011771号