python高级编程 ——装饰器、闭包、函数进阶

闭包

使用闭包可以调用私有变量,同时可以在该私有变量基础上添加想要的参数。

def father(fatherName):
    def son(sonName):
        print("{}是{}的爸爸".format(fatherName, sonName))
    return son

test = father("老王")
test("小明")
test("小李")

输出

老王是小明的爸爸
老王是小李的爸爸

装饰器

  1. 装饰器可以嵌入函数中
  2. 装饰器使用@装饰语法,相同的函数名只出现一次,可读性更高。
  3. 装饰器可以加入参数
  4. 装饰对象可以是函数、类

基本原理

python的装饰器使用闭包来实现了,基本原理如下

def myDecorator(func):
    print("I am a decorator!")
    def warp_func():
        func()
        print("Hello, warp funcation!")
        
    return warp_func
def require_func():
    print("I am require function!")

require_func = myDecorator(require_func)
require_func()

输出

I am a decorator!
I am require function!
Hello, warp funcation!

用法

不带参数的修饰器

def myDecorator(func):
    print("I am a decorator!")
    def warp_func():
        func()
        print("Hello, warp function!")
    return warp_func
@myDecorator
def require_func():
    print("I am require function!")
require_func()
#名字输出存在缺陷
print(require_func.__name__)

输出

I am a decorator!
I am require function!
Hello, warp funcation!
warp_fun

打印函数require_func名字时输出不对,为解决该问题可使用warp包装解决,即

def myDecorator(func):
    from functools import wraps
    print("I am a decorator!")
    @wraps(func)
    def warp_func():
        func()
        print("Hello, warp function!")
    return warp_func
@myDecorator
def require_func():
    print("I am require function!")
require_func()
#名字输出不存在缺陷
print(require_func.__name__)

带参数的装饰器

def outer(args):
    print(args)
    def myDecorator(func):
        print("I am a decorator!")
        def warp_func():
            func()
            print("Hello, warp funcation!")
        return warp_func
    return myDecorator

@outer("outer: 我是outer装饰器传入的")
def require_func():
    print("I am require function!")
    
require_func()

输出

outer: 我是outer装饰器传入的
I am a decorator!
I am require function!
Hello, warp funcation!

类装饰器

可以用来设置类的属性等

def decorator(enabled=True):
    def warp_func(cls):
        cls.__pd_type__ ='test'
        cls.__enabled__ = enabled
        return cls
    return tracer
    
#报错,显示没有该属性  
#class TestCases(object):
#    pass
#print(TestCases.__dict__['__pd_type__'])
#print(TestCases.__dict__['__enabled__'])

@TestClass()
class TestCases(object):
    pass
    
print(TestCases.__dict__['__pd_type__'])
print(TestCases.__dict__['__enabled__'])

输出

test
true

python内置装饰器

@staticmethod
  1. 声明方法为静态方法,可直接通过类或者实例调用。
  2. 其修饰的方法,不需要self参数,可传入自定义的任何参数,其使用方法与直接调用函数相同。
@classmethod
  1. 声明方法为类方法,可直接通过类或实例调用。
  2. 其修饰的方法,不需要self参数,需要一个标识类本身的cls参数。
比较
class Test:
    def __init__(self, name):
        self.name = name

    @staticmethod
    def static_func(*args):
        print("这是一个静态方法")

    @classmethod
    def class_func(cls):
        print("这是一个类的静态方法")
        print("类的名字为%s"%cls.__name__)

    def func(self):
        print("这是一个类的普通方法")
        print(self.name)

测试该类

[In 1]: Test.static_func()
[Out 1]: 这是一个静态方法

[In 2]: Test.class_func()
[Out 2]: 这是一个类的静态方法
类的名字为Test

[In 3]: Test.func()
[Out 3]:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: func() missing 1 required positional argument: 'self'

[In 4]: test = Test("test")
[Out 4]: 这是一个类的普通方法
test

[In 5]: test.static_func()
[Out 5]: 这是一个静态方法

[In 6]: test.class_func()
[Out 6]: 这是一个类的静态方法
Test

描述器

  1. 描述器是一个类
  2. 可以定义__get__, __set__, __delete__方法,来控制属性的访问、赋值和删除操作
  3. 当某个类定义了一个描述器对象的类属性,调用这个类对象的此属性,会触发相应描述器的__get__, ___set___, __delete__方法。
#定义描述器————info类,为其设置相应的方法
class info:
    def __init__(self, name):
        self.name = name
    def __set__(self, instance, value):
        print("触发set方法")
        instance.__dict__[self.name] = value
        print(instance.__dict__)
    def __get__(self, instance, owner):
        print("触发get方法")
        return instance.__dict__[self.name]
    def __del__(self):
        print("触发del方法")

class user:
    info = info("money")
    def __init__(self, name):
        self.name = name

xiaoMing = user("xiaoMing")
print("=="*20)
xiaoMing.info = 5

print("=="*20)
print(xiaoMing.info)

print("=="*20)
xiaoMing.info

'''output
==================================
触发set方法
{'name': 'xiaoMing', 'money': 5}
==================================
触发get方法
5
==================================
触发get方法
触发del方法
'''

@property

该描述符可在类中把一个方法变成属性调用

定义只读属性

名字开头为双下划线的私有属性也可访问,而@property可定义真正意义上的私有属性,无法被实例调用。

class Person():
    def __init__(self, name):
        self.name = name
        self.__age = 12
    @property
    def age(self):
        print(self.__age)
        return self.__age
        
xm = Person('xiaoMing') 
print(xm.age) #结果为12
xm.age() #报错

类似描述器的实现

class Person():
    def __init__(self, name):
        self.name = name
        self.__age = 18
        
    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        print("触发set方法")

    @age.getter
    def age(self):
        print("触发get方法")
        return self.__age

    @age.deleter
    def age(self):
        print("触发delete方法")


xm = Person('xiaoming')
print('='*30)
print(xm.age)

print('='*30)
xm.age = 10

print('='*30)
del xm.age
'''output
==============================
触发get方法
18
==============================
触发set方法
==============================
触发delete方法
'''

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值