day21(python高级编程,property属性,生成器,迭代器,闭包,装饰器)

属性property

私有属性添加getter和setter方法

对于类对象的私有属性,我们不能直接调用,可以添加方法来调用。

class Person:

    def __init__(self):

        pass

    def setAge(self,age):

        if 0<=age<=100:

            self.__age = age

        else:

            self.__age = 16

            print('输入的年龄不符合')

    def getAge(self):

        return self.__age

p1 = Person()

p1.setAge(10)

print(p1.getAge())

p1.setAge(200)

print(p1.getAge())

结果:

10

输入的年龄不符合

16

使用property升级getter和setter方法

class Person:

    def __init__(self):

        pass

    def setAge(self,age):

        if 0<=age<=100:

            self.__age = age

        else:

            self.__age = 16

            print('输入的年龄不符合')

    def getAge(self):

        return self.__age

        age = property(getAge,setAge)

p1 = Person()

p1.age = 10

print(p1.age)

p1.age = 200

print(p1.age)

结果:

10

入的年龄不符合

16

使用property取代getter和setter方法

class Person:

    def __init__(self):

        pass

    @property

    def age(self):

        return self.__age

    @age.setter

    def age(self,age):

        if 0<=age<=100:

            self.__age = age

        else:

            self.__age = 16

            print('输入的年龄不符合')

p1 = Person()

p1.age = 10

print(p1.age)

p1.age = 200

print(p1.age)

结果:

10

输入的年龄不符合

16

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

创建生成器

1.把列表生成式的[]改成()

如:

[ x*2 for x in range(5)]

改为:

( x*2 for x in range(5))

如果想要打印,可以通过next()获取生成器的下一个返回值,而且,generator也是可迭代的,所以也可以用循环遍历。

2.有的比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

可以用yield

例如:

def fib(num):

    a,b = 0,1

    while num>0:

        yield b

        a,b = b,a+b

        num-=1


f = fib(5)

print(' ',next(f))

print(' ',next(f))

for i in f:

    print(i)

在上面fib 的例子,我们在循环过程中不断调用 yield ,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。同样的,把函数改成generator后,我们基本上从来不会用 next() 来获取下一个返回值,而是直接使用 for 循环来迭代。

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中。

send:

执行到yield时,gen函数作用暂时保存,返回i的值;temp接收下次c.send("python"),send发送过来的值,c.next()等价c.send(None)。

def nums():

    for i in range(10):

        ret = yield i

        if ret == '平方':

            print(i**2)

        elif ret == '立方':

            print(i**3)

num = nums()

print(num)

print(next(num))

print(next(num))

print(next(num))

print(next(num))

print(next(num))

print('----------')

num1 = nums()

next(num1)

num1.send('平方')

num1.send('平方')

num1.send('平方')

num1.send('立方')

num1.send('立方')

num1.send('立方')

__next__:作为一个魔法方法,__next__等价于next()

生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。

生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

生成器的特点:

节约内存

迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的

迭代器

迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

可迭代对象

以直接作用于 for 循环的数据类型有以下几种:

一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;

一类是 generator ,包括生成器和带 yield 的generator function。

这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。

判断是否可以迭代

可以使用 isinstance() 判断一个对象是否是 Iterable 对象:

from collections import Iterable,Iterator

def f():

    yield 'hello'

print(isinstance(f(),Iterable))

print(isinstance(f(),Iterator))

print(isinstance('abc',Iterable))

print(isinstance('abc',Iterator))

迭代器

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

可以使用 isinstance() 判断一个对象是否是 Iterator 对象。

iter()函数

生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。

把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数。

name = 'abc'

myIter = iter(name)

print(type(myIter))

print(isinstance(myIter,Iterator))

try:

    print(next(myIter))

    print(next(myIter))

    print(next(myIter))

    print(next(myIter))

except StopIteration as ex:

    print('迭代完了,%s'%ex)

闭包

函数引用

闭包概念:

在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。

def test(number):

    '''

    在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,

    那么将这个函数以及用到的一些变量称之为闭包

    '''

    def test_in(number_in):

        print("in test_in 函数, number_in is %d"%number_in)

        return number+number_in

    #其实这里返回的就是闭包的结果

    return test_in

#给test函数赋值,这个20就是给参数number

ret = test(20)

#注意这里的100其实给参数number_in

print(ret(100))

#注意这里的200其实给参数number_in

print(ret(200))

闭包思考:

1.闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成

2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存

装饰器

装饰器,功能就是在运行原来功能基础上,加上一些其它功能,比如权限的验证,比如日志的记录等等。不修改原来的代码,进行功能的扩展。

比如java中的动态代理,python的注解装饰器

其实python的装饰器,是修改了代码。

def login(func):

    def inner(a,b):

        user = input('请输入用户名:')

        psd = input('请输入密码:')

        if user == a and psd == b:

            print('Welcome in!')

            func(a,b)

        else:

            print('Passward error!')

    return inner

@login

def f1(nowHaveUser,nowHavePsd):

print('f1')

def f2():

print('f2')

def f3():

print('f3')

def f4():

print('f4')

f1('haha','123456')


python解释器就会从上到下解释代码,步骤如下:

1.def login(func): ==>将login函数加载到内存

2.@login

没错, 从表面上看解释器仅仅会解释这两句代码,因为函数在 没有被调用之前其内部代码不会被执行。

从表面上看解释器着实会执行这两句,但是@login这一句代码里却有大文章,@函数名 是python的一种语法糖。

上例@login内部会执行一下操作:

执行login函数

执login1函数 ,并将@login下面的函数作为login函数的参数,即:@login等价于login(f1)所以,内部就会去执行。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 1.1==,is的使用 ·is是比较两个引用是否指向了同一个对象(引用比较)。 ·==是比较两个对象是否相等。 1...
    TENG书阅读 721评论 0 0
  • 基础1.r''表示''内部的字符串默认不转义2.'''...'''表示多行内容3. 布尔值:True、False(...
    neo已经被使用阅读 1,658评论 0 5
  • 住的这个小区也建好几年了,怎么周围一直在装修,钻啊钻啊。于是开大音乐,挡住钻的声音,周期性重复的声音实在是乱人心绪...
    KevinCool阅读 815评论 1 1
  • 今晚吃秘鲁菜,酸酸辣辣的味道,一不留神吃多了。席间,突然想起已经两年多没有跟纳豆先生说:我从明天开始减肥这句话了...
    疯小虾阅读 857评论 11 11
  • 有时候当被别人说到“你变了”之类的话,总是会不由自主的感到紧张焦虑 紧张别人说起自己的变是怎样一种口吻和态度,更怕...
    艺妹哦耶耶阅读 450评论 1 2