property属性就是负责把类中的一个方法当作属性进行使用,可以简化代码
class Person(object): def __init__(self): self.__age =0 @property def age(self): return self.__age @age.setter def age(self,new_age): self.__age = new_age p=Person() print(p.age) p.age=100 print(p.age)
property的参数
第一个参数是获取属性是要执行的方法
第二个参数是设置属性时要执行的方法
定义property属性有两种方式:1、装饰器方式 2、类属性方式
装饰器方式:1、property修饰获取值的方法
2、@方法名。setter修饰设置值的方法
类属性方式
1、property属性=property(获取值方法,设置值方法)
class Person(object): def __init__(self): self.__age = 0 def get_age(self): return self.__age def set_age(self,new_age): if new_age>=150: print("年龄错误") else: self.__age=new_age age = property(get_age,set_age) p=Person() print(p.age) # 设置属性 p.age=100 print(p.age)
python提供了with语句用于简化资源释放的操作,使用with语句操作建立在上下文管理器(实现 __ enter __ 和 __ exit __ 方法)的基础上
class File(object): def __init__(self,file_name,file_model): self.file_name = file_name self.file_name= file_model 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 File("1.txt","r") as f: file_data=f.read() print(file_data)
根据程序设计者指定的规则循环生成数据,当条件不成立时则生成数据结束。
数据不是一次性全部生成出来,而是使用一个,再生成一个,可以节约大量的内存
与列表推导式类似,只不过生成器推导式使用小括号
data = (x for x in range(100)) next(data) for i in data: print(i)
生成器相关函数
next函数获取生成器中的下一个值
for循环遍历生成器中的每一个值
yield关键字生成器的特征:在def函数中具有yield关键字
def mygenerater(n): for i in range(n): print('开始生成....') yield print('完成一次.....') g= mygenerater(5) # print(next(g)) # print(next(g)) # print(next(g)) for i in g: print(i)
1、代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
2、生成器如果把数据生成完成,再次获取生成器中的下一个数据会抛出一个StopIteration异常,表示停止迭代异常
3、while循环内部没有处理异常操作,需要手动添加处理异常操作
4、for 循环内部自动处理了停止迭代异常,使用起来更加方便,推荐使用
(前面两个数字相加) 1、2、3、5、8、13、21.。。。。。
def fb(num): a =0 b=1 index =0 while index< num: result = a a,b = b,a+b yield result index +=1 f=fb(8) for i in f: print(i)
1、生成器时根据算法生成数据的一种机制 ,每次调用生成器只生成一个值,可以节省大量内存
2、生成器的创建
copy函数时浅拷贝,只对可变类型的第一层对象进行拷贝
对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象
#普通赋值 import copy a =[1,2,3] b=[11,22,33] c =[a,b] d=c print(id(d)) print(id(c)) #浅拷贝可变类型 import copy a =[1,2,3] b=[11,22,33] c =[a,b] d=copy.copy(c) print(id(d)) print(id(c)) #浅拷贝、深层数据 import copy a =[1,2,3] b=[11,22,33] c =[a,b] d=copy.copy(c) print(id(a)) print(id(c[0])) print(id(d[0])) #浅拷贝不可变类型 import copy a =[1,2,3] b=[11,22,33] c =(a,b) d=copy.copy(c) print(id(a)) print(id(c[0])) print(id(d[0]))
对每一层拷贝对象都会开辟新的内存空间进行存储
# 深拷贝,可变数据 import copy a =[1,2,3] b=[11,22,33] c =[a,b] d=copy.deepcopy(c) # print(id(a)) print(id(c)) print(id(d)) # 深拷贝,深层数据 import copy a =[1,2,3] b=[11,22,33] c =(a,b) d=copy.deepcopy(c) print(id(a)) print(id(c[0])) print(id(d[0])) #深拷贝不可变类型 import copy a =(1,2,3) b=(11,22,33) c =(a,b) d=copy.deepcopy(c) print(id(c)) print(id(d))
作用:1、函数名存放的是函数所在空间的地址
2、函数名()执行函数名所存放空间地址中的代码
3、如下func01=func02函数名可以像普通变量一样赋值,func01()等价于func0()
def func01(): print("func01 is show") def foo(func): func() foo(func01)
闭包可以保存函数内的变量,不会随着函数调用完而销毁
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数成为闭包。
1、在函数嵌套
2、内部函数使用了外部函数的变量
3、外部函数返回了内部函数
def config_name(name): def say_info(info): print(name + ":" , info) return say_info tom =config_name("tom") tom("你好") tom("你在么") jerry = config_name("jerry") jerry("你好") jerry("我在呢")
6.5、修改闭包
修改闭包内使用的外部变量使用nonlocal关键字完成
def func_out(num1): def func_inner(num2): nonlocal num1 num1 = num2 + 10 print(num1) func_inner(10) print(num1) return func_inner f=func_out(10) f(10)
在不改变原有函数的源代码的情况下,给函数增加新的功能
装饰器符合了开发中的封闭原则
本质上相当于是一个闭包
装饰器的语法格式
def check(fn): def inner(): print("登录验证。。。。") fn() return inner #解释器遇到@check 会立即执行comment = check(comment) @check def comment(): print("发表评论") #comment = check(comment) comment()
使用场景:函数执行时间统计
import time def get_time(fn): def inner(): start = time.time() fn() end = time.time() print("时间:",end-start) return inner @get_time def func(): for i in range(10000): print(i) func()
装饰器作用:在不改变已有函数源代码及调用方式的前提下,对已有函数进行功能的扩展
def logging(fn): def inner(a,b): fn(a,b) return inner @logging def sum_num(a,b): result = a + b print(result) sum_num(1,2)
def logging(fn): def inner(a,b): result=fn(a,b) return result return inner @logging def sum_num(a,b): result = a + b return result result = sum_num(1,2) print(result)
def logging(fn): def inner(*args, **kwargs): fn(*args, **kwargs ) return inner @logging def sum_num(*args, **kwargs): print(args,kwargs) sum_num(1, 2,3,age=18)
def check1(fn1): def inner1(): print("登录验证") fn1() return inner1 def check2(fn2): def inner2(): print("登录验证2") fn2() return inner2 @check2 @check1 def comment(): print("发表评论") comment()
离函数最近的装饰器先装饰,然后外面的装饰器再装饰,由内到外的装饰过程
使用装饰器装饰函数的时候可以传入指定参数
语法:@装饰器(参数。。。。)
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)
带参数的装饰器
1、装饰器的外部函数只接受一个参数—被装饰的函数
2、需要给装饰器传参数需要在装饰器外部再增加一个函数
__ call __ 方法的使用
一个类里面一旦实现了 __ call __ 方法
那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用
class Check(object): def __init__(self,fn): self._fn = fn def __call__(self, *args, **kwargs): print("我是call方法") self._fn() @Check def comment(): print("发表评论") comment()