1

好的,这是我的困境:

我正在为 subreddit 开发一个常见问题解答机器人。我在布尔逻辑方面遇到了麻烦,可以使用一双更有经验的眼睛(这是我在 Python 中的第一次冒险)。现在,机器人基本上是在向我创建的测试 subreddit 发送垃圾邮件。而不是分享特定信息,这里有一个例子,它显示了我遇到的确切问题:

#Define Key Words
##################################
#System Requirements Definitions
sysReq1 = ('system requirements' and '?')
sysReq2 = ('can' and ('handle' or 'play' or 'run') and ('netbook' or 'notebook' or 'pc' or 'mac' or 'macbook' or 'laptop' or 'comp' or 'computer') and '?')
#System Requirements Response
sysReqResponse = 'PROGRESS'
##################################
testString1 = "i hate this"
#intended result for 1: nothing
testString2 = "is that real?"
#intended result for 2: nothing
testString3 = "What are the system requirements?"
#intended result for 3: 'PROGRESS'
print testString1
if (sysReq1 or sysReq2) in testString1.lower():
    print sysReqResponse
print testString2
if (sysReq1 or sysReq2) in testString2.lower():
    print sysReqResponse
print testString3
if (sysReq1 or sysReq2) in testString2.lower():
print sysReqResponse

当你运行它时,它会显示:

i hate this
is that real?
PROGRESS
What are the system requirements?
PROGRESS

它不断返回 testString2 的值。我认为这与“?”有关。但真的不知道如何或为什么或该怎么做。帮助!

编辑:这是我希望它显示的内容:

当你运行它时,它会显示:

i hate this
is that real?
What are the system requirements?
PROGRESS

到目前为止,我发现如果我更改我sysReq1 = ('system requirements' and '?')的 tosysReq1 = 'system requirements' '?'并且只检查iffor sysReq1,它会返回战斗值。问题是我真的需要这些or语句来减少混乱/冗余。

存在 sysReq2 的原因是因为有些人对相同的答案提出了不同的问题:

  • 它可以在我的上网本上运行吗?

  • 我的电脑可以处理吗?

  • 可以在我的mac上玩吗?

这不包括“我能做到”的变体,但你明白了。所有这些都应返回相同的值(在本例中为“PROGRESS”)

4

3 回答 3

1

两个问题。首先,您不能使用andandor来“存储”某种比较运算符以供以后使用。当您编写andor立即评估结果时。相关规则在文档中进行了描述。

其次,您不能以这种方式 使用andand 。不会“分布在” and 和. 写作并不意味着“x中的A和x中的B”。它首先评估(在这种情况下会给你),然后检查单个结果是否在.orininandor('A' and 'B') in x('A' and 'B') 'B'x

使用简单的运算符无法实现您想要的。没有办法只使用andandor运算符来存储您以后可以应用的复杂查询。您将不得不将您的标准转换为函数并使用“测试字符串”作为参数调用它们:

def sysReq1(x):
    return 'system requirements' in x and '?' in x

>>> testString2 = "is that real?"
... testString3 = "What are the system requirements?"
... print testString2
... if sysReq1(testString2.lower()):
...     print "2 passed the test"
... print testString3
... if sysReq1(testString3.lower()):
...     print "3 passed the test"
is that real?
What are the system requirements?
3 passed the test

我建议您通过Python 教程来掌握 Python 的基础知识。

于 2013-06-27T05:37:44.450 回答
1

我认为any,allgenerators可以帮助你。

编码

#Define Key Words
##################################
#System Requirements Definitions
sysReq1 = ['system requirements', '?']
sysReq2 = [['can']
          ,['handle', 'play', 'run']
          ,['netbook', 'notebook', 'pc', 'mac', 'macbook', 'laptop', 'comp', 'computer']
          ,['?']
          ]
def test(testString):
    lowerTestString = testString.lower()
    return all(i in lowerTestString for i in sysReq1) or all(any(j in lowerTestString for j in i) for i in sysReq2)
#System Requirements Response
sysReqResponse = 'PROGRESS'
##################################
testString1 = "i hate this"
#intended result for 1: nothing
testString2 = "is that real?"
#intended result for 2: nothing
testString3 = "What are the system requirements?"
#intended result for 3: 'PROGRESS'
print testString1
if test(testString1):
    print sysReqResponse
print testString2
if test(testString2):
    print sysReqResponse
print testString3
if test(testString3):
    print sysReqResponse

该函数不是绝对必要的,但它确实使代码更易于维护。如果您需要更改支票,它只会更改一处。

这里发生了什么?

首先,我们将这两组字符串转换为列表和列表列表。然后要求变为“字符串必须包含 的所有元素sysReq1或每个子列表中的至少一个元素sysReq2。”

any我们通过将生成器与andall函数结合来完成检查这个条件。在存储lower以避免重复调用它之后,我们创建了一个布尔值的生成器(相当于一个迭代器)。每个布尔值告诉我们单个元素sysReq1是否包含在 lowered 中。然后我们将此迭代器传递给 first all,它检查列表是否包含所有Trues。如果是,则all函数返回True并且第二次检查被短路。否则,它返回False并且 Python 继续前进or.

检查sysReq2更复杂。首先,我们为每个子列表创建一个布尔生成器;这是在any通话中。该列表包含一组关于子列表的每个元素是否在降级字符串中的布尔值。如果此布尔列表(基于子列表)中的任何元素是 ,则调用any返回。(顺便说一下,它短路了,因为我们使用的是生成器,所以跟在 a 后面的检查甚至都不会运行,这与我们使用列表不同。)然后我们创建另一个生成器;这个包含每个子列表测试的结果(所有调用)。然后在这个生成器上调用,它检查问题是否包含来自所有子列表的元素。TrueTrueTrueanyall

我会注意到,如果用户直接输入无意义的问题,他们可以输入这些问题。例如,'Play can netbook kuguekf ugifugfj ugufsgjf nugjfgjfgj?'将通过此检查。

概括

使用生成器运行返回布尔值的测试。使用anyandall组合布尔值的可迭代对象。

编辑

根据评论,这是一个替代解决方案,它split通过空格 s 输入字符串并使用sets 而不是lists。我还从您列出的示例问题中添加了一个测试用例,以确保第二部分or被击中。

#Define Key Words
##################################
#System Requirements Definitions
sysReq1 = set(['system', 'requirements'])
sysReq2 = [set(['can'])
          ,set(['handle', 'play', 'run'])
          ,set(['netbook', 'notebook', 'pc', 'mac', 'macbook', 'laptop', 'comp', 'computer'])
          ]
def test(testString):
    if not testString.endswith('?'):
        return False

    lowerTestString = set(testString.rstrip('?').lower().split())
    return  lowerTestString.issuperset(sysReq1) or all(not lowerTestString.isdisjoint(i) for i in sysReq2)
#System Requirements Response
sysReqResponse = 'PROGRESS'
##################################
testString1 = "i hate this"
#intended result for 1: nothing
testString2 = "is that real?"
#intended result for 2: nothing
testString3 = "What are the system requirements?"
#intended result for 3: 'PROGRESS'
testString4 = "Can my PC handle it?"
#intended result for 4: 'PROGRESS'
print testString1
if test(testString1):
    print sysReqResponse
print testString2
if test(testString2):
    print sysReqResponse
print testString3
if test(testString3):
    print sysReqResponse
print testString4
if test(testString4):
    print sysReqResponse

我认为这很简单。请注意,set构造函数采用可迭代对象,因此我为此传递了列表。“不脱节”部分可能有点令人困惑;它只是确保交叉口不是空的。我使用它是希望实现该函数以便它不会计算整个交集。问号是有问题的,因为它没有用空格分隔,所以我只是确保字符串以问号结尾并将rstrip其删除。

实际上,这种实现可能比具有大量生成器的实现更清洁、更易于维护。

于 2013-06-27T07:29:09.607 回答
0

在 python 中,包含 BOOLEAN OPERATORS 的表达式的输出不必是 BOOLEAN ( http://docs.python.org/2/library/stdtypes.html ) 例如,sysReq1 = ('system requirements' and '?')sysReq1='?'在此处制作并注意sysReq1不是布尔值而是等于 QUESTION MARK 的字符串。同样,sysReq2也将等于?。此外,在上面的链接中查找 TRUTH VALUE TESTING,因为这将解释哪些值将被视为 FALSE 表达式。

于 2013-06-27T05:25:28.677 回答