大家可以先跳转到机器人那一块,上机跑一跑效果,感受一下在钻研代码,如果不会再去看我所罗列到的知识点。
做出专属于你的图灵机器人
流程:
一:剖析一下生成器对象 二:类比java讲解py中的协程
三:做出专属于你的图灵机器人
一:剖析一下生成器对象
先通过下面的例子来看一下什么是生成器?
def gen():
print ('start ..')
for i in range(3):
yield i
print ('end...')
G = gen()
#打印类型
print (type(G))
<class 'generator'>
上面表示G是一个生成器对象,我来看看里面具体有什么?
dir()函数,能够显示一个模块定义的所有成员
print(dir(G))
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
这里有很多成员,我们着重关注四个函数
- close()
- next()
- send()
- throw()
下面重点阐明:
二:类比java讲解py中的协程
如果大家有java基础,就会敏感发现上述的方法和线程是一样的。
只是在py中,我们叫他 协程,
可以认为协程是一种轻量级的线程或者微线程,可以运行多个函数,让这几个函数看起来似乎是同一时间运行,
但是比线程又有一些优点,比如不用占大量的内存,开销小,也不用考虑线程的安全
1.send()函数
send()函数用于传递参数,实现与生成器的交互,当程序运行到receive=yield时,就会被挂起(停止),等待生成器调用send方法,
这时候当外部调用send函数时,发送数据变量,数据变量就会传递到received里面
示例:
def demo():
while True:
received =yield
print('Received:{}'.format(received))
Demo = demo()
next(Demo)
Demo.send('First')
Demo.send('Second')
Received:First
Received:Second
对于生成器需要理解以下知识点:
yield :yield可以当做一个暂停/开始的信号,有yield的函数就是一个generator,yield x 整体就是一个表达式,代码运行到yield就会暂停
还有疑惑或者想深入了解可以看一下这篇文章:python yield用法总结
next():遇到表达式时暂停,返回yield表达式中的参数x,此时搁置yield表达式,再次调用next时,就会跳过yield,直接执行后面的代码
对于上述代码,做以下解释:
a).demo函数里面有一个死循环,里面有一行关键的代码,received=yield
(有yield就可以看成是生成器),这个received接受的就是函数从外部发送过来的数据
b).外部函数一开始就会生成一个构造器对象,也就是这行语句:Demo = demo()
c).最关键的就是一定要调用next这个方法,让生成器推进到第一条yield表达式
d).接下来我们就可以把yield操作和send操作结合起来,可以获取外界所输入的数据,然后用一套流程去进行处理:不断获取,不断回复
2.throw()函数
throw函数主要是向生成器发送一个异常,可以结束系统以及我们自定义的异常,并按照我们的要求输出(和java的try catch几乎一样)
我们使用以下几步来理解此方法:
- a.创建生成器对象G
- b.执行next(G)并打印结果,我们会得到第一个yield里缓存的结果’First’,并且停留在yield 'Second’之前
- c. 抛出一个异常类ValueError(注意ValueError是类不是字符串),当生成器收到异常直接跳过 yield ‘Second’进入except部分,打印出’Catch the TypeError’
- d. 执行next(G)并打印结果,我们会回到while头部,并且消耗掉第一个yield ‘Frist’,执行yield ‘Second’
示例代码如下:
def YiChang():
while True:
try:
yield 'First step'
yield 'Second step'
except TypeError:
print('Catch the TypeError')
except ValueError:
print('Catch the ValueError')
E = YiChang()
print(next(E))
E.throw(ValueError)
print(next(E))
结果如下:
First step
Catch the ValueError
Second step
3.close()函数
close用于停止生成器,如果停止之后再调用next,就会引发StopIteration错误
示例代码:
def demo():
while True :
received = yield
print('Receive:{}'.format(received))
try:
Demo = demo()
next(Demo)
Demo.close()
Demo.send('现在还能输出吗')
except (StopIteration):
print('Catch the StopIteration')
输出:
Catch the StopIteration
当生成器对象Echo调用完close()之后,再调用send(‘现在还能输出吗’)就会抛出一个异常StopIteration,然后被我们捕捉到了,没有打印出我们想要的语句,代表已经被关了
三.做出专属于你的图灵机器人
了解了上述知识点,我们通过生成器来做一个智能聊天机器人吧
- 1)创建一个聊天机器人生成器函数,可以认为是后台的一个线程函数
注意:当检索到输入包含此语句单词就会输出
def chat_robot():
res = ''
while True:
receive = yield res
if 'hi' in receive or '你好鸭' in receive or '你好' in receive or 'hello' in receive:
res = '你好鸭'
elif'名字 ' in receive or '叫啥' in receive or '称呼' in receive:
res = '我叫小国平'
elif '年龄' in receive or '多大' in receive or 'old' in receive:
res = '我十九岁啦'
elif 'sex' in receive or '性别' in receive :
res = '我是个男孩子哦~ '
elif 'from' in receive or '来自' in receive or 'where' in receive or '故乡' in receive :
res = '我来自甘肃金昌,西北汉子一枚'
elif '现在在哪读书 ' in receive or '现在在哪' in receive :
res = '我现在在湖南长沙哦'
elif '体重' in receive or '你多重呀' in receive:
res = '我的体重是65千克'
elif 'height' in receive or '身高' in receive:
res = '我的身高是 170 cm'
elif 'hobby' in receive or '爱好' in receive or '喜欢什么' in receive:
res = '我的爱好广泛哦,从笔墨中的丹青,到远方的故事,从书卷中的诗句,到未来的畅想,我有故事也有酒,只差一个听故事的你'
elif 'bye' in receive or '拜拜' in receive or '再见' in receive:
res = 'Bye bye, 期待下一次和你再见哦!'
elif 'handsome' in receive or 'beautiful' in receive or '帅气' in receive or '好看' in receive:
res = '你真帅气!你最帅气啦!'
elif 'girlfriend' in receive or '女朋友' in receive or '单身' in receive:
res = '这个问题太扎心了!'
elif 'fuck' in receive:
res = '来呀!小宝贝'
elif '怎么学' in receive:
res = '亲,推荐百度一下哦'
elif '要你干' in receive:
res = '呜呜呜,人家只能陪你聊天解闷,至于其他功能,小主人还没开发呢'
else :
res = "对不起,我不能理解你所说的,可以重新表述一下吗"
- 2).前台不断的获取用户的输入,然后利用协程发送给后台处理
Chat = chat_robot()
next(Chat)
while True:
mess = input('Please input:')
if mess == 'q' or mess == 'Q':
print( 'Robot exit..')
break
response = Chat.send(mess)
print('Robot:{}'.format(response))
if 'Bye bye' in response:
break
Chat.close()
大家可以改一下自己的语料库,就做出专属于自己的聊天机器人啦