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')