The background knowledge of Python
视频教程附录一 - python语法:https://singtown.com/learn/50061/
Benefits of using python
OpenMV can use Python to achieve secondary development and it has several benefits:
- It is easy to start with.
- You do not have to consider the malloc and free of the memory.
- There are many MicroPython libraries for you to use directly (but incompatible with the Python module on the PCs).
- The development team has built many algorithms and modules for you to use.
Python is a common language which is use broadly in image processing, machine Learning and network programming. And Python is also a language easy to start with, which is easier as long as you have basic knowledge of other programming languages such as C, C++ or Java.
We recommend a course if you have programing experience of C/C++/Java (or any other languages) before 廖雪峰的Python教程
We recommend a course if you have no programming experience: 笨方法学Python
REPL & Serial Ports
The IDE of OpenMV includes a serial port assistant to connect with both OpenMV as well as other serial ports such as Arduino, pyboard and esp8266.
First, disconnect OpenMV and IDE, or the serial ports would contradict each other.
Click Tool in OpenMV → Open Terminal → New Terminal
Input the following words in a terminal
print("hello OpenMV!")
it would display
hello OpenMV!
Python syntax
Output
用print()在括号中加上字符串,就可以向屏幕上输出指定的文字。比如输出'hello, world',用代码实现如下:
print('hello, world')
hello, world
print()函数也可以接受多个字符串,用逗号“,”隔开,就可以连成一串输出:
print('The quick brown fox', 'jumps over', 'the lazy dog')
The quick brown fox jumps over the lazy dog
print()会依次打印每个字符串,遇到逗号“,”会输出一个空格,因此,输出的字符串是这样拼起来的:
The quick brown fox jumps over the lazy dog
print()也可以打印整数,或者计算结果:
print(300)
300
print(100 + 200)
300
因此,我们可以把计算100 + 200的结果打印得更漂亮一点:
print('100 + 200 =', 100 + 200)
100 + 200 = 300
注意,对于100 + 200,Python解释器自动计算出结果300,但是,'100 + 200 ='是字符串而非数学公式,Python把它视为字符串.
变量
在Python中,等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:
a = 123 # a是整数
print(a)
a = 'ABC' # a变为字符串
print(a)
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言,赋值语句如下(// 表示注释):
int a = 123; // a是整数类型变量
a = "ABC"; // 错误:不能把字符串赋给整型变量
和静态语言相比,动态语言更灵活,就是这个原因。
list列表
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。
比如,列出班里所有同学的名字,就可以用一个list表示:
classmates = ['Michael', 'Bob', 'Tracy']
classmates
['Michael', 'Bob', 'Tracy']
变量classmates就是一个list。用len()函数可以获得list元素的个数:
len(classmates)
3
用索引来访问list中每一个位置的元素,记得索引是从0开始的:
classmates[0]
'Michael'
classmates[1]
'Bob'
classmates[2]
'Tracy'
classmates[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(classmates) - 1。
如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素:
classmates[-1]
'Tracy'
以此类推,可以获取倒数第2个、倒数第3个:
classmates[-2]
'Bob'
classmates[-3]
'Michael'
classmates[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
当然,倒数第4个就越界了。
list是一个可变的有序表,所以,可以往list中追加元素到末尾:
classmates.append('Adam')
classmates
['Michael', 'Bob', 'Tracy', 'Adam']
也可以把元素插入到指定的位置,比如索引号为1的位置:
classmates.insert(1, 'Jack')
classmates
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
要删除list末尾的元素,用pop()方法:
classmates.pop()
'Adam'
classmates
['Michael', 'Jack', 'Bob', 'Tracy']
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
classmates[1] = 'Sarah'
classmates
['Michael', 'Sarah', 'Tracy']
list里面的元素的数据类型也可以不同,比如:
L = ['Apple', 123, True]
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
L = []
len(L)
0
tuple元组
另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:
classmates = ('Michael', 'Bob', 'Tracy')
现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素。
不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。
tuple的陷阱:当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
t = (1, 2)
t
(1, 2)
但是,要定义一个只有1个元素的tuple,如果你这么定义:
t = (1)
t
1
定义的不是tuple,t是整型变量,变量t的值为1!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。
所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
t = (1,)
t
(1,)
Python在显示只有1个元素的tuple时,也会加一个逗号,,以免你误解成数学计算意义上的括号。
条件判断
if语句的完整形式是:
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>
比如:
age = 20
if age >= 6:
print('teenager')
elif age >= 18:
print('adult')
else:
print('kid')
循环
Python的循环有两种,一种是for...in循环,依次把list或tuple中的每个元素迭代出来,看例子:
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
执行这段代码,会依次打印names的每一个元素:
Michael
Bob
Tracy
所以for x in ...循环就是把每个元素代入变量x,然后执行缩进块的语句。
如果要计算1-100的整数之和,从1写到100有点困难,幸好Python提供一个range()函数,可以生成一个整数序列,再通过list()函数可以转换为list。比如range(5)生成的序列是从0开始小于5的整数:
list(range(5))
[0, 1, 2, 3, 4]
range(101)就可以生成0-100的整数序列,计算如下:
sum = 0
for x in range(101):
sum = sum + x
print(sum)
第二种循环是while循环,比如我们要计算100以内所有奇数之和,可以用while循环实现:
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
===== 数据类型转换 =====
Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:
>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False
===== 函数 =====
在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
我们先写一个计算x2的函数:
def power(x):
return x * x
对于power(x)函数,参数x就是一个位置参数。
当我们调用power函数时,必须传入有且仅有的一个参数x:
power(5)
25
power(15)
225
现在,如果我们要计算x3怎么办?可以再定义一个power3函数,但是如果要计算x4、x5……怎么办?我们不可能定义无限多个函数。
你也许想到了,可以把power(x)修改为power(x, n),用来计算xn,说干就干:
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
对于这个修改后的power(x, n)函数,可以计算任意n次方:
power(5, 2)
25
power(5, 3)
125
修改后的power(x, n)函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数x和n。
切片
取一个list或tuple的部分元素是非常常见的操作。比如,一个list如下:
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
取前3个元素,用一行代码就可以完成切片:
L[0:3]
['Michael', 'Sarah', 'Tracy']
L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。
如果第一个索引是0,还可以省略:
L[:3]
['Michael', 'Sarah', 'Tracy']
也可以从索引1开始,取出2个元素出来:
L[1:3]
['Sarah', 'Tracy']
tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
(0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)
字符串'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
'ABCDEFG'[:3]
'ABC'
对象
Python是面向对象编程的,比如一个LED灯
from pyb import LED
red_led = LED(1)
red_led.on()
LED是一个类,red_led就是一个对象,可以对这个对象进行操作,比如点亮on,关掉off,查看value。