我有以下问题和两个非常重要的问题。 编写一个名为文字游戏的类。它应该有一个包含单词列表的字段。用户 的类应将他们要使用的单词列表传递给类。应该有 以下方法:
- words_with_length(长度) — 返回长度长度的所有单词的列表
- starts_with(s) — 返回以 s 开头的所有单词的列表
- ends_with(s) — 返回以 s 结尾的所有单词的列表
- 回文() — 返回列表中所有回文的列表
第一个问题。编译我的程序后,方法以返回相同的单词开头,以返回相同的单词结束。 下一个问题。在这种情况下,我创建了一个包含三个名称的列表。但是,如果我想要求列表大小并在要求输入单词的同时迭代它怎么办。我怎样才能实现这个想法?
class Wordplay:
def __init__(self):
self.words_list=[]
def words_with_lenght(self,lenght):
for i in range(0,len(self.words_list)-1):
if len(self.words_list[i])==lenght:
return self.words_list[i]
def starts_with_s(self,s):
for i in range(0,len(self.words_list)-1):
if s.startswith('s')==True:
return self.words_list[i]
def ends_with_s(self,s):
for i in range(0,len(self.words_list)-1):
if s.endswith('s')==True:
return self.words_list[i]
def palindromes(self):
for i in range(0,len(self.words_list)-1):
normal_word=self.words_list[i]
reversed_word=normal_word[::-1]
if reversed_word==normal_word:
return reversed_word
verification=Wordplay()
verification.words_list=['sandro','abba','luis']
lenght=int(input('Digit size you want to comparen'))
s='s'
print(verification.words_with_lenght(lenght))
print(verification.starts_with_s(s))
print(verification.ends_with_s(s))
print(verification.palindromes())
如果我输入例如大小 4,我希望结果是: 阿巴,路易斯 ; 桑德罗;路易斯;阿爸,不是—— 阿爸;桑德罗;桑德罗;阿爸
在第if s.startswith('s')==True:
行中,您已将字符串"s"
传递到函数中,导致
if 's'.startswith('s')==True:
# ^^^
return self.words_list[i]
这个条件总是正确的。您可能根本不需要这里的参数,因为分配要求您"s"
硬编码。您可以使用:
if self.words_list[i].startswith('s'):
return self.words_list[i]
请注意,上面的示例在找到匹配项后立即使用return
。这是一个问题。此程序中的循环会提前中断,一旦找到单个匹配项,就会从函数中返回。您可能打算将每个成功的匹配项附加到列表中并返回结果列表,或者使用yield
关键字返回生成器(但如果调用方希望从生成器获得持久列表,则需要使用list()
)。使用列表构建结果如下所示:
result = []
for i in range(len(self.words_list)):
if self.words_list[i].startswith('s'):
result.append(self.words_list[i])
return result
另一个问题:该程序中的循环不会一直遍历各自的列表。range()
函数包含开始和排除结束,因此您可能打算range(len(self.words_list))
而不是range(0, len(self.words_list) - 1)
。
除此之外,我还想建议一些设计和风格点:
在运算符之间使用水平间距,并在块周围使用垂直空格。
foo=bar.corge(a,b,c) if foo==baz: return quux
更清晰为
foo = bar.corge(a, b, c) if foo == baz: return quux
使用 4 个空格而不是 2 个空格进行缩进,这样可以更轻松地快速确定哪个代码在哪个块中。
- 更喜欢
for element in my_list
而不是for i in range(len(my_list))
。如果需要索引,在大多数情况下可以使用for i, elem in enumerate(my_list)
.更好的是,使用列表推导来执行过滤操作,这是此逻辑的大部分。
没有必要 使用
if condition == True
.if condition
就足够了。您可以简化令人困惑和不准确的逻辑,例如:def palindromes(self): for i in range(0,len(self.words_list)-1): normal_word=self.words_list[i] reversed_word=normal_word[::-1] if reversed_word==normal_word: return reversed_word
例如:
def palindromes(self): return [word for word in self.words_list if word[::-1] == word]
也就是说,尽可能避免使用中间变量和索引。
我知道你可能被设计束缚住了,但这对我来说是一种编写实用程序类的奇怪方式。作为对可迭代对象进行操作的静态方法,它会更灵活。典型用法可能是:
from Wordplay import is_palindrome is_palindrome(some_iterable)
而不是:
wordplay = Wordplay(some_iterable) wordplay.palindromes()
我的理由是,这个类基本上是无状态的,所以在不需要状态时强加状态似乎很奇怪。这有点主观,但值得注意的是(如果您曾经使用过
math
或random
模块,这是同样的想法)。构造函数中缺少参数更加奇怪;类的客户端必须神奇地以某种方式"知道"
words_list
是他们需要赋值才能填充类状态的内部变量名称。此变量名称应该是客户端不知道的实现详细信息。如果在初始化函数中提供参数失败,则此字段应该有一个 setter(或者只是完全跳过内部状态)。ends_with_s(self, s)
是一个愚蠢的功能;设计师似乎在想要写ends_with(self, letter)
和ends_with_s(self)
之间混淆了(前者更可取)。如果你想要一封新信怎么办?您是否需要为每个可能的结束字符ends_with_a
、ends_with_b
、ends_with_c
等编写数十个函数?我意识到这只是一个人为的作业,但班级仍然表现出糟糕的设计。拼写错误:
words_with_lenght
->words_with_length
.
以下是有关如何构建定位这些问题的技能的一般提示:在非常小的块中工作并经常运行程序。看起来这四个函数是一次性编写的,没有在整个过程中测试每个函数以确保它首先工作。这是显而易见的,因为所有四个函数都重复了相同的错误。
s.endswith('s')
将您的输入字符串s
("s")与"s"
进行比较。"s"以"s"结尾,因此它始终返回您的第一个条目。将其更改为if self.words_list[i].startswith('s'):
(与endswith
相同)。
我建议更改您的 for 循环以迭代单词本身:
def ends_with_s(self, s):
for word in self.words_list:
if word.endswith('s'):
return word
输入您描述的值列表:
amount = int(input("How many words? "))
words = [input("Word {}".format(i + 1)) for i in range(amount)]