了解Python 3 中的代码重用和模块化
什么是面向对象编程(OOP)?
OOP 是一种基于“对象”概念的编程范式,它可能包含数据,以字段的形式,通常称为属性;和代码,以过程的形式,通常称为方法。在这里了解更多信息,或者只是谷歌“OOP”。
对象具有特性和特性,称为属性,并且可以通过它们的方法做各种事情。 OOP 最大的特点是对象可以很好地交互,甚至在未来被塑造,这使得它们对开发人员、规模、随时间的变化、测试等等非常友好。
什么是模块化?
模块化是指先制作多个模块,然后将它们链接组合成一个完整系统的概念(即软件/Web应用程序可以划分为更小的模块的程度称为模块化)。模块化实现了可重用性并最大限度地减少了重复。
文章流程
目标:学习面向对象编程——模块化。我们如何将我们的代码的某些部分变成一个库,以便任何人都可以使用它以供将来参考。使代码模块化将实现可重用性并最大限度地减少重复。
依赖: pygame
总结:我们要做一个小游戏(不是真正的游戏),只是一个环境和其中的一些对象。我们将尝试使环境静态和对象(在我们的例子中是 blob)模块化。我们将使用 PyGame,因为它为我们提供了一种简单的方法来实际可视化我们正在做什么和构建什么,因此我们可以看到我们的对象在行动。我们要做的是构建 Blob World,这是一个由参与者组成的世界,称为 blob。不同的 blob 具有不同的属性,并且 blob 需要在其 Blob World 环境中以其他方式函数。通过这个例子,我们将能够说明模块化。
我们将学习过程分为两个阶段。
- 创建环境和 Blob
- 了解模块化
存储库(Github):源
BLOB 世界( Python代码)
Python
import pygame
import random
STARTING_BLUE_BLOBS = 10
STARTING_RED_BLOBS = 3
WIDTH = 800
HEIGHT = 600
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
game_display = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Blob World")
clock = pygame.time.Clock()
class Blob:
def __init__(self, color):
self.x = random.randrange(0, WIDTH)
self.y = random.randrange(0, HEIGHT)
self.size = random.randrange(4,8)
self.color = color
def move(self):
self.move_x = random.randrange(-1,2)
self.move_y = random.randrange(-1,2)
self.x += self.move_x
self.y += self.move_y
if self.x < 0: self.x = 0
elif self.x > WIDTH: self.x = WIDTH
if self.y < 0: self.y = 0
elif self.y > HEIGHT: self.y = HEIGHT
def draw_environment(blob_list):
game_display.fill(WHITE)
for blob_dict in blob_list:
for blob_id in blob_dict:
blob = blob_dict[blob_id]
pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size)
blob.move()
pygame.display.update()
def main():
blue_blobs = dict(enumerate([Blob(BLUE) for i in range(STARTING_BLUE_BLOBS)]))
red_blobs = dict(enumerate([Blob(RED) for i in range(STARTING_RED_BLOBS)]))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
draw_environment([blue_blobs,red_blobs])
clock.tick(60)
if __name__ == '__main__':
main()
输出:
PART(1/2):Blob World在这一部分中,我们将创建一个简单的游戏环境和其中的一些对象,因为将我们创建的内容可视化是学习编程的一种特殊方式。这里解释了使用 pygame 创建 blob 世界(即它的环境和它的对象)的解释。我们需要了解的是如何使我们的代码模块化。
PART(2/2):模块化在第二部分,我们将了解面向对象编程的一个基本特征,即模块化。到目前为止,我们还没有引入任何会使这个(BLOB WORLD 代码)随着时间的推移难以维护或扩展的东西,至少在我们可以用 PyGame 做的范围内。让它模块化怎么样?有一个非常简单的测试,让我们尝试导入它!
为此,让我们有两个文件。让我们复制 Blob 类并随机生成一个新文件:blob.py
import random
class Blob:
def __init__(self, color):
self.x = random.randrange(0, WIDTH)
self.y = random.randrange(0, HEIGHT)
self.size = random.randrange(4,8)
self.color = color
def move(self):
self.move_x = random.randrange(-1,2)
self.move_y = random.randrange(-1,2)
self.x += self.move_x
self.y += self.move_y
if self.x WIDTH: self.x = WIDTH
if self.y HEIGHT: self.y = HEIGHT
回到我们原来的文件,让我们删除 Blob 类,然后从 blob.py 中导入 Blob。
import pygame
import random
from blob import Blob
STARTING_BLUE_BLOBS = 10
...
立即,我们在 blob.py 文件中得到一个错误,关于我们的 Blob 类,其中我们有一些未定义的变量。这绝对是写类的问题,我们应该尽量避免在类外使用常量或变量。让我们将这些值添加到 __init__ 方法中,然后修改我们使用常量的所有部分。
所以,这是我们新的 Blob 类文件:blob.py
接下来,在我们的原始文件中,当我们调用 Blob 类时,它期望这些参数有一些值,因此您将在主函数中添加这些值:
def main():
blue_blobs = dict(enumerate([Blob(BLUE,WIDTH,HEIGHT) for i in range(STARTING_BLUE_BLOBS)]))
red_blobs = dict(enumerate([Blob(RED,WIDTH,HEIGHT) for i in range(STARTING_RED_BLOBS)]))
while True:
...
太好了,所以现在我们的 Blob 类至少可以被导入,所以它本质上已经是模块化的了!另一个好主意是尝试为使用您的代码的开发人员提供尽可能多的功能,并使您的类尽可能泛化。至少有一个例子,我们可以肯定地给使用这个类的程序员更多的东西是在 blob 大小的定义中:
self.size = random.randrange(4,8)
我们有什么理由不想给程序员一个简单的方法来改变这些?我不这么认为。然而,与 x_boundary 和 y_boundary 不同,我们不一定*需要*程序员为我们提供大小值,因为我们至少可以使用合理的起始默认值。因此,我们可以这样做:
class Blob:
def __init__(self, color, x_boundary, y_boundary, size_range=(4,8)):
self.x_boundary = x_boundary
self.y_boundary = y_boundary
self.x = random.randrange(0, self.x_boundary)
self.y = random.randrange(0, self.y_boundary)
self.size = random.randrange(size_range[0],size_range[1])
self.color = color
现在,如果程序员想改变大小,他们可以,否则他们不必。如果他们愿意,我们可能还希望允许程序员修改 blob 的速度:
import random
class Blob:
def __init__(self, color, x_boundary, y_boundary, size_range=(4,8), movement_range=(-1,2)):
self.size = random.randrange(size_range[0],size_range[1])
self.color = color
self.x_boundary = x_boundary
self.y_boundary = y_boundary
self.x = random.randrange(0, self.x_boundary)
self.y = random.randrange(0, self.y_boundary)
self.movement_range = movement_range
def move(self):
self.move_x = random.randrange(self.movement_range[0],self.movement_range[1])
self.move_y = random.randrange(self.movement_range[0],self.movement_range[1])
self.x += self.move_x
self.y += self.move_y
if self.x self.x_boundary: self.x = self.x_boundary
if self.y self.y_boundary: self.y = self.y_boundary
现在我们已经打开了很多课程。还有什么东西会向我们跳出来吗?是的,我们强制 blob 保持在界内的线。是否存在我们希望 blob 能够在视野之外自由漫游的示例?当然!这个边界代码有用吗?程序员是否很可能想要经常使用它?当然!但是,根本没有代码或给它自己的方法更有意义,如下所示:
import random
class Blob:
def __init__(self, color, x_boundary, y_boundary, size_range=(4,8), movement_range=(-1,2)):
self.size = random.randrange(size_range[0],size_range[1])
self.color = color
self.x_boundary = x_boundary
self.y_boundary = y_boundary
self.x = random.randrange(0, self.x_boundary)
self.y = random.randrange(0, self.y_boundary)
self.movement_range = movement_range
def move(self):
self.move_x = random.randrange(self.movement_range[0],self.movement_range[1])
self.move_y = random.randrange(self.movement_range[0],self.movement_range[1])
self.x += self.move_x
self.y += self.move_y
def check_bounds(self):
if self.x self.x_boundary: self.x = self.x_boundary
if self.y self.y_boundary: self.y = self.y_boundary
现在,程序员可以决定是否使用它。您还可以在 move 方法中提供某种参数,如果为 True,则将强制执行边界。
因此,我们了解了如何使我们的Python代码模块化。
资源:
- 原创视频系列(由 pythonprogramming.net 提供)
- pythonprogramming.net
- 哈里森·金斯利(谢谢 H.Kinsley)