可以保存函数内变量,不会随着函数调用完而销毁
# 1.在函数嵌套(函数中定义函数)的前提下
def func_out(num1):
def func_inner(num2):
# 2.内部函数使用了外部函数的变量
num = num1 + num2
print(f"num的值为:{num}")
# 3.外部函数返回了内部函数
return func_inner
# 创建闭包实例
f = func_out(10)
# 执行闭包
f(6) # 打印 num的值为:16
# 1.在函数嵌套(函数中定义函数)的前提下
def func_out(num1):
def func_inner(num2):
# 声明外部变量
nonlocal num1
# 2.内部函数使用了外部函数的变量
num1 += num2
print(f"num1的值为:{num1}")
# 3.外部函数返回了内部函数
return func_inner
# 创建闭包实例
f = func_out(10)
# 执行闭包
f(8) # 打印 num的值为:18
也是一种闭包,可在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能
# 定义一个装饰器
def remind(func):
# 为目标函数增加新功能
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
# 需要被装饰的函数
def sleep():
import random
import time
print("睡眠中...")
time.sleep(random.randint(1, 5))
# 未装饰
sleep()
# 打印
# 睡眠中...
# 使用装饰器装饰函数(增加睡前起床提醒)
# 返回增强后的inner函数
fn = remind(sleep)
fn()
# 打印
# 我睡觉了
# 睡眠中...
# 我起床了
@装饰器名字
,解释器碰到时会自动执行装饰过程,简化使用流程# 定义一个装饰器
def remind(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
# 需要被装饰的函数
# 解释器遇到@remind 会立即执行 sleep = remind(sleep)
@remind
def sleep():
import random
import time
print("睡眠中...")
time.sleep(random.randint(1, 5))
# 通过语法糖注解,直接调用即可达到效果
sleep()
# 打印
# 我睡觉了
# 睡眠中...
# 我起床了
# 定义装饰器1
def remind(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
# 定义装饰器2
def study(func):
def inner():
func()
print("我要敲代码啦")
return inner
# 谁近谁先装饰
@study # 2.执行 sleep = study(remind(sleep))
@remind # 1.执行 sleep = remind(sleep)
def sleep():
import random
import time
print("睡眠中...")
time.sleep(random.randint(1, 5))
sleep()
# 打印
# 我睡觉了
# 睡眠中...
# 我起床了
# 我要敲代码啦
# 第一层:用于接收装饰器传递的参数
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)
__call__
方法,那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用# 定义类
class Login:
def __call__(self, *args, **kwargs):
print("登录中。。。")
# 创建实例
login = Login()
# 如函数般调用
login() # 打印 登录中。。。
call
方法实现# 定义类装饰器
class Check:
# 接收待装饰的函数
def __init__(self, fn): # fn = comment
self.__fn = fn
def __call__(self, *args: object, **kwargs: object) -> object:
print("登录")
self.__fn() # comment()
# 被装饰的函数
@Check # comment = Check(comment)
def comment():
print("发表评论")
comment()
把类中的一个方法当作属性进行使用,简化开发
例如我们如果想获取和修改私有属性必须通过类方法修改,示例代码:
class Person:
def __init__(self):
self.__age = 18
def age(self):
return self.__age
def set_age(self, new_age):
self.__age = new_age
p = Person()
age = p.age()
print(f"修改前年龄是:{age}") # 打印 修改前年龄是:18
p.set_age(66)
age = p.age()
print(f"修改后年龄是:{age}") # 打印 修改后年龄是:66
@property
表示把方法当作属性使用,表示当获取属性时执行下面修饰的方法@方法名.setter
表示把方法当作属性使用,表示当设置属性值时会执行下面修饰的方法class Person:
def __init__(self):
self.__age = 18
@property
def age(self):
return self.__age
@age.setter
def age(self, new_age):
self.__age = new_age
p = Person()
# 可直接通过对象.属性使用
print(f"修改前年龄是:{p.age}") # 打印 修改前年龄是:18
p.age = 66
print(f"修改后年龄是:{p.age}") # 打印 修改后年龄是:66
property
的参数说明:class Person:
def __init__(self):
self.__age = 18
def get_age(self):
return self.__age
def set_age(self, new_age):
self.__age = new_age
# 类属性方式的property属性
age = property(get_age, set_age)
p = Person()
print(f"修改前年龄是:{p.age}") # 打印 修改前年龄是:18
p.age = 66
print(f"修改后年龄是:{p.age}") # 打印 修改后年龄是:66
由实现了__enter__()和__exit__()方法的类创建的对象
with语句
可以自动调用关闭文件操作,即使出现异常也会自动调用关闭文件操作。with open("guanzhi.txt", "w") as f:
f.write("hello world")
# 定义一个File类
class File:
def __init__(self, file_name, file_model):
self.file_name = file_name
self.file_model = file_model
# 实现__enter__()和__exit__()方法
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语句来完成文件操作
with File("1.txt", "w") as f:
f.write("hello world")
开辟新的内存空间接收变量
id()
可获得变量的内存地址copy函数
进行浅拷贝,只对可变类型的第一层对象进行拷贝对拷贝的对象开辟新的内存空间进行存储
不会拷贝对象内部的子对象
import copy
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
# 普通赋值,指向同一空间
d = c
print(f"c内存地址:{id(c)}") # 打印 c内存地址:2265505547072
print(f"d内存地址:{id(d)}") # 打印 d内存地址:2265505547072
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
# 浅拷贝,指向不同空间
d = copy.copy(c)
print(f"c内存地址:{id(c)}") # 打印 c内存地址:2265505547648
print(f"d内存地址:{id(d)}") # 打印 d内存地址:2265505548608
# 不会拷贝对象内部的子对象
print(id(a)) # 打印 2135734964288
print(id(c[0])) # 打印 2135734964288
print(id(d[0])) # 打印 2135734964288
a = (1, 2, 3)
b = (11, 22, 33)
c = (a, b)
# 浅拷贝效果与普通赋值一样
d = c
e = copy.copy(c)
print(f"c内存地址:{id(c)}") # c内存地址:1536064302016
print(f"d内存地址:{id(d)}") # d内存地址:1536064302016
print(f"e内存地址:{id(e)}") # e内存地址:1536064302016
保障数据的独立性
使用deepcopy函数进行深拷贝,会对可变类型内每一层可变类型对象进行拷贝,开辟新的内存空间进行存储
import copy
a = [1, 2, 3]
b = [11, 22, 33]
c = [a, b]
d = copy.deepcopy(c)
print(f"c内存地址:{id(c)}") # 打印 c内存地址:2603978212160
print(f"d内存地址:{id(d)}") # 打印 d内存地址:2603978215488
# 内部的可变类型也会拷贝
print(id(a)) # 打印 2603978215104
print(id(c[0])) # 打印 2603978215104
print(id(d[0])) # 打印 2603978212992
a = (1, 2, 3)
b = (11, 22, 33)
c = (a, b)
d = copy.deepcopy(c)
print(f"c内存地址:{id(c)}") # 打印 c内存地址:1312354282432
print(f"e内存地址:{id(d)}") # 打印 e内存地址:1312354282432
eval()
函数可将字符串当成有效的表达式来求值并返回计算结果# 基本的数学运算
res = eval("(1+9)*5")
print(res)
# 打印 50
# 字符串重复
res = eval("'*'*10")
print(res)
# 打印 **********
# 字符串转换成列表
print(type(eval("[1,2,3,4]")))
# 打印 <class 'list'>
# 字符串转成字典
print(type(eval("{'name':'guanzhi','age':20}")))
# 打印 <class 'dict'>
用户可能恶意输入有危害的终端指令
input_str = input() # 输入 __import__('os').system('rm -rf /*')
eval(input_str) # 直接运行可能导致主机崩溃
# 等价于
import os
os.system("终端命令")
阅读量:1037
点赞量:0
收藏量:0