闭包与装饰器

1.闭包:

闭包函数是什么时候产生的?

当内部函数引用了外部函数的变量时,确保内部函数的引用外部值的正确性,																						

此时产生闭包函数。

闭包函数:内部函数+外部引用

外部函数装饰其它函数时,外部函数被调用,并返回内部函数对象,最终由被

装饰函数名指向。这一个过程也会产生闭包函数。

2.变量作用域:

内部函数和外部函数的关系? 

 	包含与被包含

	内部函数可持有外部函数的引用或变量

	函数内部存在作用域, 而if/while/for/with是不存在作用域。

	内部函数不能被其它的函数或模块直接调用,可以由外部函数返回

3.局部变量与全局变量:

	定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作域。

	局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内

	访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

	global:声明变量为全局变量	nonlocal:声明变量为局部变量

4.函数的封装:

广义的封装:函数的定义和类的提取,都是封装的体现

狭义的封装:在面向对象编程中,一个类的某些属性,在使用的过程中,如果不希望

被外界【直接】访问,就可以将该属性封装【将不希望被外界直接访问的属性私有

化private,该属性只能被当前类持有,此时可以给外界暴露一个访问的函数即可】

封装的本质:就是属性私有化的过程

公开属性:可以在类以外的任何地方直接访问

私有属性:只能在类的内部被直接访问	在对象属性的前面添加两个下划线

5.私有化属性的访问:

在类外面访问属性,无非涉及到两个操作:获取值,修改值

# 封装函数返回被私有化属性的值
class Person1():
    def __init__(self, name, age):
        self.__name = name
        self.__age = age
	
    # 获取值
    def getname(self):
        return self.__name
	
    # 修改值
    def setname(self, name):
        self.__name = name
	
    # 获取值
    def getage(self):
        return self.__age
	
    # 修改值
    def setage(self, age):
        if age < 0:
            age = abs(age)
        self.__age = age

p1 = Person1("111", 11)

# 获取值
r1 = p1.getname()
print(r1)			# r1 = '111'
r2 = p1.getage()
print(r2)			# r2 = 11

# 修改值
p1.setname("jack")
print(p1.getname())	 # 'jack'
p1.setage(-19)
print(p1.getage())	 # 19

# property装饰器
# @property将一个函数转换为属性调用,为了简化函数的调用,函数名本身表示指定函数的返回值
class Check():
    @property
    def show(self):
        print('ok')
        # 注意:如果函数被@property修饰,最好设置返回值
        return 10

    
c = Check()
# c.show()  #TypeError: 'str' object is not callable
print(c.show)  # 10
------------------------------------------------------------------------
@property
def func():
    pass
print(func)  # <property object at 0x000002441A234228>

# @property和@xxx.setter

"""
为了简化函数的调用,Python中通过@property和@xxx.setter分别修改两个函数
注意:
    a.两个函数的函数名尽量和被私有化的属性名保持一致
    b.@xxx.setter中的xxx需要和被@property修饰的函数名保持一致
    c.@property修饰的函数用于获取值,@xxx.setter修饰的函数用于传值修改值
    d.@property和@xxx.setter并不是需要同时出现,根据自己的需求进行选择
        @property出现,@xxx.setter可以不出现
        @xxx.setter出现,@property必须出现
"""

class Person2():
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
        
    # 获取值:将被私有化属性的值返回
    @property
    def name(self):
        return self.__name
    # 修改值:设置参数
    @name.setter
    def name(self,name):
        self.__name = name

    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        if age < 0:
            age = abs(age)
        self.__age  = age
        
        
p2 = Person2("222", 22)

# 获取值
r3 = p2.name
print(r3)  # r3 = '222'
r4 = p2.age
print(r4)  # r4 = 22

# 修改值
p2.name = "jack"
print(p2.name)  # 'jack'
p2.age = -19
print(p2.age)  # 19

6.私有化函数

class Person3():
    def func(self):
        # 间接调用
        self.__show()
        
    def __show(self):
        print("show")


p3 = Person3()

p3.func()

7.装饰器函数

import time

def runtime(func):
    def wrapper(*args, **kwargs):
        # 在调用目标函数(被装饰函数)之前
        start_time = time.time()
        ret = func(*args, **kwargs)  # 闭包函数中的引用(被装饰的函数)
        # 执行函数并获取返回结果之后
        print('用时 %.3f 秒' % (time.time()-start_time))
    return wrapper
    

@runtime
def download(url):  # 产生闭包函数, download => wrapper+download引用
   print('downloading ', url)
  
@runtime
def parse(url, html):  # 产生闭包函数
   print(url, html)
   
   
download('http://www.baidu.com')  # 调用闭包函数
parse(html='<h1>haha</h1>',url='http://jd.com')

# 有参的装饰器函数

import os

def exists(file, error=True):
    def outer(func):
        def wrapper(*args, **kwargs):
            if not os.path.exists(file):
                if error: raise Exception('%s 文件不存在' % file)
                return None
            return func(*args, **kwargs) # 闭包函数被执行后的返回结果
        return wrapper  # 作用:准备产生闭包函数
    return outer  # 作用: 接收被装饰函数对象


@exists('a.txt',error=False)
def write(content):
   with open('a.txt', 'a', encoding="utf-8") as f:
      f.write(content)
      print('writted')

@exists('b.txt')
def read():
    with open('b.txt',encoding='utf-8') as f:
        print(f.read())

8.装饰器类

import time 
class Runtime():
    def __init__(self, func):
        self.func = func
        
    def __call__(self, *args, **kwargs):
        start_time = time.time()
        ret = self.func(*args, **kwargs)
        print('用时 %.3f 秒' % (time.time()-start_time))
        return ret

# 闭包函数产生的过程: 
# 1. 调用Runtime()实例化方法,将print_pdf函数传入作为初始化参数传入, 返回Runtime类的实例对象
# 2. print_pdf 指向 Runtime的实例对象
# eg :  print_pdf = Runtime(print_pdf)
@Runtime
def print_pdf(pdf):
    print('printing ', pdf)
    

@Runtime
def save_db(sql, args):
    print('---->正在处理数据-->')
    time.sleep(0.2)
    print(sql, args)
    
    
print_pdf('aa.pdf')  # 调用Runtime实例对象-> __call__实例方法

# 有参的装饰器类

import random
GET, POST, PUT, DELETE = 1, 2, 4, 8


class CheckQX():
   def __init__(self, qx=1):
      self.qx = qx
    
   def __call__(self, func):
      def wrapper(*args, **kwargs):
            print('验证当前用户是否具有权限值:', self.qx)
            # 模拟当前会话中的用户权限值 
            current_user_qx = random.randint(0, 15) # [0, 15]
            # 12-> 8+4
            if current_user_qx & self.qx == self.qx:
                ret = func(*args, **kwargs)
                return ret
            else:
                print('当前用户的权限', current_user_qx, '不具有', self.qx, '权限')
      
      return wrapper
    
# query_all_user = CheckQX(GET)(query_all_user)
@CheckQX(GET)
def query_all_user():
    print('select all user')
    print('Ok')
    
@CheckQX(DELETE)    
def delete_user(user_id):
    print('deleting user : ', user_id)
    print('Ok')
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值