Python笔记(14)-高级特性

迭代iteration

判断一个对象可迭代:

通过for循环来遍历

[root@centos01 python]# cat test.py 
#!/usr/bin/env python
# coding:utf-8
s="hello"
for i in s:
    print i
[root@centos01 python]# python test.py 
h
e
l
l
o
[root@centos01 python]# cat test.py 
#!/usr/bin/env python
# coding:utf-8
s = 1
for i in s:
    print i
[root@centos01 python]# python test.py 
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    for i in s:
TypeError: 'int' object is not iterable

通过collections模块的iterable类型判断

#isinstance() 函数来判断一个对象是否是一个已知的类型

In [1]: from collections import Iterable

In [2]: isinstance('abc',Iterable)
Out[2]: True

In [3]: isinstance({"name":"vaon"},Iterable)
Out[3]: True

In [4]: isinstance([123],Iterable)
Out[4]: True

In [5]: isinstance((1,2,3),Iterable)
Out[5]: True

In [6]: isinstance(1,Iterable)
Out[6]: False

列表生成式

for循环

输出1-10之间所有整数求平方之后的结果

In [9]: [i**2 for i in range(1,11)]
Out[9]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

for循环+if语句

输出1-10之间所有整数求平方,再跟2取余为0的结果

In [11]: [i**2 for i in range(1,11) if (i**2)%2 == 0]
Out[11]: [4, 16, 36, 64, 100]

for循环+for循环

输出'abc'和'123'的全排列

In [12]: [i+j for i in "abc" for j in "123"]
Out[12]: ['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']

扩展

列出当前目录下的所有.py文件或目录

#os.listdir(".")表示列出当前目录下所有文件、目录

#i.endswith(".py")判断字符串是否以.py后缀结尾,如果以指定后缀结尾返回True,否则返回False

In [26]: [i for i in os.listdir(".") if i.endswith(".py")]
Out[26]: ['check_bool.py', 'function.py', 'test.py']

练习1

给定一个正整数,编写程序计算有多少对质数的和等于输入的这个正整数,并输出结果。输入值小于1000。如,输入为10, 程序应该输出结果为2。(共有两对质数的和为10,分别为(5,5),(3,7))

#!/usr/bin/env python
# coding:utf-8
shuru=input("输入一个正整数(<=1000):")
def zhishu(num):
    for i in range(2,num):
        if num%i == 0:
            return False
    else:
        return True
 
p=[i for i in range(2,shuru) if zhishu(i)]
 
peidui=[(m,n) for m in p for n in p if m+n == shuru and m <= n]
print len(peidui)

生成器generator

背景

通过列表生成式,可以直接创建一个列表(list):

In [2]: [i for i in range(1,10)]
Out[2]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

受到内存限制,列表容量肯定是有限的,例如创建一个包含 100 万个元素的列表,会占用很大的存储空间,创建过程有可能使电脑卡住。

定义

在循环的过程中不断由前一个元素推算出后一个元素,但是后续元素并不立刻生成出来。这样就不必创建完整的 list,从而节省大量的空间。在 Python 中,这种一边循环一边计算的机制,称为生成器(Generator)

使用生成器的方式

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

In [3]: g=(i for i in range(1,10000000))

In [4]: g
Out[4]: <generator object <genexpr> at 0x7f9d83652dc0>

调用:

使用.next()

每调用一次显示一个元素

In [5]: g=(i for i in range(1,4))

In [6]: g.next()
Out[6]: 1

In [7]: g.next()
Out[7]: 2

In [8]: g.next()
Out[8]: 3

In [9]: g.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-9-d7e53364a9a7> in <module>()
----> 1 g.next()

StopIteration: 

使用for循环

In [10]: g=(i for i in range(1,4))

In [11]: for i in g:
   ....:     print i
   ....:     
1
2
3

2.yield用法

如果函数里面有yield关键字,那么调用这个函数的结果赋值给的变量为生成器

当生成器g调用第一个next方法时,会运行函数,直到遇到第一个yield停止

当调用第二个next方法时,会从停止的地方继续执行,直到遇到下一个yield

#!/usr/bin/env python
# coding:utf-8
def fun():
    print "1."          #输出"1."
    yield "第一个yield"  #遇到yield停止,yield后面跟的内容可以在print g.next()时显示出来
    print "2."
    yield "第二个yield"
    print "3."
    yield "第三个yield"
    print "4."
    yield "第四个yield"
 
g = fun()
print g.next()
print g.next()
print g.next()
print g.next()

执行结果:

[root@centos01 python]# python test.py
1.
第一个yield
2.
第二个yield
3.
第三个yield
4.
第四个yield

练习1:

Fibonacci(斐波纳契)数列,除第一个和第二个数外,任意一个数都可由前两个数相加得到:1, 1, 2, 3, 5, 8, 13, 21,...,本题要求生成6个数即可

#!/usr/bin/env python
# coding:utf-8
def fib(max):    #max为最终生成fib数列个数
    n,a,b = 0,0,1   #n代表当前fib数列个数,a代表n-1的值,b代表n的值
    while n < max:
        yield b     #当前第一个数列
        a,b = b,a+b
        n += 1
 
g = fib(6)   #变量g就是生成器

for i in g:
    print i

输出结果:

[root@centos01 python]# python test.py
1
1
2
3
5
8

3.send用法

使用send方法给生成器函数发送数据

使用send方法前,必须先调用一次next()方法

遇到下一个yield停止

#!/usr/bin/env python
# coding:utf-8
def fun():
    print "start"
    num1 = yield
    print num1
    num2 = yield
    print num2

g = fun()   #g是生成器 
g.next()    #使用send方法前,必须先调用一次next()方法
g.send(1)   #将1发送给变量num1,此时num1=1
g.send(11)  #将11发送给变量num1,此时num1=11

 执行结果:

[root@centos01 python]# python test.py
start
1
11
Traceback (most recent call last):
File "test.py", line 13, in <module>
g.send(11) #将11发送给变量num1,此时num1=11
StopIteration

#!/usr/bin/env python
# coding:utf-8
def fun():
    print "one"
    num1 = yield "sss"
    print num1
    num2 = yield
    print num2

g = fun()   #g是生成器
g.next()    #这里先打印"one",代码执行到num1 = yield "sss"停止,g.next()存储yield后面的内容
print g.send("hello")   #从上次yield停止的地方继续执行,将"hello"发送给num1,打印出num1的值,执行到num2 = yield停止,g.send()存储yield后面的内容,由于这里为空,所以此时g.send()=None

执行结果:

[root@centos01 python]# python test.py
one
hello
None

练习1:

生产者-消费者(producer-consumer)模型,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的 缓冲区。其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。问题出现在当缓冲区已经满了,而此时生产者还想向其中放入 一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。同样地,当缓冲区已经空了,而消费 者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。

#!/usr/bin/env python
# coding:utf-8
import time  #调用time内置模块
food = []    #定义一个food列表,模拟包子店的所有包子
def consumer(name):
    print "%s准备买包子" %(name)
    while True:
        baozi_name = yield
        print "客户[%s]买了[%s]馅的包子" %(name,baozi_name)
        food.remove(baozi_name)  #当客户买了这个馅的包子就从列表中删除
def producer(name,*kind):  #*kind表示使用函数中的可变参数
    c1 = consumer("路飞")
    c1.next()
    print "%s准备制作包子..." %(name)
    for i in kind:
        time.sleep(3)  #表示休眠3秒,模拟厨师制作包子过程
        print "厨师[%s]做了[%s]馅包子" %(name,i)
        food.append(i)  #厨师制作了这个馅的包子就在列表中加入        
        c1.send(i)
 
producer("白胡子","牛肉","韭菜","豆沙")

 练习2:

简易聊天机器人

# coding:utf-8
def chat_robot():
    res = ""    #由于在使用.next()时会将遇到的第一个yield后面的内容保存到.next()中,因此必须给.next()一个值,否则会报错
    while True:
        receive = yield res
        if "hi" in receive or "hello" in receive:
            res = "你好"
        elif "名字" in receive or "name" in receive:
            res = "我是小冰"
        elif "年龄" in receive or "age" in receive:
            res = "18"
        elif "再见" in receive or "bye" in receive:
            res = "回聊"
        else:
            res = "我不懂你在说什么"

Chat = chat_robot()  #Chat时生成器
Chat.next()          #使用send方法前,必须先调用一次next()方法
while True:
    your_said = raw_input("客户>>:")
    if your_said.lower() == 'q':    #.lower()表示无论大写小写都转换为小写
        print "robot exit..."
        break
    response = Chat.send(your_said)
    print "小冰>>:%s" %(response)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值