class PhoneBook:
def __init__(self):
self.__persons = {}
def add_number(self, name: str, number: str):
if name in self.__persons:
self.__persons[name].add_number(number)
else:
self.__persons[name] = Person(name=name, numbers=[number])
def get_entry(self, name: str):
# IMPORTANT this part bellof (2-3 lines) is problematic for the given test case...
if name in self.__persons and not self.__persons[name].address():
print(self.__persons[name].numbers()[0])
print("address unknown")
elif name in self.__persons and not self.__persons[name].numbers():
print("number unknown")
print(self.__persons[name].address())
elif name not in self.__persons:
print("address unknown")
print("number unknown")
else:
for num in self.__persons[name].numbers():
print(num)
print(self.__persons[name].address())
def add_address(self, name:str, address:str):
if name in self.__persons:
self.__persons[name].add_address(address)
else:
self.__persons[name] = Person(name = name, address=address)
def all_entries(self):
return self.__persons
class PhoneBookApplication:
def __init__(self):
self.__phonebook = PhoneBook()
def help(self):
print("commands: ")
print("0 exit")
print("1 add number")
print("2 search")
print("3 add address")
def add_number(self):
name = input("name: ")
number = input("number: ")
self.__phonebook.add_number(name, number)
def search(self):
name = input("name: ")
self.__phonebook.get_entry(name)
def add_address(self):
name = input("name: ")
address = input("address: ")
if address:
self.__phonebook.add_address(name, address)
else:
raise ValueError("Enter a valid address.")
def execute(self):
self.help()
while True:
print("")
command = input("command: ")
if command == "0":
break
elif command == "1":
self.add_number()
elif command == "2":
self.search()
elif command == "3":
self.add_address()
else:
self.help()
class Person:
def __init__(self, name:str, address:str = None, numbers:list = None):
self.__name = name
self.__address = address if address is not None else ""
self.__numbers = numbers if numbers is not None else []
def name(self):
return self.__name
def numbers(self):
return self.__numbers
def address(self):
if self.__address:
return self.__address
else:
return None
def add_number(self, number:str):
if number:
self.__numbers.append(number)
else:
raise ValueError("Enter a valid number.")
def add_address(self, address:str):
if address:
self.__address = address
else:
raise ValueError("Enter a valid address.")
def __str__(self):
return f"{self.numbers()}\n{self.address()}"
phonebook = PhoneBookApplication()
phonebook.execute()
测试失败输出:
#IMPORTANT TEST FAIL OUTPUT:
# Test failed
# PhoneBook2_Part2Test: test_3_works_many_numbers
# The output of your program should be
# 040-999999
# with input
# 1
# Emilia
# 09-123456
# 1
# Emilia
# 040-999999
# 2
# Emilia
# 0
# Now the output was
# commands:
# 0 exit
# 1 add number
# 2 search
# 3 add address
#
# 09-123456
# address unknown
import unittest
from unittest.mock import patch
from tmc import points, reflect
from tmc.utils import load, load_module, reload_module, get_stdout, check_source
from functools import reduce
import os
import os.path
import textwrap
from random import choice, randint
from datetime import date, datetime, timedelta
def test_3_works_many_numbers(self):
syote = ["1", "Emilia", "09-123456", "1", "Emilia", "040-999999", "2", "Emilia", "0"]
with patch('builtins.input', side_effect=syote):
try:
reload_module(self.module)
except:
self.fail(f"Check that the program works with input\n{s(syote)}")
output = get_stdout()
expected = "09-123456"
self.assertTrue(expected in output,
f"The output of your program should be\n{expected}\nwith input\n{s(syote)}\nNow the output was\n{output}")
expected = "040-999999"
self.assertTrue(expected in output,
f"The output of your program should be\n{expected}\nwith input\n{s(syote)}\nNow the output was\n{output}")
名称
class PhoneBook:
def __init__(self):
self.__persons = {}
single
self._persons
对人属性{名称,地址,数字}。使用“包括电池” add_number()方法繁琐。 喜欢依靠 defaultdict(人)
.dataclass
班级真的想成为一个
sign签名的这一方面显然是不正确的,如Mypy的标记:
_
相似,因为没有一个显然不是列表。 property
这个呼叫站点访问和实现, 感到有些不适。Person
我的意思是,当然可以起作用。
但是它想成为一个address: str = None,
numbers
方法调用表示法。
相似于
if ... and not self.__persons[name].address():
...
def address(self):
if self.__address:
return self.__address
else:
return None
属性。
评估副作用
@property
()
numbers
或
def get_entry(self, name: str):
,或类似的东西。 名字真的很重要;它们影响我们对代码的推理方式。Mapping {如果,埃利夫,elif}就可以了。 您可能更喜欢使用
... -> None:
用于分配功能:
def print_entry
这个似乎不建议这样做。
def display_entry
我不知道“ Syote”的含义。 但是看来您想覆盖
dict
向目标代码提供某些输入。
更合适的方法来“仪器目标代码!” 使用自动测试将是重构功能 变成一对功能,其中一个接受简单 输入参数,另一个调用
dispatch = {
"0": sys.exit,
"1": self.add_number,
"2": self.search,
"3": self.add_address,
}
。
显然,从stdin中消耗角色是一种副作用,
因此,将是“纯”功能,而另一个将
有副作用。
您的代码库的上升空间是您会找到一些
类型的功能更容易测试其他功能。