# 14\_Python基础

## 前言 <a href="#qian-yan" id="qian-yan"></a>

Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。

Python 的设计具有很强的可读性，相比其他语言经常使用英文关键字，其他语言的一些标点符号，它具有比其他语言更有特色语法结构。

* Python 是一种解释型语言： 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。
* Python 是交互式语言： 这意味着，您可以在一个Python提示符，直接互动执行写你的程序。
* Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。

Python的另一大优势与便利性在于其开源性。网络上有相当多且高效有用的开源库可供我们进一步开发使用，比如著名的矩阵计算库numpy，科学计算库scipy等等。PYNQ已经为我们预装了这些有用的库，我们先来介绍一下python的基础用法，并在最后一小节讲讲如何使用pip来添加查询新的库。

通过键入关键词import，空格后按下tab即可查看所有已经安装的库。如图所示：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45kksNf9tZPqBOCj%2F01.png?generation=1574912160902188\&alt=media)

## Python常用辅助函数 <a href="#python-chang-yong-fu-zhu-han-shu" id="python-chang-yong-fu-zhu-han-shu"></a>

当我们使用（import）一个新的库的时候，我们常常不知道这个库有什么，该如何使用这个库。这个时候我们就可以借助两个关键的函数：help(), dir() 来帮助我们了解库的使用。我们以asyncio库为例。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45kmimwHsQVO1iQP%2F02.png?generation=1574912161010674\&alt=media)

导入库后，我们首先调用help函数，help函数会给我们提供asyncio库的制作者所写的帮助文档。通过这个文档，我们可以非常轻松的了解库里有哪些函数以及这些函数有什么作用。但是有的时候，我们希望可以更快的寻找我们需要的函数而非阅读全部的帮助文档。此时我们即可借助dir()函数。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45ko6fpTeuZYtJRd%2F03.png?generation=1574912161013459\&alt=media)

dir()函数以列表的形式提供了所有该库下可调用函数或子库，此时我们可以更容易的找到我们需要的内容。假如我们对图中的Condition模块感兴趣，我们只需键入help(asyncio.Condition)即可查看该模块的详细信息。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45kqE7ceLRkrSuCa%2F04.png?generation=1574912213075021\&alt=media)

依赖help与dir，我们通常就可以快速达成我们对所需要函数的快速检索以及使用，这对我们日后开发程序是非常有帮助的。事实上，help的功能更加广泛，我们可以对任意我们已经定义了的变量进行help来获得详细信息。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45ks1D8e2ynSO_dH%2F05.png?generation=1574912213084995\&alt=media)

## Python基础知识概览 <a href="#python-ji-chu-zhi-shi-gai-lan" id="python-ji-chu-zhi-shi-gai-lan"></a>

与其他语言不同，python的变量定义无需申明类型，直接拿来定义即可。这是因为python的所有变量类型都是以object（对象）定义的。在上一小结末尾，我们定义了a = 3，通过help可以看到，a是一个int object（整数对象），这也是python的一大特色。Python通过名字空间与对象空间的链接达成了对变量的管理。具体来说，当python执行a = 3的时候，它首先在对象空间里创建一个int object，其值为3，接着在名字空间里创建（或寻找）变量名a，将其指向对象“3”。贴切的说，a里存储的并不是3，而是“3”这个对象的地址。此外，对象名只能由英文数字下划线组成且数字不能作为开头，变量名区分大小写。

Python基础的对象主要有int（整数），float（浮点数），str（字符串），list（列表），tuple（元组），dict（字典），set（集合）。集合相对来说不怎么常用，这里不予讨论。Int与float同其他语言一致，包含基本的加减乘除（+-*/）以及整除（//）取余（%）幂次（\**），如下所示：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45kuVevrEjpU018A%2F06.png?generation=1574912213007375\&alt=media)

字符串对象可用单引号‘string’、双引号“string”、三单引号‘‘‘string’’’或者三双引号“““string”””表示，但是通常三引号用作注释说明，一般只使用单引号与双引号。

与其他语言不同，python并没有数组对象array，相对的，其有元组(value1, value2, …)与列表\[value1, value2, …]，两者唯一的区别在于元组是一个不可变对象——无法添加删除新的元素、无法变更元组内不可变对象的值（这列可能有点拗口，但是如果某个value是可变对象比如列表，则仍然有办法修改里面的值），而列表为可变对象（增改删查皆可）。基本操作如下所示：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45kwB4uWvOWJvjuG%2F07.png?generation=1574912161043305\&alt=media)

在上面的示范里，我们可以发现a + . + function的用法。正如前面介绍，这正是因为列表a也是一个对象，而python调用对象方法的语法便是对象名object + . + function。

最后是字典对象{key1: value1,…}其采用键值对组合。其中键（key）必须为不可变对象，值（value）可为任意对象。字典本身为可变对象，即可增改删查，这里只介绍最基本的增与改。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45kynaR2M63JdGpP%2F08.png?generation=1574912160980286\&alt=media)

## Python简单实例——分解因数 <a href="#python-jian-dan-shi-li-fen-jie-yin-shu" id="python-jian-dan-shi-li-fen-jie-yin-shu"></a>

这一节，我们将通过一个简单实例来了解python的一些基本操作：函数定义、条件判断、for循环迭代。代码如下：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45l-N3Q_Dftnh3oj%2F09.png?generation=1574912160968634\&alt=media)

为了实现代码的整洁与重复使用，函数的定义是必须要掌握的。Python中使用关键词def + function\_name(arg1, arg2, …)来定义函数。上面代码就定义了一个名为factorize的函数，其参数为n。我们注意到，与其他的语言不同，python并没有各类括号来划分代码块，因为其采用的是冒号“:”加缩进（tab）的形式来划分。冒号为缩进提示符，因此必不可少，下面处于同一级别缩进的都属于def的函数范围。当然，缩进也可以嵌套，子缩进属于父缩进。若要结束函数定义，只需退回到和def的缩进级别（0缩进）即可。下图展示了def的具体形式。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45l1JZeOueximkRf%2F10.png?generation=1574912160971789\&alt=media)

函数定义的时候可以指定任意多个参数，同时也允许赋予默认值。但是拥有默认值的形参必须排在最后。即上面的图示中，若写成arg1，arg2 = 3， arg3，便是非法的。函数最后可以使用关键词return来返回函数体中的数据，且一旦碰到return，函数调用就结束了。上面的示例中我们返回了arg1，因此q得到的值就是func(4,6)里的4。有的时候，为了能让别人读懂函数的作用，我们通常会在def的下一行增添注释，也就是因素分解实例中的三引号部分。

回到实例，在函数内部，我们首先定义了空列表factor，随后使用了选择分支结构if….else，其具体结构如下所示：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45l3s2OFKDlZZRUu%2F11.png?generation=1574912160878411\&alt=media)

其中只有if是必要的，并且采用冒号+缩进的方式提示程序代码块到何处结束。Elif和else是分支选项，可有可无，elif可以写多个，而else只能有一个，他们都与if同级缩进。

最后是for循环结构，语法如下：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45l50UKlFSeNG-ON%2F12.png?generation=1574912160869158\&alt=media)

注意到与别的语言不同，for循环并不是只能迭代次数循环，iterate\_unit可以是任何一个可迭代对象，常见的有元组、列表、字符串。每一次迭代的内容会赋给item，通过对item进行操作来完成循环目的。在实例中，我们的循环部分首先使用内置函数range(start, stop, step)生成了一个可迭代对象，并通过循环该对象完成因数分解操作。其中range函数返回的是一个从start开始（包含start）至stop结束（不包含stop）且间隔为step的整数列列表（比如range(0,6,2)返回的的是\[0,2,4]）。

了解了if和for后，我们再纵观整个程序一遍。程序首先判断输入的n是否是一个可以被因数分解的对象，随后从1至 根号n遍历，找到所有的因数（即可以被整除），并将因数添加至列表factor，最后返回列表。

有关更多的python教程，还请找专门的书籍自行学习。

## Python库的使用 <a href="#python-ku-de-shi-yong" id="python-ku-de-shi-yong"></a>

我们之前说过，python的强大之处在于其丰富的开源库，我们接下来以Numpy与pynq的结合为例稍微的体验一下库的运用。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45l7vTtjrjDPkhIe%2F13.png?generation=1574912160908593\&alt=media)

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45l9DD5ACrqR3390%2F14.png?generation=1574912160940478\&alt=media)

Numpy包为我们提供了传统的数组形式，而pynq包则为我们在numpy的基础上进一步封装，使得其成为了可被PYNQ板的ARM处理器可处理的形式。换而言之，我们可以用numpy包来处理从硬件上搜集的数据，也可以用pynq包把数据包装后传回硬件。我们要写的只不过是一行代码，其内部具体的实现原理无需我们推敲，这正是python的开源性为我们带来的便利性。如果想知道函数的具体用法，我们只需使用help即可。如图所示：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lBdYM6CvO3reEC%2F15.png?generation=1574912161029887\&alt=media)

## Python高级实例——异步IO操作 <a href="#python-gao-ji-shi-li-yi-bu-io-cao-zuo" id="python-gao-ji-shi-li-yi-bu-io-cao-zuo"></a>

在与可编程逻辑设备通过事件交互的时候，python3.5以后的版本的asyncio模块可以发挥巨大的优势（PYNQ已经搭载了3.6版本）。我们可以使用这个模块来异步处理PYNQ板上的多个IO任务，这样就可以避免有的IO占线太长而导致其他IO操作堵塞。也就是说，程序可以优先处理准备好运行的了IO任务，最后再回过头去把占线的任务解决掉。

当然了，这里我们并不知道我们的可编程逻辑设备上运行的是什么，所以我们这里仅仅在程序上模拟一下异步处理（即使用下面的asyncio.sleep方法达成占线操作）。代码如下：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lDqMYnWC1c3D3S%2F16.png?generation=1574912184542102\&alt=media)

我们在定义函数关键词def前增加关键词async，即可定义“异步函数”，其余语法不变。我们称一个异步函数为协程（Coroutine），其特点是只允许在其内部的出现的await操作（await出现在async def以外的地方会提示语法错误）。关键词await 允许该协程在此处中断，先去执行其他协程，并在await后的内容结束后立即回到原先协程继续执行未完成的代码。在上面定义的函数中，我们用asyncio.sleep来模拟IO的占线操作（这里我们不可以使用time.sleep，因为await后必须是一个Awaitable对象，asyncio.sleep相当于协程版的time.sleep），在实际操作中，我们await后加的可能是另外一个IO操作协程。接下来，我们就用这个函数来模拟异步IO操作。代码如下：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lFEbdoALaL2iNg%2F17.png?generation=1574912184655942\&alt=media)

为了体现出异步处理的强大，我们特地让第二个IO任务的执行时间高于第一个IO任务。从输出可以看到，两个协程的开始时间是几乎一致的。也就是说，当第一个任务运行到await后，并未等待占线结束，而是直接运行第二个协程。当第一个协程的5s结束后，程序并没有等待运行中的第二个协程的8s操作，而是中断回到第一个协程继续后面的操作，当8s过后再回过头去执行第二个协程。

## Pip的使用 <a href="#pip-de-shi-yong" id="pip-de-shi-yong"></a>

简介提到，Python为我们提供了相当多的优质的库，同时，python也为我们提供了专门的库管理工具——pip。通过pip，我们可以非常简单的下载安装新的库。本小节就来介绍如何给PYNQ板装新的库。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lHdt4YblU76p7D%2F18.png?generation=1574912184673082\&alt=media)

首先，我们打开PYNQ的Jupyter，并在New下找到Terminal，点击后进入终端操作界面。界面如下：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lJQ33HS0hGUhR0%2F19.png?generation=1574912213097222\&alt=media)

接着我们输入sudo pip3或者sudo pip3.6测试一下自己的pip命令是哪一个（对于sd卡里烧写了不同版本的PYNQ来说，命令可能不一样），之后附加的命令内容均一致。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lLbYvpx1v4oNBM%2F20.png?generation=1574912213064982\&alt=media)

这里使用的sudo pip3.6命令， 首先我们键入sudo pip3.6 list，即可列出所有已安装的库。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lNxQ7y-vObxqkh%2F21.png?generation=1574912213065145\&alt=media)

这里的列表因人而异，因为自己电脑上本来就装过的库也是可以调用的。

至于安装新的库，有两种方法。第一种通过电脑联网下载库的文件夹（下图为整个文件夹的内容，该库为cv2pynq），该文件夹里有着setup.py用以帮助安装。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lP3DmjlUfPUydu%2F22.png?generation=1574912212979952\&alt=media)

首先，我们把整个文件夹通过samber传输文件的方法拷贝至PYNQ的pynq文件夹内。这里我将文件夹取名为pynqhodm。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lRF7BGgNZStJfx%2F23.png?generation=1574912212991825\&alt=media)

打开jupyter notebook的终端，转移到当前文件夹，语法是 cd pynq/YOUR\_FILENAME，成功后，命令行的前缀会变为如下所示：

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lTysdKu-wFwkCr%2F24.png?generation=1574912216497771\&alt=media)

接着我们运行安装命令“sudo pip3.6 install –e .”，注意，这个末尾的“.”不可漏！

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lVqMVyyEI6OnIF%2F25.png?generation=1574912161084737\&alt=media)

提示了Successfully之后即表明安装成功。

第二种方法，需要pynq连接上电脑以及外网，经过测试，我们需要使用v2.3版本的镜像。也即pip命令为sudo pip3的版本。

第一步，我们需要确保我们的板子连上外网，为此，你需要你的电脑连上外网。打开网络和Internet设置界面，找到更改适配器选项。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lX3Qk6_d48Cb7N%2F26.png?generation=1574912161021256\&alt=media)

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lZfDk6Gi1Ns6GN%2F27.png?generation=1574912160936522\&alt=media)

可以看到我们连接到外网的WLAN以及连接到板子的以太网。我们右键WLAN找到属性界面。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45la4clV0RP2WxPQ%2F28.png?generation=1574912160988722\&alt=media)

在共享界面，选择板子连上的以太网进行共享。点击确定，若跳出提出弹窗，点击确定即可。

此时，由于共享了网络，我们板子的IP地址不再是默认的192.168.2.99，而是改成了动态配置IP地址。因此第二步是找到板子串口的新IP地址。我们需要上网下载一个工具来连接串口。

登录网址[https://www.chiark.greenend.org.uk/\~sgtatham/putty/latest.html](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html%E8%8E%B7%E5%BE%97putty) 获得putty工具。下载适合自己系统的版本。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lcz9dgiYqcTnrP%2F29.png?generation=1574912160943775\&alt=media)

安装完成后，打开putty。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lewVd6gE7wl_ve%2F30.png?generation=1574912160941621\&alt=media)

接下来我们需要找到自己的Serial port。打开控制面板，在硬件和声音里找到设备管理器。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lgBi0uOzuIMbC1%2F31.png?generation=1574912161146970\&alt=media)

在设备管理器的端口下找到自己的端口。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45liqVZFv1MdMqbN%2F32.png?generation=1574912161063508\&alt=media)

图中为COM5。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lkIXFH5396Rr7h%2F33.png?generation=1574912160974694\&alt=media)

填写完上述三个配置后，点击open。（speed栏固定115200）

打入回车后，出现如下界面。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lmfR4_IwU6p9KB%2F34.png?generation=1574912160937879\&alt=media)

输入命令ifconfig后，即可查看串口IP地址。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45loBCJM-haCg53w%2F35.png?generation=1574912160966848\&alt=media)

打开浏览器，即可用该ip地址登录jupyter notebook。

最后一步，打开terminal终端，输入sudo pip3 install package\_name 即可直接安装新的包。以Luminoth为例。

![](https://gblobscdn.gitbook.com/assets%2F-Luk3T3QoKyS_b-1joBV%2F-Luk3tukeoHpawWbVABz%2F-Luk45lqYDxFar7Iwvfy%2F36.png?generation=1574912161153587\&alt=media)

倘若包确实存在却碰到失败，多半是因为网络延迟造成，尝试多次执行安装命令即可。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://digilent-china.gitbook.io/pynq-z1_tutorial/pynq-zhong-wen-zi-liao/14python-ji-chu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
