栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

32.Python面向对象(五)【描述符、运算符底层、装饰器:闭包-闭包参数-内置装饰器-类装饰器】

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

32.Python面向对象(五)【描述符、运算符底层、装饰器:闭包-闭包参数-内置装饰器-类装饰器】

目录:
  • 每篇前言:
  • Python面向对象(五)
    • 1.1 描述符
    • 1.2 运算符底层调用的什么?
    • 1.3 装饰器
      • 第一部分——引入门
        • (1)首先、咱再看遍闭包是啥:
        • (2)然后,咱稍微高级点,看看闭包参数。
        • (3)最后,就来看看第一种装饰器:
      • 第二部分——类里面的内置装饰器
        • (1)引入
        • (2)第一个是把类里面的方法变为属性:
        • (3)静态方法
        • (4)第三个是类方法:
      • 第三部分——最后阶段
        • (1)类装饰器 必须使用__call__方法
        • (2)看看高级点的
      • 拓展一下呗——来个装饰器的习题

每篇前言:
  • 作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者

  • 本文已收录于Python全栈系列专栏:《Python全栈基础教程》
  • 热门专栏推荐:《Django框架从入门到实战》、《爬虫从入门到精通系列教程》、《爬虫高级》、《前端系列教程》、《tornado一条龙+一个完整版项目》。
  • ​本专栏面向广大程序猿,为的是大家都做到Python从入门到精通,同时穿插有很多很多习题,巩固学习。
  • 订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
  • 加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

Python面向对象(五) 1.1 描述符

描述符协议:python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问。这些方法有__get__(), __set__(), 和__delete__()。
如果这些方法中的任何一个被定义在一个对象中,这个对象就是一个描述符

举例说明:

# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
# 描述符:描述符就是类里面的属性base
# 控制实例对象a访问 这个属性 (base)  可以做一些额外的操作
# 描述符  定义了__get__  __set__  __delete__  当中的一种
class Base:
    def __get__(self,instance,owner):
        print('恭喜玩家获得荒古宝典')
    def __set__(self, instance,value):
        print('强化%s'%value)
    def __delete__(self,instance):
        print('武器已经损坏')

class A:
    base = Base()

#实例化
a = A()

a.base           # __get__        会直接输出__get__方法里面的内容

a.base = 50      # __set__ 		  会直接输出__set__方法里面的内容

del a.base       # __delete__	  会直接输出__delete__方法里面的内容

1.2 运算符底层调用的什么?
  • +调用的是__add__

举例说明:

# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class A:
	def __init__(self,num1,num2):
		self.num1 = num1
		self.num2 = num2

	def __add__(self,other):      #self  实例对象   ;   other  另外一个实例对象
		sum1 = self.num1 + other.num1
		sum2 = self.num2 + other.num2
		return sum1,sum2


a = A(1,2)
b = A(3,4)
print(a+b)    #输出为  (4,6)

运算符方法(了解即可)

__add__(self,other)	# x+y
__sub__(self,other)	# x-y
__mul__(self,other)	# x*y
__mod__(self,other)	# x%y
__iadd__(self,other)	# x+=y
__isub__(self,other)	# x-=y
__radd__(self,other)	# y+x
__rsub__(self,other)	# y-x
__imul__(self,other)	# x*=y
__imod__(self,other)	# x%=y
1.3 装饰器

有这个玩意的原因:python是一个动态语言,因为一切都是对象。是一个脚本语言。

第一部分——引入门 (1)首先、咱再看遍闭包是啥:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
#闭包
def fun1():
    print('fun1')
    def fun2():
        print('fun2')
    return fun2

#fun1()() ===>  fun2()
a = fun1()
a()           #会执行两个函数
(2)然后,咱稍微高级点,看看闭包参数。

这种方法比较麻烦,所以下面就引入了装饰器,和这个的功能一模一样,不过
简单了许多:

# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
#闭包里面有参数        回调函数
def aa(fun):                         #fun = f1
    print('------------aa')
    def bb():
        fun()                         #fun()   =  f1()
        print('----------bb')
    return bb

def f1():
    print('this is f1')

def f2():
    print('this is f2')

cc = aa(f1)
cc()

(3)最后,就来看看第一种装饰器:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
# 装饰器   在不改变原有函数的基础上面增加额外的功能
# 装饰器
def aa(fun):                         #fun = f1
    print('------------aa')
    def bb():
        fun()                         #fun()   =  f1()
        print('----------bb')
    return bb

# 装饰器  被装饰的函数名字(f1)会被当做参数传递给装饰函数(aa)
# 代码就是:     aa(f1)
# 装饰函数(aa)执行完它自己内部的代码之后,会把它的结果返回给
# 被装饰的函数(f1)
# 代码就是:     f1 = aa(f1)
# 然后下面又是f1()    就相当于   aa(f1)()

@aa             # 就相当于 f1 = aa(f1)   要使用嵌套函数里面的内容  aa(f1)(),就是最后调用的时候f1加个括号
                # 而注意函数外部的只要用到装饰器就会执行,而嵌套的内层函数需要调用才会执行,所以
                #  用处就是把重要的东西写到嵌套的内层函数,在调用的时候才会执行
def f1():
    print('this is f1')

def f2():
    print('this is f2')

f1()           #输出和上面一个一模一样

第二部分——类里面的内置装饰器 (1)引入
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Base:

    def fun(self):
        print('好好学习,天天向上')


b = Base()
b.fun()  # 调用类里面的方法,就会执行类里面的方法fun,打印 好好学习,天天向上

正题:

(2)第一个是把类里面的方法变为属性:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Base:
    name = '孤寒者'

    @property         #将方法变为属性  更加简洁
    def fun(self):
        return('好好学习,天天向上')


b = Base()
print(b.name)          #属性的使用不需要加括号;方法的使用才要加括号
print(b.fun)          #现在类里面的方法fun就变成了类的属性

(3)静态方法
  • 第二个是把类里面的方法变为静态方法,让其可以像使用函数一样去使用,而不需要再实例化才能使用:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Base:

    @staticmethod       #静态方法  方法能够像函数一样的去使用, 比如在类里面,你要写一些闭包什么的就可以在这里面写,相当于扩展了一些功能。
    def fun2():              # 注意:这里已经不需要self   和class类断开联系
        print('过年好,新年好')

    #再来个不加装饰器的
    def func(self):
        print('这是普通方法')

Base.fun2()     # fun2已经变为静态方法,可以像使用函数一样的使用
# 输出为:  过年好,新年好

# Base是类名;Base() 就是实例化
Base().func()      # 而没有使用装饰器的方法就需要先实例化,才能去使用

(4)第三个是类方法:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Base:

    def func(self):
        print('这是普通方法')

    @classmethod
    def fun3(cls):  # 没有self   和实例无关,这是类方法  ;   有self的是实例方法,需要先实例化才能使用
        print('cls类方法')
        cls().func()  # cls 代表类本身,即Base这个类


# 类方法的使用,也不用实例化 直接类名点方法
Base.fun3()

第三部分——最后阶段 (1)类装饰器 必须使用__call__方法
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Base:

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

    def __call__(self,*args,**kwargs):
        print('this is call')

@Base      # func = Base(func)     被装饰函数(func)当做参数传递给装饰函数(Base)
def func():
    print('this is func')

func()     # 此处的括号就相当于 func() = Base(func)()
           # __call__方法只要实例化就会被调用
#输出为:   this is call

(2)看看高级点的
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Base:

    def __init__(self,fun):
        self.fun = fun

    def __call__(self,*args,**kwargs):
        self.fun()         #就会打印    this is func
        print('this is call')

    def __str__(self):
        return 'this is str'

@Base      # func = Base(func)  相当于实例化   被装饰函数(func)当做参数传递给装饰函数(Base)
def func():
    print('this is func')

func()     # 此处的括号就相当于 func() = Base(func)()
           # __call__方法只要实例化就会被调用
print(func)        # 打印类的实例,就会调用类里面的__str__方法

拓展一下呗——来个装饰器的习题
  • 测试type和isinstance两个函数,哪个速度更加的快?

需要注意的是:程序运行速度比较快 只查看上面两个函数 运行一次的时间显示不出来效果,可以查看循环一万次的时间。

# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
#time.time()  计算目前的时间  时间戳(格林威治时间, 1970.1.1到现在的总秒数)
import time

def funa(fun):
    def funb():
        a = time.time()
        fun()
        b = time.time()
        print('函数运行了%s'%(b-a))
    return funb

@funa
def f1():
    for i in range(100000):
        type(1)
f1()

@funa
def f2():
    for i in range(100000):
         isinstance(1,int)
f2()

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1036950.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号