上课笔记。
这周讲到了Event-driven Programming。
先举个栗子,这是一个猜数字的小游戏:
- # template for "Guess the number" mini-project
- # input will come from buttons and an input field
- # all output for the game will be printed in the console
- import simplegui
- import random
-
- secret_number = 0
- end = 100
- remaining_guess = 7
-
- # helper function to start and restart the game
- def new_game():
- # initialize global variables used in your code here
- global secret_number
- global end
- secret_number = random.randrange(0, end)
-
- print "New game. Range is from 0 to", end
- print "Number of remaining guesses is", remaining_guess
- print ""
-
-
- # define event handlers for control panel
- def range100():
- # button that changes the range to [0,100) and starts a new game
- global remaining_guess
- remaining_guess = 7
-
- global end
- end = 100
-
- new_game()
-
-
- def range1000():
- # button that changes the range to [0,1000) and starts a new game
- global remaining_guess
- remaining_guess = 10
-
- global end
- end = 1000
-
- new_game()
-
- def input_guess(guess):
- # main game logic goes here
- global secret_number
- global remaining_guess
-
- guessi = int(guess)
- print "Guess was", guessi
- remaining_guess -= 1
- print "Number of remaining guesses is", remaining_guess
-
- if guessi < secret_number:
- print "Higher"
- elif guessi > secret_number:
- print "Lower"
- else:
- print "Correct"
- print ""
- range100()
-
- print ""
-
- if remaining_guess == 0:
- print "You lose."
- print ""
- range100()
-
-
- # create frame
- frame = simplegui.create_frame("game", 200, 200)
-
- # register event handlers for control elements and start frame
- frame.add_button('Range is [0,100)', range100, 200)
- frame.add_button('Range is [0,1000)', range1000, 200)
-
- frame.add_input("Input your guess: ", input_guess, 50)
-
-
-
- # call new_game
- new_game()
-
- # always remember to check your completed program against the grading rubric
复制代码 http://www.codeskulptor.org/#user41_5azXiELlsx_1.py
这个网址要翻一下墙的哈 - -
而且由于simpleGUI这个API的特殊性,貌似只能在codeskulpter网站运行。
点开运行了之后是这样的:

运行结果是这样的: - New game. Range is from 0 to 100
- Number of remaining guesses is 7
-
- Guess was 25
- Number of remaining guesses is 6
- Higher
-
- Guess was 50
- Number of remaining guesses is 5
- Lower
-
- Guess was 38
- Number of remaining guesses is 4
- Lower
-
- Guess was 31
- Number of remaining guesses is 3
- Higher
-
- Guess was 34
- Number of remaining guesses is 2
- Lower
-
- Guess was 33
- Number of remaining guesses is 1
- Lower
-
- Guess was 32
- Number of remaining guesses is 0
- Correct
-
- New game. Range is from 0 to 100
- Number of remaining guesses is 7
复制代码
这个module的重点是,event-driven programming的思想。
我们知道,一般玩个什么游戏、使个什么交互应用,每次有不同的操作,就会产生不同的结果。
如下图所示,初始化之后,根据用户的操作,会产生不同的触发事件,当有input event进来的时候,就会等待handler来进行处理,知道最后程序运行结束。

event的种类常见的以下几种:

一般使用下面的program structure是比较合理而符合人的认知以及写代码结构的:

那么这就是刚才的小program里的代码编写顺序。
几点需要注意的tips:
1. 全局变量与局部变量
Python与其他编程语言比较相异的一点是,Python对于变量的定义区分基本上是没有的- -。
因此就会产生一点需要注意的问题。 - num1 = 1
- print "num1 =", num1
-
- def fun():
- num2 = num1 + 1
- print "num2 =", num2
-
- fun()
-
- print "num1 =", num1
- print "num2 =", num2
复制代码 运行这个Python文件,输出结果是这样的: - num1 = 1
- num2 = 2
- num1 = 1
- num2 =
- Traceback (most recent call last):
- Line 11, in <module>
- print "num2 =", num2
- NameError: name 'num2' is not defined
复制代码 出现了一个NameError,这是为什么呢?
因为在函数体内部定义的变量是局部变量,当程序执行调用函数体的时候才会产生,当函数体调用结束后这个局部变量也就随之消失了。因此在全局中要求输出num2的时候它已经不在了。
而全局变量则不然,它是随着程序一直存在的。
把上面的例子改一改: - num1 = 1
- print "num1 =", num1
-
- def fun():
- num1 = 2
- num2 = num1 + 1
- print "num2 =", num2
-
- fun()
-
- print "num1 =", num1
复制代码 运行结果是: - num1 = 1
- num2 = 3
- num1 = 1
复制代码 我们看到,最后输出的num1还是全局变量的num1,而非函数体中的那一个,函数体中的那一个早就随函数调用的结束消失了。
那么,如果我们要在函数中用到全局变量,我们应该怎么用呢?
在函数中变量前加global申明即可。
如下例所示: - num = 4
-
- def fun1():
- global num
- num = 5
-
- def fun2():
- global num
- num = 6
-
- print num
- fun1()
- print num
- fun2()
- print num
复制代码 运行结果是: 复制代码
2. 输入值的转换
在课上使用的simpleGUI的API中,使用add_input这个接口输入的值都是string类型的,因此如果我们需要数字,必须进行强制类型转换。
在开头的例子中,用的是这行代码: 复制代码
3. 代码规范(参见Python官方文档https://docs.python.org/release/2.6.8/tutorial/controlflow.html#intermezzo-coding-style)
提高易读性,减少易错性。 - Use 4-space indentation, and no tabs.
4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation (easier to read). Tabs introduce confusion, and are best left out.- Wrap lines so that they don’t exceed 79 characters.
- This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.
- Use blank lines to separate functions and classes, and larger blocks of code inside functions.
- When possible, put comments on a line of their own.
- Use docstrings.
- Use spaces around operators and after commas, but not directly inside bracketing constructs: a = f(1, 2) + g(3, 4).
- Name your classes and functions consistently; the convention is to use CamelCase for classes and lower_case_with_underscores for functions and methods. Always use self as the name for the first method argument (see A First Look at Classes for more on classes and methods).
- Don’t use fancy encodings if your code is meant to be used in international environments. Plain ASCII works best in any case.
|