当前位置: > 质感生活
balcony是什么意思(到底什么是面向对象编程|OOP?)
2023-05-25 11:58:01
Mars
126
来源:读芯术

balcony是什么意思?全文共9402字,预计学习时长19分钟

balcony是什么意思

图片来源:https://unsplash.com/@marcelheil

Python是数据科学中一种十分常用的编程语言。对一些人来讲,它的语言灵活、可读性强,对另一些人来讲,它简单易上手,对大多数人来讲,是由于它的多面性。

我们将Python称为多面语言,因为它允许使用四种不同的编码规范进行编码:功能性、命令性、面向对象和面向过程。这些编码风格被正式称为编程范例(

https://en.wikipedia.org/wiki/Programming_paradigm),代表了一种根据语言特性对语言进行分类的方法。

本文将对面向对象编程( OOP )(

https://en.wikipedia.org/wiki/Object-oriented_programming)进行研究。

什么是面向对象编程( OOP )?

OOP是一种基于对象概念的编程范式。在计算机科学中,“对象”一词可以指代不同概念,但基本上,它是标识符所引用的内存值(

https://en.wikipedia.org/wiki/Object_(computer_science))。

在OOP的执行环境中,对象指状态(变量)和行为(方法)的组合。面向对象方法的目标是创建可重复使用的软件,以下四个特征使其更易维护:封装、抽象、继承和多态。

还可以进一步区分面向对象语言,例如,基于类和基于原型。

在基于类的OOP中,对象是类的实例。类是关于如何定义某些内容的蓝图,但它不会提供内容本身——它只是提供结构。

学习策略

有许多方法可以用来学习和练习OOP,因必须选择其中一种,所以笔者决定采用莎士比亚的《罗密欧与朱丽叶》的故事线,制作一个简单的基于文本的游戏。具体步骤如下:

1. 写下故事

2. 指出问题

3. 确定实体——这些是类别

4. 创建实体层次结构

5. 确定实体的功能

6. 编写测试

7. 检查测试是否成功——因未编写过任何代码,所以最初会出现错误!

8. 编写代码

9. 重复!重构!精炼!

这个过程不是一成不变的,也不是注定要被它牵着鼻子走。这一系列步骤帮助笔者开始了编程之路。面向对象不仅仅是一种编程范式,还是一种解决问题的方法,尽管它并非没有非议,但在构建复杂系统时却是一个很好的选择。

兔子洞(The Rabbit Hole)

请注意步骤6:编写测试。现在,这个不是笔者最初的步骤。笔者正计划给各类别编码。但在研究OOP时,笔者发现了测试驱动开发( TDD )这一概念。

TDD是一种编程实践,开始于程序每个功能所进行的测试的设计和开发。这样,在开始编写代码之前,你就不得不考虑其规范、要求或设计。换句话说,在编写任何代码之前,都要编写代码来测试代码。

是不是感到迷惑不解?笔者也是。但做这个练习是完全值得的。

测试驱动开发和单元测试

TDD的过程非常简单:

图片来自Kanchan Kulkarni的TDD教程(

https://www.guru99.com/test-driven-development.html)

1. 写出测试

2. 运行测试

3. 写下代码

4. 运行测试

5. 重构代码

6. 重复步骤

在这个例子中,笔者使用单元测试(

http://softwaretestingfundamentals.com/unit-testing/)进行TDD。单元测试是软件测试的第一级,其目的是验证程序中的每个单元是否按设计执行。可以使用不同的框架来执行单元测试。

人们对于TDD持有两种不同观点。就我个人的经历而言,TDD的优点如下:

· 在毫无方向地开始输入代码之前,TDD迫使人们必须考虑要解决的问题。

· 在基于类别的OOP的特殊情况下,它能帮助理解每个类别内容。如职责是什么?必须知道什么?——目标是低耦合和高内聚性时,这变得更加息息相关。

· 尽管一开始它可能会减慢速度,但从长远来看,它通过最小化调试时间来节省时间。

· 它鼓励更好的设计,使代码更容易维护、减少冗余(不写重复代码!),并在需要时安全地重构。

· 它是一个动态文档——只需查看测试,就能理解每个单元应该做什么,如此一来,代码就能自证其明。

罗密欧与朱丽叶——代码与测试

在考虑了游戏的故事性之后,笔者决定采用两个不同的故事线:经典桥段和另类桥段。第一个是人们熟知的罗密欧与朱丽叶,第二个故事对我们来说则较为陌生。

故事安排(创建不同类别的引用)如下:

· 场景:蒙面舞会、阳台、决斗,安排、药剂师、卡普莱特墓和另类结局。该“场景”有两个主要职责,即为玩家描述场景,以及以是非问题提示玩家从而获取信息输入。

· 地图:地图就像一个有限状态机(

https://en.wikipedia.org/wiki/Deterministic_finite_automaton)。它具有有限的状态(场景)、转换函数(从一个场景移动到另一个场景)和开始状态(第一个场景)。

· 故事线:定义两个唯一常量值。

从场景的定义中可以看到,所有场景都有相同的职责,只有它们的内容发生了变化(场景的描述和提示)。这就是为什么要利用继承的概念。这个概念允许定义一个类,该类别从另一个类中继承了所有方法和属性;在这种情况下,不重复写代码至关重要。

class Storyline(Enum):

CLASSIC = "classic"

ALTERNATIVE = "alternative"

对于故事线这一类别,笔者使用了Python’s enumeration type(

https://docs.python.org/3/library/enum.html)或enum。在文档中,它们的定义为“一组绑定到唯一常量值的符号名(成员)。在枚举中,成员可以按标识进行比较,枚举本身可以循环访问。”

接下来,我们有Sence类和MockSence类。测试代码中有两个值得注意的特征:1.使用MockMap类;2.创建TestScene类以测试Scene类。在单元测试阶段,将创建一个Test类为每个类编写测试。

Class Scene(object):

a_map = None

def __init__(self, a_map):

self.a_map = a_map

def get_message(self):

return """

This scene is yet to be initialized

"""

def get_prompt(self):

return """

This scene is yet to be initialized

"""

def enter(self):

self.print_description()

self.prompt_user()

def print_description(self):

print(dedent(self.get_message()))

def prompt_user(self):

input_from_user = input(self.get_prompt()).lower()

if input_from_user == "yes":

self.a_map.advance_scene(Storyline.CLASSIC)

elif input_from_user == "no":

self.a_map.advance_scene(Storyline.ALTERNATIVE)

self.a_map.play()

import unittest

from unittest.mock import patch, mock_open

import sys

import io

from romeo_and_juliet import *

class MockMap(Map):

storyline = None

play_executed = False

def advance_scene(self, a_storyline):

self.storyline = a_storyline

def play(self):

self.play_executed = True

class TestScene(unittest.TestCase):

def test_print_description(self):

a_scene = Scene(Map())

Releasing standard output.

sys.stdout = sys.__stdout__

def test_prompt_user(self):

a_map = MockMap()

a_scene = Scene(a_map)

with patch("builtins.input", return_value = "yes"):

a_scene.prompt_user()

self.assertEqual(a_map.storyline, Storyline.CLASSIC)

with patch("builtins.input", return_value = "no"):

a_scene.prompt_user()

self.assertEqual(a_map.storyline, Storyline.ALTERNATIVE)

self.assertTrue(a_map.play_executed)

最后,来看看Map类和TestMap类。和往常一样,我们会创建一个模拟测试,但在本例中,是为Scene类创建一个MockScene类。

class Map(object):

scenes = None

current_scene = None

def __init__(self):

self.scenes = {

"the_masked_ball": TheMaskedBall(self),

"the_balcony": TheBalcony(self),

"the_duel": TheDuel(self),

"the_arrangement": TheArrangement(self),

"the_apothecary": TheApothecary(self),

"the_capulet_tomb": TheCapuletTomb(self),

"the_alternative_ending": TheAlternativeEnding(self)

}

self.current_scene = self.scenes["the_masked_ball"]

def get_current_scene(self):

return self.current_scene

def play(self):

self.current_scene.enter()

def advance_scene(self, storyline):

if storyline == Storyline.CLASSIC:

if self.current_scene == self.scenes["the_masked_ball"]:

self.current_scene = self.scenes["the_balcony"]

elif self.current_scene == self.scenes["the_balcony"]:

self.current_scene = self.scenes["the_duel"]

elif self.current_scene == self.scenes["the_duel"]:

self.current_scene = self.scenes["the_arrangement"]

elif self.current_scene == self.scenes["the_arrangement"]:

self.current_scene = self.scenes["the_apothecary"]

elif self.current_scene == self.scenes["the_apothecary"]:

self.current_scene = self.scenes["the_capulet_tomb"]

elif self.current_scene == self.scenes["the_capulet_tomb"]:

raise Exception

if storyline == Storyline.ALTERNATIVE:

if self.current_scene == self.scenes["the_masked_ball"]:

self.current_scene = self.scenes["the_alternative_ending"]

elif self.current_scene == self.scenes["the_balcony"]:

self.current_scene = self.scenes["the_alternative_ending"]

elif self.current_scene == self.scenes["the_duel"]:

self.current_scene = self.scenes["the_alternative_ending"]

elif self.current_scene == self.scenes["the_arrangement"]:

self.current_scene = self.scenes["the_alternative_ending"]

elif self.current_scene == self.scenes["the_apothecary"]:

self.current_scene = self.scenes["the_alternative_ending"]

elif self.current_scene == self.scenes["the_alternative_ending"]:

raise Exception

class MockScene(Scene):

was_entered = False

def enter(self):

self.was_entered = True

class TestMap(unittest.TestCase):

def test_play(self):

a_map = Map()

mock_scene = MockScene(a_map)

a_map.current_scene = mock_scene

a_map.play()

self.assertTrue(mock_scene.was_entered)

def test_initial_state(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

def test_advance_scene_classic(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheBalcony)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheDuel)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheArrangement)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheApothecary)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheCapuletTomb)

with self.assertRaises(Exception):

a_map.advance_scene(Storyline.CLASSIC)

def test_advance_scene_alternative_one(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

a_map.advance_scene(Storyline.ALTERNATIVE)

self.assertIsInstance(a_map.get_current_scene(), TheAlternativeEnding)

with self.assertRaises(Exception):

a_map.advance_scene(Storyline.ALTERNATIVE)

def test_advance_scene_alternative_two(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheBalcony)

a_map.advance_scene(Storyline.ALTERNATIVE)

self.assertIsInstance(a_map.get_current_scene(), TheAlternativeEnding)

with self.assertRaises(Exception):

a_map.advance_scene(Storyline.ALTERNATIVE)

def test_advance_scene_alternative_three(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheBalcony)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheDuel)

a_map.advance_scene(Storyline.ALTERNATIVE)

self.assertIsInstance(a_map.get_current_scene(), TheAlternativeEnding)

with self.assertRaises(Exception):

a_map.advance_scene(Storyline.ALTERNATIVE)

def test_advance_scene_alternative_four(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheBalcony)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheDuel)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheArrangement)

a_map.advance_scene(Storyline.ALTERNATIVE)

self.assertIsInstance(a_map.get_current_scene(), TheAlternativeEnding)

with self.assertRaises(Exception):

a_map.advance_scene(Storyline.ALTERNATIVE)

def test_advance_scene_alternative_five(self):

a_map = Map()

self.assertIsInstance(a_map.get_current_scene(), TheMaskedBall)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheBalcony)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheDuel)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheArrangement)

a_map.advance_scene(Storyline.CLASSIC)

self.assertIsInstance(a_map.get_current_scene(), TheApothecary)

a_map.advance_scene(Storyline.ALTERNATIVE)

self.assertIsInstance(a_map.get_current_scene(), TheAlternativeEnding)

with self.assertRaises(Exception):

a_map.advance_scene(Storyline.ALTERNATIVE)

留言 点赞 关注

我们一起分享AI学习与发展的干货

编译组:余书敏、张璐瑶

相关链接:

https://towardsdatascience.com/object-oriented-programming-and-the-magic-of-test-driven-development-d377acae85fa

如需转载,请后台留言,遵守转载规范

本文关键词: balcony是什么意思
本文标签: