Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

无法理解正则表达式附录的eliza模块中的匹配规则 #1514

Open
pyz610173878 opened this issue Sep 13, 2022 · 3 comments
Open

Comments

@pyz610173878
Copy link

pyz610173878 commented Sep 13, 2022

大致了解并练习了本章节的主要语法与用法,打算尝试理解eliza模块。我的思路,直接从头阅读源代码。

但以下代码,尝试简化并拆分。但还是无法理解。
代码如下:

self.keys = list(
map( lambda x: re.compile(x[0],  re.IGNORECASE), gPats))

list函数中嵌套着map函数,其中函数为lambda表达式,参数x,匹配规则为参数x + 集合原子[0]。re.IGNORECASE我查了一下,这个标志允许正则表达式与给定的字符串进行不区分大小写的匹配。

gPats为可迭代对象,以下是gPats具体的值。

gPats = [r'I need (.*)',
  [  "Why do you need %1?",
    "Would it really help you to get %1?",
    "Are you sure you need %1?"]],

老师这一整个嵌套的列套是一个整体的匹配规则吗?
还是说,在逗号分隔的地方为一个匹配规则。我也尝试把此规则放进regex101,但还是不能理解,希望老师给点线索。

@pyz610173878 pyz610173878 changed the title 关于正则表达式附录的eliza模块 无法正则表达式附录的eliza模块中的匹配规则 Sep 13, 2022
@pyz610173878 pyz610173878 changed the title 无法正则表达式附录的eliza模块中的匹配规则 无法理解正则表达式附录的eliza模块中的匹配规则 Sep 13, 2022
@neolee
Copy link
Owner

neolee commented Sep 13, 2022

这个问题的关键是你要理解 map() 函数的机制,我简单写下,你可能还需要读读相关的文档:

  1. map(f, seq) 接受两个参数,第一个参数是个函数,第二个参数是个列表(其实任何 iterable object 都可以);
  2. map 函数会按顺序用 seq 里的每个元素作为参数去调用函数 f,所以 f 必然是一个单参数的函数;
  3. 调用的结果按照原顺序组成一个新的列表,这个列表就是 map 的返回值。

而你的例子里的函数 f 是什么呢?大致长这样:

def f(x):
    return re.compile(x[0], re.IGNORECASE)

也就是说,f 的作用是取出列表里的每个元素,然后把这个元素(本身又是个列表)的第一个元素拿出来,编译成一个正则匹配对象,并返回。

再来看要被函数 f 反复操作的 gPats 列表,它的结构是这样的:

gPats = [
    [
        r'I need (.*)',
        [
            "Why do you need %1?", "Would it really help you to get %1?",
            "Are you sure you need %1?"
        ]
    ],
    [
        r'Why don\'?t you ([^\?]*)\??',
        [
            "Do you really think I don't %1?", "Perhaps eventually I will %1.",
            "Do you really want me to %1?"
        ]
    ],
    [
        r'Why can\'?t I ([^\?]*)\??',
        [
            "Do you think you should be able to %1?",
            "If you could %1, what would you do?",
            "I don't know -- why can't you %1?", "Have you really tried?"
        ]
    ],
    ...
]

这个列表的每个元素都是一个小列表,每个小列表里有两个元素,第一个是个正则匹配串,比如 r'I need (.*)',所以上面的 map 函数就是把这些正则匹配串取出来组成一个新的列表(保存在 self.keys 中),源代码后面还把 gPats 里每个元素的第二个元素(是个包含若干字符串的列表)取出来,组成了另一个列表(保存在 self.values 中)。

事实上,如果你搞不清楚一些问题,最好的办法是把整个代码放进一个 Jupyter Notebook,分段落执行,看每一步的输出结果,有些问题的答案自己就能猜出来了。

@pyz610173878
Copy link
Author

老师,有个疑惑。已经尝试理解,Eliza模块的基本结构与逻辑。为了追求更深入的理解。是否应该尝试理解为什么它要这么写,或者进一步开始模仿吗?

@neolee
Copy link
Owner

neolee commented Sep 19, 2022

老师,有个疑惑。已经尝试理解,Eliza模块的基本结构与逻辑。为了追求更深入的理解。是否应该尝试理解为什么它要这么写,或者进一步开始模仿吗?

个人认为更好的思路是,要么自己扔开这个实现自己尝试写个出来(之前研究原代码得到的知识可以用),要么尝试改进原代码实现更多功能,后者更容易一些。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants