class Ask():
def __init__(self,choices=['y','n']): # 创建一个提问类,默认选项是y和n
self.choices = choices # 把选项保存起来
def ask(self): # 提问的方法
if max([len(x) for x in self.choices])>1: # 如果选项文字比较长(多于1个字符)
for i,x in enumerate(self.choices): # 就把选项编上号显示
print("{0}. {1}".format(i,x),flush=True) # 打印:0. 选项1,1. 选项2...
x = int(input()) # 等待用户输入数字
return self.choices[x] # 返回对应的选项
else: # 如果选项很短(比如y/n)
print("/".join(self.choices),flush=True) # 就直接显示 y/n
return input() # 等待用户输入并返回
class Content(): # 创建一个内容基类
def __init__(self,x):
self.x=x # 保存内容
class If(Content): # 创建If类,表示"如果"条件
pass # 直接继承Content类,没什么特殊
class AND(Content): # 创建AND类,表示"并且"关系
pass # 直接继承Content类
class OR(Content): # 创建OR类,表示"或者"关系
pass # 直接继承Content类
# 定义动物识别的规则库
rules = {
'default': Ask(['y','n']), # 默认的提问方式是y/n
'color' : Ask(['red-brown','black and white','other']), # 颜色有3个选项
'pattern' : Ask(['dark stripes','dark spots']), # 花纹有2个选项
# 定义什么是哺乳动物:有毛发 或者 产奶
'mammal': If(OR(['hair','gives milk'])),
# 定义什么是食肉动物:有尖牙+爪子+前视眼睛 或者 吃肉
'carnivor': If(OR([AND(['sharp teeth','claws','forward-looking eyes']),'eats meat'])),
# 定义什么是有蹄类动物:是哺乳动物 并且 (有蹄子 或者 反刍)
'ungulate': If(['mammal',OR(['has hooves','chews cud'])]),
# 定义什么是鸟:有羽毛 或者 (会飞 并且 下蛋)
'bird': If(OR(['feathers',AND(['flies','lies eggs'])])),
# 下面是具体动物的识别规则:
'animal:monkey' : If(['mammal','carnivor','color:red-brown','pattern:dark spots']),
'animal:tiger' : If(['mammal','carnivor','color:red-brown','pattern:dark stripes']),
'animal:giraffe' : If(['ungulate','long neck','long legs','pattern:dark spots']),
'animal:zebra' : If(['ungulate','pattern:dark stripes']),
'animal:ostrich' : If(['bird','long nech','color:black and white','cannot fly']),
'animal:pinguin' : If(['bird','swims','color:black and white','cannot fly']),
'animal:albatross' : If(['bird','flies well'])
}
class KnowledgeBase(): # 创建知识库类,这是最核心的部分
def __init__(self,rules): # 初始化知识库
self.rules = rules # 保存规则
self.memory = {} # 创建一个记忆字典,记住已经问过的问题答案
def get(self,name): # 获取某个特征的值
if ':' in name: # 如果名字中有冒号,比如"color:red-brown"
k,v = name.split(':') # 拆成两部分:color 和 red-brown
vv = self.get(k) # 先获取颜色到底是什么
return 'y' if v==vv else 'n' # 如果颜色匹配返回y,否则返回n
if name in self.memory.keys(): # 如果这个问题之前问过
return self.memory[name] # 直接返回记住的答案,不用再问
# 在规则库中找相关的规则
for fld in self.rules.keys():
if fld==name or fld.startswith(name+":"): # 找到匹配的规则
value = 'y' if fld==name else fld.split(':')[1] # 计算期望的值
res = self.eval(self.rules[fld],field=name) # 评估这个规则
if res!='y' and res!='n' and value=='y': # 如果得到具体动物名
self.memory[name] = res # 记住答案
return res
if res=='y': # 如果规则成立
self.memory[name] = value # 记住答案
return value
# 如果没找到对应规则,用默认方式提问
res = self.eval(self.rules['default'],field=name)
self.memory[name]=res # 记住答案
return res
def eval(self,expr,field=None): # 评估表达式
if isinstance(expr,Ask): # 如果是提问对象
print(field) # 打印问题
return expr.ask() # 调用提问方法
elif isinstance(expr,If): # 如果是If条件
return self.eval(expr.x) # 评估条件内容
elif isinstance(expr,AND) or isinstance(expr,list): # 如果是AND或者是列表
expr = expr.x if isinstance(expr,AND) else expr # 获取实际内容
for x in expr: # 遍历每个条件
if self.eval(x)=='n': # 如果有一个条件不成立
return 'n' # 整个AND就不成立
return 'y' # 所有条件都成立
elif isinstance(expr,OR): # 如果是OR关系
for x in expr.x: # 遍历每个条件
if self.eval(x)=='y': # 如果有一个条件成立
return 'y' # 整个OR就成立
return 'n' # 所有条件都不成立
elif isinstance(expr,str): # 如果是字符串
return self.get(expr) # 递归获取这个特征的值
else: # 其他未知类型
print("Unknown expr: {}".format(expr))
# 创建知识库对象,传入规则
kb = KnowledgeBase(rules)
# 开始识别动物
result = kb.get('animal')
# 打印识别结果
print(result)
这个代码每一句是什么意思,用小白能听懂的话解释一下
最新发布