Python教程

python高级语法--闭包、装饰器

本文主要是介绍python高级语法--闭包、装饰器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 1、property属性
    • 1.1、定义
    • 1.2、装饰器方式
    • 1.3、类属性方式
  • 2、with语句
  • 3、生成器
    • 3.1、作用
    • 3.2、生成器推导式
    • 3.3、yield关键字
    • 3.4、生成器产生斐波纳锲数列
  • 4、深拷贝和浅拷贝
    • 4.1、可变类型浅拷贝
    • 4.2、深拷贝
  • 5、函数参数
  • 6、闭包
    • 6.1、闭包作用:
    • 6.2、闭包的定义
    • 6.3、构成闭包的条件
    • 6.4、闭包的使用
  • 7、装饰器
    • 7.1、装饰器的作用
    • 7.2、装饰器的使用
    • 7.3、通用装饰器——带有参数的函数
    • 7.4、装饰带有返回值的函数
    • 7.5、装饰带有不定长参数的函数
    • 7.6、多个装饰器
    • 7.7、带有参数的装饰器
    • 7.8、类装饰器

1、property属性

1.1、定义

property属性就是负责把类中的一个方法当作属性进行使用,可以简化代码

1.2、装饰器方式

class Person(object):
    def __init__(self):
        self.__age =0
        
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,new_age):
        self.__age = new_age

p=Person()
print(p.age)
p.age=100
print(p.age)

1.3、类属性方式

property的参数

第一个参数是获取属性是要执行的方法

第二个参数是设置属性时要执行的方法

定义property属性有两种方式:1、装饰器方式 2、类属性方式

装饰器方式:1、property修饰获取值的方法

​ 2、@方法名。setter修饰设置值的方法

类属性方式

​ 1、property属性=property(获取值方法,设置值方法)

class Person(object):
    def __init__(self):
        self.__age = 0

    def get_age(self):
        return self.__age

    def set_age(self,new_age):
        if new_age>=150:
            print("年龄错误")
        else:
            self.__age=new_age
    age = property(get_age,set_age)

p=Person()
print(p.age)
# 设置属性
p.age=100
print(p.age)

2、with语句

python提供了with语句用于简化资源释放的操作,使用with语句操作建立在上下文管理器(实现 __ enter __ 和 __ exit __ 方法)的基础上

class File(object):
    def __init__(self,file_name,file_model):
        self.file_name = file_name
        self.file_name= file_model
    def __enter__(self):
        print("这是上文")
        self.file = open(self.file_name,self.file_model)
        return self.file
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("这是下文")
        self.file.close()

with File("1.txt","r") as f:
    file_data=f.read()
    print(file_data)

3、生成器

3.1、作用

根据程序设计者指定的规则循环生成数据,当条件不成立时则生成数据结束。

数据不是一次性全部生成出来,而是使用一个,再生成一个,可以节约大量的内存

3.2、生成器推导式

与列表推导式类似,只不过生成器推导式使用小括号

data = (x for x in range(100))
next(data)

for i in data:
    print(i)

生成器相关函数

next函数获取生成器中的下一个值

for循环遍历生成器中的每一个值

3.3、yield关键字

yield关键字生成器的特征:在def函数中具有yield关键字

def mygenerater(n):
    for i in range(n):
        print('开始生成....')
        yield
        print('完成一次.....')
g= mygenerater(5)
# print(next(g))
# print(next(g))
# print(next(g))

for i in g:
    print(i)

1、代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行

2、生成器如果把数据生成完成,再次获取生成器中的下一个数据会抛出一个StopIteration异常,表示停止迭代异常

3、while循环内部没有处理异常操作,需要手动添加处理异常操作

4、for 循环内部自动处理了停止迭代异常,使用起来更加方便,推荐使用

3.4、生成器产生斐波纳锲数列

(前面两个数字相加) 1、2、3、5、8、13、21.。。。。。

def fb(num):
    a =0
    b=1
    index =0
    while index< num:
        result = a
        a,b = b,a+b
        yield result
        index +=1
f=fb(8)
for i in f:
    print(i)

1、生成器时根据算法生成数据的一种机制 ,每次调用生成器只生成一个值,可以节省大量内存

2、生成器的创建

4、深拷贝和浅拷贝

copy函数时浅拷贝,只对可变类型的第一层对象进行拷贝

对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象

4.1、可变类型浅拷贝

#普通赋值
import copy
a =[1,2,3]
b=[11,22,33]
c =[a,b]
d=c
print(id(d))
print(id(c))

#浅拷贝可变类型
import copy
a =[1,2,3]
b=[11,22,33]
c =[a,b]
d=copy.copy(c)
print(id(d))
print(id(c))

#浅拷贝、深层数据
import copy
a =[1,2,3]
b=[11,22,33]
c =[a,b]
d=copy.copy(c)
print(id(a))
print(id(c[0]))
print(id(d[0]))

#浅拷贝不可变类型
import copy
a =[1,2,3]
b=[11,22,33]
c =(a,b)
d=copy.copy(c)
print(id(a))
print(id(c[0]))
print(id(d[0]))

4.2、深拷贝

对每一层拷贝对象都会开辟新的内存空间进行存储

# 深拷贝,可变数据
import copy
a =[1,2,3]
b=[11,22,33]
c =[a,b]
d=copy.deepcopy(c)
# print(id(a))
print(id(c))
print(id(d))

# 深拷贝,深层数据
import copy
a =[1,2,3]
b=[11,22,33]
c =(a,b)
d=copy.deepcopy(c)
print(id(a))
print(id(c[0]))
print(id(d[0]))

#深拷贝不可变类型

import copy
a =(1,2,3)
b=(11,22,33)
c =(a,b)
d=copy.deepcopy(c)
print(id(c))
print(id(d))

5、函数参数

​ 作用:1、函数名存放的是函数所在空间的地址

​ 2、函数名()执行函数名所存放空间地址中的代码

​ 3、如下func01=func02函数名可以像普通变量一样赋值,func01()等价于func0()

def func01():
    print("func01 is show")

def foo(func):
    func()
foo(func01)

6、闭包

6.1、闭包作用:

闭包可以保存函数内的变量,不会随着函数调用完而销毁

6.2、闭包的定义

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数成为闭包。

6.3、构成闭包的条件

1、在函数嵌套

2、内部函数使用了外部函数的变量

3、外部函数返回了内部函数

6.4、闭包的使用

def config_name(name):
    def say_info(info):
        print(name + ":" , info)
    return say_info

tom =config_name("tom")
tom("你好")
tom("你在么")

jerry = config_name("jerry")
jerry("你好")
jerry("我在呢")

6.5、修改闭包

修改闭包内使用的外部变量使用nonlocal关键字完成

def func_out(num1):
    def func_inner(num2):
        nonlocal num1
        num1 = num2 + 10

    print(num1)
    func_inner(10)
    print(num1)

    return func_inner

f=func_out(10)
f(10)

7、装饰器

7.1、装饰器的作用

在不改变原有函数的源代码的情况下,给函数增加新的功能

装饰器符合了开发中的封闭原则

本质上相当于是一个闭包

装饰器的语法格式

def check(fn):
    def inner():
        print("登录验证。。。。")
        fn()
    return inner
#解释器遇到@check 会立即执行comment = check(comment)
@check
def comment():
    print("发表评论")

#comment = check(comment)
comment()

7.2、装饰器的使用

使用场景:函数执行时间统计

import time
def get_time(fn):
    def inner():
        start = time.time()
        fn()
        end = time.time()
        print("时间:",end-start)
    return inner

@get_time
def func():
    for i in range(10000):
        print(i)

func()

装饰器作用:在不改变已有函数源代码及调用方式的前提下,对已有函数进行功能的扩展

7.3、通用装饰器——带有参数的函数

def logging(fn):
    def inner(a,b):
        fn(a,b)
    return inner

@logging
def sum_num(a,b):
    result = a + b
    print(result)

sum_num(1,2)

7.4、装饰带有返回值的函数

def logging(fn):
    def inner(a,b):
        result=fn(a,b)
        return result
    return inner

@logging
def sum_num(a,b):
    result = a + b
    return result
    
result = sum_num(1,2)
print(result)

7.5、装饰带有不定长参数的函数

def logging(fn):
    def inner(*args, **kwargs):
        fn(*args, **kwargs )

    return inner

@logging
def sum_num(*args, **kwargs):
    print(args,kwargs)

sum_num(1, 2,3,age=18)

7.6、多个装饰器

def check1(fn1):
    def inner1():
        print("登录验证")
        fn1()
    return inner1
def check2(fn2):
    def inner2():
        print("登录验证2")
        fn2()
    return inner2
@check2
@check1
def comment():
    print("发表评论")

comment()

离函数最近的装饰器先装饰,然后外面的装饰器再装饰,由内到外的装饰过程

7.7、带有参数的装饰器

使用装饰器装饰函数的时候可以传入指定参数

语法:@装饰器(参数。。。。)

def logging(flag):

    def decorator(fn):
        def inner(num1,num2):
            if flag == "+":
                print("正在努力加法计算")
            elif flag == "-":
                print("正在努力减法计算")
            result = fn(num1,num2)
            return result
        return inner
    return decorator

@logging('+')
def add(a,b):
    result = a+b
    return result

result = add(1,3)
print(result)

带参数的装饰器

1、装饰器的外部函数只接受一个参数—被装饰的函数

2、需要给装饰器传参数需要在装饰器外部再增加一个函数

7.8、类装饰器

__ call __ 方法的使用

一个类里面一旦实现了 __ call __ 方法

那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用

class Check(object):
    def __init__(self,fn):
        self._fn = fn

    def __call__(self, *args, **kwargs):
        print("我是call方法")
        self._fn()

@Check
def comment():
    print("发表评论")

comment()
这篇关于python高级语法--闭包、装饰器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!