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) # 196.私有化函数
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')