问题描述
我正在做的练习是由一本书给出的,该书接受字典参数,并要求我给出True或False的返回值。我是Python 3的新手,作为学习的个人练习,我想将“作为棋盘的有效词典”的所有条件转换为单个返回值。我尚未实际测试此代码的错误,因为它尚未完成,但我确实通过我发现的https://extendsclass.com/python-tester.html在线验证器运行了它。
我想知道如何将下面的2个代码块转换为简单的表达式,以在下面的函数中的return语句中使用。您可以在下面看到,我已经将大多数表达式转换为带有“和”的返回值”,因为“所有表达式必须== True”
for pieces in dictionary.values():
if all(pieces.startswith('b')) or \
all(pieces.startswith('w')):
return True
else:
return False
上面的代码块循环通过传递给“件”的字典键, 并分别比较每个键,以确定它是否以'b'或'w'开头。因此,如果任何键都不以“ b”或“ w”开头,则词典“ chessboard”为假,因为它包含不正确的部分。好的,我想我会发现一个错误,我将对其进行调查并尝试解决。好的,我注意到以上代码中的一些错误需要解决,我目前正在研究如何正确执行以上代码。
for square in dictionary:
try:
if int(square[:0]) <= 8 and \
square[-1] <= 'h':
return True
else:
return False
except ValueError:
return False
我在上面的代码块上工作了很长时间,但仍然不确定这是我想要执行的“最佳”实现。但是我还是个新人,尽我所能。 无论如何,它都会对字典键进行切片,并比较键中的第一个字符,以确保它不超过8,这是最大的“有效范围”;如果超出有效范围,它将返回false,而任何非int值显然会自动为False并返回通过“例外”。
然后,它对字典键进行切片以获取字典键的最后一个字符,并将其与
这里是当前函数,最后是测试字典:
def cBV(dic): # (c)hess(B)oard(V)alidator
Err = 'Error: Invalid Board -'
if not isinstance(dic,type({})):
raise TypeError('Object passed to cBV is not of type <class dict>')
chess_pieces = {'bk pieces': 0,'wh pieces': 0,'bk pawns': 0,'wh pawns': 0}
# converts dictionary values into keys and assigns those keys "counn of values"
for squares,pieces in dic.items:
if pieces.startswith('b'): # alt if pieces[:0] == 'b':
if pieces.startswith('bpawn'): # alt if pieces == 'bpawn':
chess_pieces['bk pawns'] += 1
chess_pieces['bk pieces'] += 1
elif pieces.startswith('w'):
if pieces.startswith('wpawn'):
chess_pieces['wh pawns'] += 1
chess_pieces['wh pieces'] += 1
return 'wking' in dic.values() and \
'bking' in dic.values() and \
chess_pieces['bk pieces'] <= 16 and \
chess_pieces['wh pieces'] <= 16 and \
chess_pieces['bk pawns'] <= 8 and \
chess_pieces['wh pawns'] <= 8 and \
dict = {'8h': 'wking','2c': 'bking','3a': 'wpawn','3b': 'wpawn','3c': 'wpawn','3d': 'wpawn','3e': 'wpawn','3f': 'wpawn','3g': 'wpawn','3h': 'wpawn','4b': 'wpawn'}
test = cBV(dict)
print('Is this a valid chessboard? ' + str(test))
解决方法
您现在拥有的东西很好,您应该感到自豪-有更多新颖的技巧可以使事情变得更简洁,随着您对各种数据结构的工作方式的了解,您会逐渐习惯这些。 / p>
for pieces in dictionary.values()
if pieces.startswith('b') or \
pieces.startswith('w'):
return True
else:
return False
可以转换为单线
return all(
piece.startswith('b') or piece.startswith('w')
for piece in dictionary.values()
)
这有几件事。
-
all()
函数采用任何可迭代对象,如果该可迭代对象中的所有值均为真,则返回True
。如果甚至没有一个,它就会“短路”并返回False
。 - 作为对
all()
的论点,我们给出了“理解”。理解本质上是形式为for
的单行f(element) for element in iterable
循环:对于迭代中的每个f(element)
,它执行的是element
。- 在我们的例子中,迭代器为
dictionary.values()
,它返回dictionary
(此处为{{1)中的所有值(但不包括键)。 }}。在这种情况下,这些是字符串。 -
'wking','wpawn',...
是我们为理解的每个“迭代”分配的每个元素。它会先运行piece
,然后再运行piece = 'wking'
,等等。 -
piece = 'wpawn'
是我们为每个piece.startswith('b') or piece.startswith('w')
执行的功能。根据是否满足条件,这将输出piece
或True
。 - 您可以将理解内容括在方括号
False
中,以将其输出为常规列表。但是,如果您对诸如[]
之类的函数提供一个理解,这就是我们在这里所做的,那么它将最终成为“生成器”,这是一个效率更高的对象,仅计算一个对象一次。就我们的目的而言,这并不重要。 - 这种理解总体上产生了一个包含
all()
将会消耗的True
或False
的系列。
- 在我们的例子中,迭代器为
与您的第二个代码段相似。您已经掌握了基础知识,但可以更加简洁。您的代码:
all()
可以变成
def allSquaresAreInRange(dictionary):
for square in dictionary:
try:
if int(square[:0]) <= 8 and \
pieces[-1] <= 'h':
return True
else:
return False
except ValueError:
return False
在这里,我们利用一些东西:
- 像以前一样,我们使用
def allSquaresAreInRange(dictionary): try: return all( (1 <= int(row) <= 8) and ('a' <= col <= 'h') for (row,col) in dictionary ) except ValueError: return False
,并且像以前一样,我们使用理解。但是这次,我们直接遍历all()
- 通过
dictionary
进行迭代的功能与通过dict
进行迭代的功能相同。因此,我们正在迭代键dict.keys()
- 通过
- 每个键都是两个字符的字符串。字符串是可迭代的,就像列表一样,并且大多数可迭代的对象都有一个有趣的属性,称为“多重分配”:如果我们分配的变量与可迭代对象具有的元素数量一样多,那么这些元素就会被拆分。
-
例如,
-
'8h','2c',...
在功能上与(row,col) = '8h'
和row = '8h'[0]
相同。在这两种情况下,我们只剩下col = '8h'[1]
和row = '8'
。 - 如果两边的元素数量不匹配-例如,如果键只有一个字符或只有三个字符,则会生成
col = 'h'
。这样做的副产品是,如果没有发生此错误,则保证ValueError
和row
完全是一个字符长的字符串。
-
- 我们的条件使用大于/小于符号检查
col
是否在1到8之间,以及row
是否在A和H之间。这将再次返回col
或True
。- 您似乎已经发现,在不代表整数的对象上使用
False
也会 抛出int()
。
- 您似乎已经发现,在不代表整数的对象上使用
- 此新代码段保留了您提出的
ValueError
/try
块,因为它们工作得很好。
Python周围有一些文化,以“高效编写”代码为荣。就是说,看起来尽可能花哨的代码并遵循函数式编程范例。理解力以及except
和all()
都是其中的重要部分,因此,对于他们为的任何问题,它们可能都是“正确”的解决方案(如果可以写得简洁一点)。
类似地,片段
any()
几乎总是可以凝结为
if condition:
return True
else:
return False
(或return condition
,在return bool(condition)
处理具有真实性但不是布尔值的值的情况下,例如condition
或空列表或字符串)。如果可以的话,这是个好习惯(但同样,并不总是适用)。
不过,最重要的是,您的代码可以按您希望的方式工作,并且很清楚,您可以在几个月后重新使用它并找出什么您正在做,而为什么您正在那样做。在某些情况下,可以被编写为理解,但是这使它们变得极其复杂且难以理解-在这些情况下,最好不要将它们编写为理解,并且做得更冗长道路。在继续开发时,请记住这一点,您会做得很好。