zoukankan      html  css  js  c++  java
  • 闭包 偏函数和数据锁定

    一,闭包条件

    1,函数中嵌套函数

    2,外层函数返回内层嵌套函数名

    3,内层嵌套函数有引用外层的一个非全局变量,内部嵌套函数不能引用全局变量

    二,作用

    实现数据的锁定,提高稳定性 通过

    index = login(index) 

    index.__closure__可以查看对外层非全局变量的引用

    三,装饰器的实现

     开放封闭原则:软件应该是可扩展的,而不可修改

    def index():
    
      pass

    需求:需要对index加校验功能,但由于开放封闭原则,因此不能直接修改index函数

    # 外层函数参数是被装饰的函数

    def login(index):
    
      def func():
    
        # 校验功能
    
        pass
    
        # 放入被装饰的函数
    
        index()
    
      # 外层函数返回值是内层函数
    
      return func

    执行:

    #@login 语法糖 index = login(index)  

    # index .__closure__ 这里面存储了内部函数调用外部函数的变量,也就是index函数

    @login 
    
    def index():
    
      pass

    四,装饰器的作用

    在不更改原功能函数内部代码,并且不改变调用方法的情况下为原函数添加新功能。

    五,装饰器的应用场景

    1,登录验证

    2,函数运行时间统计

    3,执行函数之前做准备

    4,执行函数后清理工作

    六,通用装饰器

    如果同一个装饰器既要装饰有参数的函数,又要装饰无参数的函数,那么我们在传参的时候就设置成不定长参数,这样不管被装饰的函数有没有参数都能用

    def f1(func):
        def fun(*args, **kwargs):
            print('执行装饰器中的函数')
            func(*args, **kwargs)
        return fun
    
    @f1
    def func(a, b):
        print('执行函数--func')
        print(a + b)
    
    func(10, 20)

    七,类装饰器

    前面是用闭包函数实现的装饰器,也可以使用类当作一个装饰器。

    把类当作装饰器有两步操作:

    1,首先在__init__方法中,把装饰器函数赋值给一个实例属性

    2,然后在类里面实现一个__call__方法,在call方法中调用原来的函数

    def add(func):
    
      def fun(*args, **kwargs):
    
        print('装饰器的功能代码:登录')
        return func(*args, **kwargs)
      return fun
    
    # myClass = login(MyClass)
    
    @login
    
    class MyClass:
    
      def __init__(self):
    
        pass

    八,装饰器装饰类 

    注意:装饰器装饰类fun中的return必须要写,因为类需要把对象返回出来,装饰函数的话return不一定要写

    def add(func):
    
        def fun(*args, **kwargs):
            print('装饰器的功能代码,登录验证')
            return func(*args, **kwargs)
        return fun
    
    @add             # MyClass = add(MyClass)----返回fun
    class MyClass:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    # 相当于fun('小鱼', 18),fun函数中如果没有return 那么该函数默认返回None,装饰之后该类不能创建对象了
    m = MyClass('小鱼', 18)
    print(m)

    九,多个装饰器装饰同一个函数

    从下往上装饰,装饰顺序:@decorator -> @login_check

    从上往下执行,执行顺序:@login_check -> @decorator -> login()函数

    
    
    import time
    def decorator(func):
    def count_time(*args, **kwargs):
    print('进入计算时间的装饰器')
    start_time = time.time()
    func()
    end_time = time.time()
    spend_time = end_time - start_time
    print('函数运行的时间为:',spend_time)
    return count_time

    with open(file='d:login.txt', mode='r+', encoding='utf-8') as f:
    data = eval(f.read())

    def login_check(func):

    def ado(*args, **kwargs):
    print('进入登录校验装饰器函数')
    if data.get('token') is not True:
    print(data.get('token'))
    n = input('请输入名字:')
    p = input('请输入密码:')

    if data.get('name') == n and data.get('passwd') == p:
    data['token'] = True
    func(*args, **kwargs)
    else:
    print('输入错误')
    else:
    func(*args, **kwargs)
    return ado

    @login_check #login = login_check(login) login指向ado函数
    @decorator # login = decorator(login) login指向count_time函数
    def login():
    time.sleep(3)
    print('这是需要被装饰的函数')

    login()
    
    

    十,类中三个装饰器

    类方法:类 实例对象都可以调用

    实例方法:类不能调用 实例可以调用

    静态方法:类 实例对象都可以调用

    class MyTest():
      def __init__(self,name):
        self.name = name @classmethod
    # 被classmethod装饰后,该方法是个类方法 def add(cls): # cls代表类本身 print('add') print(cls) def sub(self): # self代表实例本身 print(self)

      @staticmethod   
      def static():   # 静态方法是没有参数的
        pass
      
      @property
      def read_attr(self):  # 设置只读属性,防止被串改,可以像属性一样调用,注意,这里的属性不能修改,init中的属性可以被修改
        return '18' t
    = MyTest() t.add() # 类属性 类方法可以被实例调用 t.sub() #
    t.static()     # 静态方法可以被类调用
    t.read_attr    # t.read_attr()错误
    MyTest.add() # MyTest.sub() # 错误,实例方法不能被类调用
    MyTest.static() #静态方法可以被类调用
  • 相关阅读:
    C#窗体 LISTVIEW
    C#窗体布局方式
    C#窗体计算器
    操作数据库(对战小游戏)
    C#窗体
    操作数据库(数据操作类)
    操作数据库(增删改)
    操作数据库(防注入攻击)
    DO.NET操作数据库
    projecteuler Problem 9 Special Pythagorean triplet
  • 原文地址:https://www.cnblogs.com/ella-li/p/13946070.html
Copyright © 2011-2022 走看看