![Python数据整理](https://wfqqreader-1252317822.image.myqcloud.com/cover/51/32436051/b_32436051.jpg)
练习17:使用用户定义的方法实现栈
我们将继续上个练习中的栈主题。但这个练习中我们将自己实现append和pop函数。这个练习的目的有两个:一方面,我们将用实际生活中的一个例子实现这个栈,这个例子还涉及字符串方法的知识,因此可以作为上一章内容和活动的重温;另一方面,它将向我们展示Python的一个微妙特性,以及它如何将列表变量传递给函数,并将带我们进入下一个练习,函数编程。
1.首先定义两个函数:stack_push和stack_pop。我们对它们进行了重命名,这样就不会发生名称空间之间的冲突。另外,创建一个名为url_stack的栈供以后使用:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/027-i.jpg?sign=1738850434-SXX8oCav33Qr0R1KfpzvGa5z5NWLkUlg-0-cb796ed8f58ef1377eff5936be48a753)
2.第一个函数获取已经存在的栈,并在其末尾添加值。
说明
注意value周围的方括号,为了+操作,它将其转换为只有一个元素的列表。
3.第二个函数读取当前位于栈的-1索引处的值,然后使用del运算符删除该索引,最后返回先前读取的值。
4.现在我们有一串包含几个URL的字符串。我们的工作是分析该字符串,以便在遇到栈中的URL时逐个推送它们,最后使用for循环逐个弹出它们。让我们从维基百科中关于数据科学的文章开始:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/027-2-i.jpg?sign=1738850434-zeS5Hn5tn2E1Mgw0UvqYsLiSfTyepa2F-0-11fd9f5e253257ce5d7c0d3169841961)
5.为了简化这个练习,我们将目标单词之外的链接用方括号括了起来。
6.查找字符串的长度:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/027-3-i.jpg?sign=1738850434-cSIyMnzyyiEvqtDB0i59PPLfJGHIVVRb-0-6cb3da4ce5b2d6b78df113eed2c6ac81)
输出如下:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/027-4-i.jpg?sign=1738850434-t7eGkC72sRxRqffUR2Ks7DKHCtsuUpYm-0-d2c3852a9b3a705f207f0df4030bdc42)
7.使用字符串中的split方法将此字符串转换为列表,然后计算其长度:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/027-5-i.jpg?sign=1738850434-n3slBYjgOi4GB2sKQ3cVekHxMwdjwily-0-cdc251d88e9a4910983f0481c0785dd6)
输出如下:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/027-6-i.jpg?sign=1738850434-eUu7z2c6T7i8QNcUplwYBk1aVkXHAvtl-0-1097b8c7d91ea6e5556ae06ba7cfb12f)
8.使用for循环遍历每个单词并检查它是否是URL。为此,我们将使用字符串中的startswith方法,如果它是URL,则将其推入栈:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/028-i.jpg?sign=1738850434-XtacTOyglXvuS1Lp3YYzjC0vlQNzVeUk-0-b1e6a7ed79baa68d7681aa9c7d76486b)
9.输出url_stack中的值:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/028-2-i.jpg?sign=1738850434-H8A2htZ70DB2hsGpyGABUNKYfWH3HFWK-0-b74d750f9beb6c14122b086980fa69ad)
输出如下:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/028-3-i.jpg?sign=1738850434-rti165NWqq6wRPJRSBhhRAy7p6JqAt6y-0-726e2395ff9588e1f58f468d26a2e636)
10.迭代列表并使用stack_pop函数逐个打印URL:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/028-4-i.jpg?sign=1738850434-Xac7KAipNgaaqz3baYY0jcfYchBBOFYQ-0-5cdb125181ab26f02ed4f401d8b088c7)
输出如图2-2所示。
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/t2-2.jpg?sign=1738850434-EHDWdY9QtZEo3C6z7nzcwzl8RxUR8MEj-0-25bf6a563d45351ab24fbaf0ffadb04b)
图2-2 使用栈输出的URL
11.再次打印以确保在for循环之后栈为空:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/028-5-i.jpg?sign=1738850434-j0TISNVhiHnIVhtV2VCOW5ofWmQOIOoQ-0-8ea530c1fe3ed3f8883caaf5fa3920d8)
输出如下:
![](https://epubservercos.yuewen.com/63BD11/17517093106688706/epubprivate/OEBPS/Images/028-6-i.jpg?sign=1738850434-dUX4v4LbMswZNhjn8JJyNME57tJzjGGG-0-d5f4213900806be20fa59e736e4368ab)
我们注意到stack_pop方法中有一个奇怪的现象。我们在这里传递了列表变量,并在函数内部使用了del运算符,但是每次调用函数时,它都会删除最后一个索引,从而改变了原始变量。如果你熟悉C语言、C++语言和Java语言,那么这是一个完全出乎意料的行为。在这些语言中,只有当我们通过引用传递变量时这些行为才会发生,而且它能在Python代码中引起微小的错误,所以要小心。通常,在函数内部改变一个变量的值并不是一个好主意。传递给函数的任何变量都应该被认为是不可变的,这接近于函数式编程的原理。Python中的Lambda表达式是一种构造单行无名称函数的方法,这些函数按照约定是无副作用的。