概要

本人python理论知识远达不到传授级别,写文章主要目的是自我总结,并不能照顾所有人,请见谅,文章结尾贴有相关链接可以作为补充

全文分为三个部分装饰器理论知识、装饰器应用、装饰器延申

装饰理基础:无参装饰器、有参装饰器、functiontools、装饰器链

装饰器进阶:property、staticmethod、classmethod源码分析(python代码实现)

装饰器基础

无参装饰器

'''

假定有一个需求是:打印程序函数运行顺序

此案例打印的结果为:

foo1 function is starting

foo2 function is starting

'''

from functools import wraps

def NoParamDec(func):

#函数在被装饰器装时后,其函数属性也会改变,wraps作用就是保证被装饰函数属性不变

@wraps(func)

def warpper(*args, **kwargs):

print('{} function is starting'.format(func.__name__))

return func(*args, **kwargs)

return warpper

#python黑魔法省略了NoParamDec=NoParamDec(foo1)

@NoParamDec

def foo1():

foo2()

@NoParamDec

def foo2():

pass

if __name__ == "__main__":

foo1()

有参装饰器

'''

假定有一个需求是:检查函数参数的类型,只允许匹配正确的函数通过程序

此案例打印结果为:

('a', 'b', 'c')

-----------------------分割线------------------------

ERROS!!!!b must be

ERROS!!!!c must be

('a', 2, ['b', 'd'])

'''

from functools import wraps

from inspect import signature

def typeAssert(*args, **kwargs):

deco_args = args

deco_kwargs = kwargs

def factor(func):

#python标准模块类,可以用来检查函数参数类型,只允许特定类型通过

sig = signature(func)

#将函数形式参数和规定类型进行绑定

check_bind_args = sig.bind_partial(*deco_args, **deco_kwargs).arguments

@wraps(func)

def wrapper(*args, **kwargs):

#将实际参数值和形式参数进行绑定

wrapper_bind_args = sig.bind(*args, **kwargs).arguments.items()

for name, obj in wrapper_bind_args:

#遍历判断是否实际参数值是规定参数的实例

if not isinstance(obj, check_bind_args[name]):

try:

raise TypeError('ERROS!!!!{arg} must be {obj} '.format(**{'arg': name, 'obj': check_bind_args[name]}))

except Exception as e:

print(e)

return func(*args, **kwargs)

return wrapper

return factor

@typeAssert(str, str, str)

def inspect_type(a, b, c):

return (a, b, c)

if __name__ == "__main__":

print(inspect_type('a', 'b', 'c'))

print('{:-^50}'.format('分割线'))

print(inspect_type('a', 2, ['b', 'd']))

装饰器链

'''

假定有一个需求是:

输入类似代码:

@makebold

@makeitalic

def say():

return "Hello"

输出:

Hello

'''

from functools import wraps

def html_deco(tag):

def decorator(fn):

@wraps(fn)

def wrapped(*args, **kwargs):

return '<{tag}>{fn_result}<{tag}>'.format(**{'tag': tag, 'fn_result': fn(*args, **kwargs)})

return wrapped

return decorator

@html_deco('b')

@html_deco('i')

def greet(whom=''):

# 等价于 geet=html_deco('b')(html_deco('i)(geet))

return 'Hello' + (' ' + whom) if whom else ''

if __name__ == "__main__":

print(greet('world')) # -> Hello world

装饰器进阶

property 原理

通常,描述符是具有“绑定行为”的对象属性,其属性访问已经被描述符协议中的方法覆盖。这些方法是__get__()、__set__()和__delete__()。如果一个对象定义这些方法中的任何一个,它被称为一个描述符。如果对象定义__get__()和__set__(),则它被认为是数据描述符。仅定义__get__()的描述器称为非数据描述符(它们通常用于方法,但是其他用途也是可能的)。

属性查找优先级为:

类属性

数据描述符

实例属性

非数据描述符

默认为__getattr__()

class Property(object):

'''

内部property是用c实现的,这里用python模拟实现property功能

代码参考官方doc文档

'''

def __init__(self, fget=None, fset=None, fdel=None, doc=None):

self.fget = fget

self.fset = fset

self.fdel = fdel

self.__doc__ = doc

def __get__(self, obj, objtype=None):

if obj is None:

return self

if self.fget is None:

raise (AttributeError, "unreadable attribute")

print('self={},obj={},objtype={}'.format(self,obj,objtype))

return self.fget(obj)

def __set__(self, obj, value):

if self.fset is None:

raise (AttributeError, "can't set attribute")

self.fset(obj, value)

def __delete__(self, obj):

if self.fdel is None:

raise (AttributeError, "can't delete attribute")

self.fdel(obj)

def getter(self, fget):

return type(self)(fget, self.fset, self.fdel, self.__doc__)

def setter(self, fset):

return type(self)(self.fget, fset, self.fdel, self.__doc__)

def deleter(self, fdel):

return type(self)(self.fget, self.fset, fdel, self.__doc__)

class Student( object ):

@Property

def score( self ):

return self._score

@score.setter

def score( self, val ):

if not isinstance( val, int ):

raise ValueError( 'score must be an integer!' )

if val > 100 or val < 0:

raise ValueError( 'score must between 0 ~ 100!' )

self._score = val

if __name__ == "__main__":

s = Student()

s.score = 60

s.score

staticmethod 原理

@staticmethod means: when this method is called, we don't pass an instance of the class to it (as we normally do with methods). This means you can put a function inside a class but you can't access the instance of that class (this is useful when your method does not use the instance).

class StaticMethod(object):

"python代码实现staticmethod原理"

def __init__(self, f):

self.f = f

def __get__(self, obj, objtype=None):

return self.f

class E(object):

#StaticMethod=StaticMethod(f)

@StaticMethod

def f( x):

return x

if __name__ == "__main__":

print(E.f('staticMethod Test'))

classmethod

@staticmethod means: when this method is called, we don't pass an instance of the class to it (as we normally do with methods). This means you can put a function inside a class but you can't access the instance of that class (this is useful when your method does not use the instance).

class ClassMethod(object):

"python代码实现classmethod原理"

def __init__(self, f):

self.f = f

def __get__(self, obj, klass=None):

if klass is None:

klass = type(obj)

def newfunc(*args):

return self.f(klass, *args)

return newfunc

class E(object):

#ClassMethod=ClassMethod(f)

@ClassMethod

def f(cls,x):

return x

if __name__ == "__main__":

print(E().f('classMethod Test'))

参考资料

python装饰器setter实现原理_python装饰器、描述符模拟源码实现相关推荐

  1. python编程锦囊pdf百度云_python编程锦囊 相关实例(示例源码)下载 - 好例子网

    开发语言:Python | 大小:42.01M | 发布时间:2020-08-05 | 立即下载 开发语言:Python | 大小:41.83M | 发布时间:2020-11-11 | 立即下载 开发 ...

  2. python抖音表白程序代码_python 下载抖音视频示例源码

    [实例简介] 下载抖音视频 [实例截图] [核心代码] #code:utf-8 import requests from bs4 import BeautifulSoup import json se ...

  3. 设计模式 结构型模式 -- 装饰者模式(概述 快餐店案例 模式优点 使用场景 源码解析 BufferedWriter 和代理模式的区别)

    1. 装饰者模式 1.1 概述 我们先来看一个快餐店的例子: 快餐店有炒面.炒饭这些快餐,可以额外附加鸡蛋.火腿.培根这些配菜,当然加配菜需要额外加钱,每个配菜的价钱通常不太一样,那么计算总价就会显得 ...

  4. 【Python工具】Python版本的天眼查,是不是就很nice啦 | 附带源码

    相关文件 关注小编,私信小编领取哟! 当然别忘了一件三连哟~~ 公众号:Python日志 可以关注小编公众号,会不定时的发布一下Python小技巧,还有很多资源可以免费领取哟!! 源码领取:加Pyth ...

  5. [智慧农业]Python基于改进YOLOv5的猕猴桃叶病害检测系统(完整源码&数据集&视频教程)

    1.背景 现如今由于农作物病虫害的多样性和复杂性,在特定的条件下其很容易在大范围内发生,导致农产品产量急剧下降.因此,预防和监测农作物病虫害已成为农业生产活动中的重要环节.当前,耕地面积逐渐减少,世界 ...

  6. android毕业设计——基于Android+Java+Python的手机端办公自动化OA系统设计与实现(毕业论文+程序源码)——办公自动化OA系统

    基于Android+Java+Python的手机端办公自动化OA系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于Android+Java+Python的手机端办公自动化OA系统设计与实 ...

  7. python 抓取解析接口数据_[干货]用python抓取摩拜单车API数据并做可视化分析(源码)...

    原标题:[干货]用python抓取摩拜单车API数据并做可视化分析(源码) 在APP中能看到很多单车,但走到那里的时候,才发现车并不在那里.有些车不知道藏到了哪里:有些车或许是在高楼的后面,由于有GP ...

  8. Mybatis底层原理学习(二):从源码角度分析一次查询操作过程

    在阅读这篇文章之前,建议先阅读一下我之前写的两篇文章,对理解这篇文章很有帮助,特别是Mybatis新手: 写给mybatis小白的入门指南 mybatis底层原理学习(一):SqlSessionFac ...

  9. 【Vue-Router】模拟源码,解析 Vue-Router 的实现原理

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 Vue-Router 基础知识 编程式导航 this.$router.replace() this.$router.p ...

最新文章

  1. Django 模板HTML转义和CSRF4.3
  2. 我的世界基岩版json_我的世界基岩版合集
  3. java word表格_Java 添加Word表格行或列
  4. python程序员在公司都是做什么的-程序员是做什么的?工资待遇怎么样?
  5. 腾讯爬虫python_Python爬虫,爬取腾讯漫画实战
  6. 单个字段去重并保留其他字段值
  7. eclipse中复制导入的项目并且修改了项目名字,项目后面的括号显示原来项目的名字
  8. Vue提示warn:”[vue-router] Named Route ‘home’ has a default child route…”
  9. HCIE Security PKI 备考笔记(幕布)
  10. 统计学习中常用的损失函数
  11. 【24点】java减治法实现二十四点,输出所有求值结果为24的组合
  12. js 实现删除确认提示框
  13. 33种名车的标志及名称来历
  14. 服务器的上行带宽和下行带宽是什么意思
  15. 《高效能青少年的七个习惯》读后感作文3900字
  16. Linux远程访问的方法
  17. 开源的C++静态分析工具
  18. 按键精灵X学习笔记(二):键盘命令
  19. matlab中的subplot函数
  20. MySQL删除数据后,释放磁盘空间

热门文章

  1. 统计gitlab代码行脚本_详解代码统计工具cloc--计算文件数、空白行数、注释行和代码行...
  2. 发现 postman 自动生成接口调用代码的一个问题
  3. Chrome 开发者工具无法显示服务器正常返回的 HTTP 请求 - Failed to load response data
  4. SAP Fiori Elements 公开课第一单元概要介绍
  5. SAP UI的加载动画效果和幽灵设计(Ghost Design)
  6. SAP Spartacus 读取payment detail数据的API
  7. SAP Data Intelligence Graph使用浏览器访问的url规范
  8. 如何在S/4HANA里创建Custom Business object并实现自定义逻辑
  9. 开发一个简单的工具,导出github仓库所有issue列表
  10. 通过配置文件避免硬编码的一个例子