友情提示:380元/半年,儿童学编程,就上码丁实验室。
如果你有幸看完这一课,恭喜你,你掉坑了!掉什么坑?【面向对象】编程的大坑!学生们,你们将会开始接触与众不同的编程世界!
在 EV3 的世界里(一般是中小学生),就没有用 面向对象的。(除了我的学生)
在 面向对象的世界里 (一般是大学生和成年编程人员),就没有玩 EV3 比赛的。(超龄了!)
好吧,你们将会开始使用大学技术,和中小学生比赛,拿什么名次自己想!
EV3: Lesson 6 – Object Oriented Programming
EV3:第 6 课 – 面向对象 编程
6.1 What is Object Oriented Programming
6.1 什么是面向对象编程
We are not going to talk about this in detail, but we’ll learn HOW we can use object oriented programming in Python to control EV3.
我们不会很详细的介绍什么是面向对象编程,但是我们会学习如何使用面向对象编程方法,去编写 EV3 Python 程序。
An “OBJECT” consists of properties and methods, e.g:
一个【对象】(Object)有自己的【属性】(Properties)和【方法】(Methods),举例:
OBJECT PROPERTIES EXAMPLE:
对象属性例子:
object.name = “Zephan”
object.age = 12
OBJECT METHOD EXAMPLE:
对象方法例子:
intSalary = object.CalculateSalary()
Starting from this lesson, we’ll write ALL PROGRAMS in OBJECT ORIENTED APPROACH.
从这一课开始,我们【所有的程序】,都会使用面向对象方法编写!
6.2 Re-write lesson 5 programs in objected oriented approach
6.2 使用面向对象编程方法,重写第 5 课的程序
After this lesson, you’ll understand HOW and WHY we use object oriented programming!
这一课之后,你就会明白为什么和怎么样使用面向对象编程。
This time, we’ll run the program first and explain later.
这一次,我们会先运行程序,再解释源代码。
Create the following files:
创建以下的程序档案:
from ev3dev.ev3 import *
from time import sleep, time
from importlib import *
import g
class ROBOT:
lcd = Screen()
btn = Button()
def __init__(self):
global module
module = __import__(g.module)
# The following method display a Menu on the lcd screen and wait for user selection
# ShowMenu() Begin
def ShowMenu(self, strMenuTitle, listMenu, listFunction):
global module
intSelect = 1
intNoOfLine = len(listMenu)
bolSelect = False
bolPressed = False
# Continue to loop until the user make a selection
while not bolSelect:
self.lcd.clear()
intX = 5
intY = 5
# Display title
self.lcd.draw.text((intX, intY), strMenuTitle)
# Display a line after the title, to separate the title and the content
self.lcd.draw.line((0, intY + 12, 177, intY + 12), fill = None, width = 0)
intY = intY + 5
# Display all lines
i = 1
while i <= intNoOfLine:
intY = intY + 15
if i == intSelect:
# If the cursor is on this line, reverse the color of this line
self.lcd.draw.rectangle((0, intY, 177, intY + 10), fill = 'black')
self.lcd.draw.text((intX, intY), listMenu[i - 1], fill = 'white')
else:
# If the cursor is not on this line, display the text on this line
self.lcd.draw.text((intX, intY), listMenu[i - 1])
i = i + 1
# Show the screen
self.lcd.update()
if bolPressed:
sleep(0.5)
bolPressed = False
# if bolWait == True, continue waiting for key press event
bolWait = True
while bolWait:
if self.btn.up:
# if Up is pressed
bolPressed = True
bolWait = False
# Cursor go up 1 line
intSelect = intSelect - 1
if intSelect == 0:
# if Cursor at line 0, set Cursor to last line
intSelect = intNoOfLine
elif self.btn.down:
# if Down is pressed
bolPressed = True
bolWait = False
# Cursor go down 1 line
intSelect = intSelect + 1
if intSelect > intNoOfLine:
intSelect = 1
elif self.btn.left:
# if Left is pressed, do nothing
pass
elif self.btn.right:
# if Right is pressed, do nothing
pass
elif self.btn.enter:
# if Enter is pressed, exit loop
bolWait = False
bolSelect = True
else:
# Sleep for 0.05 seconds to detect another key press
sleep(0.05)
# Important to sleep here, otherwise the btn.enter will be catched by another menu
sleep(0.5)
# From here User has made its selection, do the function according to user selection
func = getattr(module, listFunction[intSelect-1])
func()
# ShowMenu() End
http://www.zephan.top/ev3pythonlessons/lesson6/robot.py
上面这个是 “robot.py”
import robot
def funInitRobot():
global rb, module
module = 'fun'
rb = robot.ROBOT()
http://www.zephan.top/ev3pythonlessons/lesson6/g.py
上面这个是 “g.py”
from time import sleep, time
import g
def StartProgram():
strMenuTitle = 'Main Menu'
listMenu = ['Sub Menu 1','Sub Menu 2']
listFunction = ['fun.StartSubMenu1','fun.StartSubMenu2']
g.rb.ShowMenu(strMenuTitle, listMenu, listFunction)
def StartSubMenu1():
strMenuTitle = 'Sub Menu 1'
listMenu = ['Sub Menu 1 Line 1','Sub Menu 1 Line 2']
listFunction = ['fun.StartSubMenu1Line1','fun.StartSubMenu1Line2']
g.rb.ShowMenu(strMenuTitle, listMenu, listFunction)
def StartSubMenu2():
strMenuTitle = 'Sub Menu 2'
listMenu = ['Sub Menu 2 Line 1','Sub Menu 2 Line 2']
listFunction = ['fun.StartSubMenu2Line1','fun.StartSubMenu2Line2']
g.rb.ShowMenu(strMenuTitle, listMenu, listFunction)
def StartSubMenu1Line1():
g.rb.lcd.clear()
g.rb.lcd.draw.text((0, 0), 'You have Selected:')
g.rb.lcd.draw.text((0, 15), 'Sub Menu 1 Line 1')
g.rb.lcd.draw.text((0, 30), 'This program will quit')
g.rb.lcd.draw.text((0, 45), 'in 10 seconds')
g.rb.lcd.update()
sleep(10)
def StartSubMenu1Line2():
g.rb.lcd.clear()
g.rb.lcd.draw.text((0, 0), 'You have Selected:')
g.rb.lcd.draw.text((0, 15), 'Sub Menu 1 Line 2')
g.rb.lcd.draw.text((0, 30), 'This program will quit')
g.rb.lcd.draw.text((0, 45), 'in 10 seconds')
g.rb.lcd.update()
sleep(10)
def StartSubMenu2Line1():
g.rb.lcd.clear()
g.rb.lcd.draw.text((0, 0), 'You have Selected:')
g.rb.lcd.draw.text((0, 15), 'Sub Menu 2 Line 1')
g.rb.lcd.draw.text((0, 30), 'This program will quit')
g.rb.lcd.draw.text((0, 45), 'in 10 seconds')
g.rb.lcd.update()
sleep(10)
def StartSubMenu2Line2():
g.rb.lcd.clear()
g.rb.lcd.draw.text((0, 0), 'You have Selected:')
g.rb.lcd.draw.text((0, 15), 'Sub Menu 2 Line 2')
g.rb.lcd.draw.text((0, 30), 'This program will quit')
g.rb.lcd.draw.text((0, 45), 'in 10 seconds')
g.rb.lcd.update()
sleep(10)
http://www.zephan.top/ev3pythonlessons/lesson6/fun.py
上面这个是 “fun.py”
#!/usr/bin/env python3
from time import sleep, time
import traceback
import g
import fun
# Initialize the LCD and Buttons
try:
g.funInitRobot()
fun.StartProgram()
except:
# If there is any error, it will be stored in the log file in the same directory
logtime = str(time())
f=open("log" + logtime + ".txt",'a')
traceback.print_exc(file=f)
f.flush()
f.close()
http://www.zephan.top/ev3pythonlessons/lesson6/lesson6_01.py
上面这个是主程序 “lesson6_01.py”
Upload the above 4 programs and run lesson6_01.py in the EV3 brick:
上传上面 4 个程序,并运行主程序 lesson6_01.py:

Figure 6.1
Press “Enter” button:
按一下【确认键】:

Figure 6.2
Press “Enter” again:
再按一下【确认键】:

Figure 6.3
As you can see, with a little change in codes, the menu in lesson 5 has become MENU(S) in lesson 6, we can reuse the codes to create as many levels of menus you like.
好像你看到的一样,只是改动一点点程序,第 5 课的单层菜单就变成了第 6 课的多层菜单,你可以重复使用面向对象的对象方法,去创建无限层数的菜单。
We are going to explain it in details:
以下我们详细介绍:
robot.py
First take a look at robot.py, it contains a “CLASS” called “ROBOT”, with 2 objects “lcd” and “btn”, which are inherited from their parent classes “Screen()” and “Button()”, we added a new method called “ShowMenu()” to this ROBOT object, to display a menu.
In this ShowMenu() Method, we mainly copy codes from lesson 5, with some changes so that it display the menu according to the parameters strMenuTitle (The title of the menu), listMenu (The contents of the menu), and listFunction (Which function to call after user press the Enter)
首先我们看一下“robot.py”这个程序,它包含了一个【类】(Class),名字叫“ROBOT”,这个类里面有两个对象 “lcd”及 “btn”,它们是实例化了它们的父类“Screen()”及 “Button()”,然后我们又在这个类里家里一个新的方法叫“ShowMenu()”,去显示一个菜单。
在这个 ShowMenu() 方法里,我们主要是把第 5 课的函数拷贝了进来,作了一些改动,让它利用调用这个方法时候的参数 strMenuTitle (就是菜单的抬头名称),及 listMenu(就是菜单的选项),及 listFunction (就是选了菜单选项以后运行什么程序),来决定菜单的内容。
g.py
We create the robot object “rb” by using the statement:
我们使用对象“rb”来实例化 ROBOT 类:
rb = robot.ROBOT()
fun.py
After assigning values to strMenuTitle, listMenu and listFunction, we use the statement:
在给 strMenuTitle, listMenu, listFunction 赋值后,我们利用下面的句子:
g.rb.ShowMenu(strMenuTitle, listMenu, listFunction)
to display the menu
来显示菜单。
lesson6_01.py
the Main Program, mainly call the:
主程序主要调用:
g.funInitRobot()
to initialize the robot object “rb”, and call the:
来初始化 “rb” 对象,并且调用:
fun.StartProgram()
to start the program.
去开始程序的运行。
In the future, in the ROBOT class, we’ll add addition methods such as something like:
将来,这 ROBOT 类里,我们会加入其它方法,比方说:
MoveForward() (向前走)
MoveBackward() (向后走)
TurnLeft() (左拐)
TurnRight() (右拐)
so that you can use something like:
因此你可以使用类似:
g.rb.MoveForward()
to control the wheels (Motors) of the Robot.
去控制机械人的轮子。
It should be noted that, the statement in g.py:
要注意的是,在 g.py 里的这一句:
module = ‘fun’
and the statement in robot.py:
和在 robot.py 里的这一句:
module = __import__(g.module)
means that in robot.py, it will import fun.py
的意思是在 robot.py 里会载入 fun.py
Which means that in the future, robot.py is usually fixed, you don’t need to change any codes inside robot.py, what you need to change are probably g.py, fun.py(or another file name for another type of robot), and lesson6_01.py
这是什么意思呢?就是说将来的不同项目,robot.py 的程序内容是基本固定的,你只需要更改 g.py, fun.py 和 主程序的内容。
(译者按:这就是面向对象编程部分强大之处,已经写好的类,可以在将来的所有项目重复使用而不需要任何更改)
In our next lesson, we’ll learn how to control EV3 Motors.
在下一课,我们会学习如何控制 EV3 的马达。
始发于知乎专栏:ken