python的精髓_思维python2e的学习精髓(4):案例研究界面设计,ThinkPython2e,精粹,四,接口...

《Think Python 2e》学习精粹(四): 案例研究—接口设计

本章将通过一个案例研究,介绍如何设计出相互配合的函数;

1、turtle 模块

turtle

模块提供的

turtle.Turtle

函数创建一个 类型为

Turtle

的对象,可以赋值给变量,例如 bob 、sam 或者 jack 等(这里选的都是拟人化的名字);

>>> import turtle

>>> bob = turtle.Turtle()

>>> type(bob)

>>> print(bob)

Turtle 对象有一系列

method

(方法)可供调用:

bob.fd(100) :向前走100(像素);

bob.bk(100):向后退100(像素);

bob.lt(90):左转90(度);

bob.rt(90):右转90(度);

bob.pu():抬笔;

bob.pd():落笔;

>>> import turtle

>>> sam = turtle.Turtle()

>>> sam.fd(100)

>>> sam.lt(90)

>>> sam.fd(100)

>>> sam.lt(90)

>>> sam.fd(100)

>>> sam.lt(90)

>>> sam.fd(100)

>>> turtle.mainloop()

2、简单的重复

for 语句示例:

for i in range(4):

bob.fd(100)

bob.lt(90)

for 语句有一个以冒号结尾的语句头(header)以及一个缩进的语句体(body), 语句体可以包含任意条语句;

for 语句执行流程会贯穿整个语句体,然后再循环回顶部,所以也被称为循环(loop);

与自定义函数不同,for 语句的语句体不需要以空行结束;

for i in range(4):

print('Hello, World!')

print('I am gsf.')

PS C:\Users\Administrator> python D:\WorkSpace\thinkpython2e\ex_char4_4.py

Hello, World!

Hello, World!

Hello, World!

Hello, World!

I am gsf.

3、练习

Turtle 对象可以有多个,这里创建了 bob、 tom、sam 和 jack 等四个 Turtle 对象;

pu、fd、bk、lt、rt、pu 等方法组合可以使得 Turtle 对象移位;

turtle.mainloop()

引入是为了避免Python脚本在命令行执行完毕后,Turtle 对象自动销毁;如果在命令行输入Python语句,则不需要;

import math

import turtle

bob = turtle.Turtle()

tom = turtle.Turtle()

sam = turtle.Turtle()

jack = turtle.Turtle()

# 第二个小题(画可设边长的正方形),先把 Turtle 对象做了移位(下同)

def square(t, length):

for i in range(4):

t.fd(length)

t.lt(90)

sam.pu()

sam.bk(350)

sam.pd()

square(sam,100)

# 第三个小题(画多边形)

def polygon(t, length, n):

for i in range(n):

t.fd(length)

t.lt(360 / n)

tom.pu()

tom.fd(300)

tom.pd()

polygon(tom, 40, 10)

# 第四个小题(画圆)

def circle(t, r):

circumference = 2 * math.pi * r

n = int(circumference / 3) + 1

length = circumference / n

polygon(t, length, n)

circle(bob, 100)

# 第五个小题(画弧线),先把函数 polygon 进行泛化

def polygon_arc(t, length, n, angle):

for i in range(int(n * angle / 360)):

t.fd(length)

t.lt(360 / n)

def arc(t, r, angle):

circumference = 2 * math.pi * r

n = int(circumference / 3) + 1

length = circumference / n

polygon_arc(t, length, n, angle)

jack.pu()

jack.rt(90)

jack.fd(300)

jack.lt(90)

jack.pd()

arc(jack,100,120)

turtle.mainloop()

4、封装

encapsulation(封装)

:将一部分代码包装在函数里;

封装的好处之一,为这些代码赋予一个名字, 这充当了某种文档说明;

另一个好处是,如果重复使用代码, 调用函数更加简洁;

5、泛化

泛化(generalization)

:为函数增加一个形参被称作泛化;

下面三个函数是不断泛化的过程:

def square(t):

for i in range(4):

t.fd(100)

t.lt(90)

square(bob)

def square(t, length):

for i in range(4):

t.fd(length)

t.lt(90)

square(bob, 100)

def polygon(t, n, length):

angle = 360 / n

for i in range(n):

t.fd(length)

t.lt(angle)

polygon(bob, 7, 70)

泛化使得函数更通用;

在实参列表中加入形参的名称,这些被称作

关键字实参(keyword arguments)

polygon(bob, n=7, length=70)

实参和形参的工作方式: 当调用函数时,实参被赋给形参;

6、接口设计

函数的

接口(interface)

是一份关于如何使用该函数的总结:形参是什么?函数做什么?返回值是什么?

接口让调用者避免处理不必要的细节,直接做自己想做的事,那么这个接口就是“干净的”,如下例中的函数,调用者只须输入圆的半径 r 和 Turtle 对象名称这两个实参;

import math

def circle(t, r):

circumference = 2 * math.pi * r

n = int(circumference / 3) + 1

length = circumference / n

polygon(t, n, length)

接口让调用者处理不必要的细节,这个接口就是“不干净的”,如下例中的函数,调用者需输入模拟圆的多边形的边数的实参 n ;

import math

def circle(t, r, n):

circumference = 2 * math.pi * r

length = circumference / n

polygon(t, n, length)

7、重构

重构(refactoring)

:重新整理一个程序以改进函数接口和促进代码复用的过程;

下面第二个函数就是在第一个的基础上重构而得,增加了形参 angle ,促进函数复用;

def polygon(t, length, n):

for i in range(n):

t.fd(length)

t.lt(360 / n)

def polygon_arc(t, length, n, angle):

for i in range(int(n * angle / 360)):

t.fd(length)

t.lt(360 / n)

8、开发方案

开发计划(development plan)

:是一种编写程序的过程;

此例中我们使用的过程是“封装和泛化”:

从写一个没有函数定义的小程序开始;

一旦该程序运行正常,找出其中相关性强的部分,将它们封装进一个函数并给它一个名字;

通过增加适当的形参,泛化该函数。

重复1–3步,直到你有一些可正常运行的函数。 复制粘贴有用的代码,避免重复输入(和重新调试);

寻找机会通过重构改进程序。 例如,如果在多个地方有相似的代码,考虑将它分解到一个合适的通用函数中;

事先不知道如何将程序分解为函数,这是个很有用办法;

9、文档字符串

文档字符串(docstring)

:位于函数开始位置的一个字符串, 解释了函数的接口;

所有的文档字符串都是三重引号(triple-quoted)字符串,也被称为多行字符串;

def polygon_arc(t, n, length, angle):

"""Draws n line segments with the given length and

angle (in degrees) between them. t is a turtle.

"""

for i in range(n):

t.fd(length)

t.lt(angle)

简要,包括了他人使用此函数时需要了解的关键信息:

说明该函数做什么(不介绍背后的具体细节);

解释每个形参对函数的行为有什么影响;

每个形参应有的类型 (如果它不明显的话);

写文档是接口设计中很重要的一部分;

10、调试

函数调用时对实参的要求被称作

先决条件(preconditions)

, 因为它们应当在函数开始执行之前成立(true);

函数结束时的条件是

后置条件(postconditions)

:函数预期的效果(如画线段)及任何其他附带效果 (如 Turtle移动、转向或者做其它改变);

如果调用者违反一个先决条件,导致函数没有正确工作,则故障(bug)出现在调用者一方,而不是函数;

如果满足了先决条件,没有满足后置条件,故障就在函数一方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值