在Python中声明未知类型变量?
我在Python中遇到了一个情况(咳咳,作业),需要把给定列表中的每个元素乘以一个指定的次数,然后返回这些元素的结果。问题是,给出的示例输入类型各不相同。比如,有的输入是字符串列表,我需要对这些字符串进行乘法操作,而其他的可能是整数。所以我的返回类型需要根据输入的类型变化。我希望能做到这一点,而不需要去检查每个对象的类型。请问有没有办法做到这一点?我知道在C#中可以用“var”,但我不确定Python中是否有类似的东西。
我明白变量不需要声明,但在这种情况下,我找不到其他解决办法。以下是我写的函数:
def multiplyItemsByFour(argsList):
output = ????
for arg in argsList:
output += arg * 4
return output
你看我需要在输出变量中添加内容。如果我试着去掉第一行的输出赋值,就会出现变量未定义的错误。但是如果我给它赋值为0或者""(空字符串),就可能会抛出异常,因为你不能把3加到字符串上,或者把"a"加到整数上,等等……
这里有一些示例输入和输出:
Input: ('a','b') Output: 'aaaabbbb'
Input: (2,3,4) Output: 36
谢谢!
11 个回答
你确定这适合Python初学者吗?在我看来,最简单的做法是用reduce()和lambda这两个工具,但这两个工具对初学者来说并不常见,有时候甚至连经验丰富的Python程序员也不太推荐使用:
def multiplyItemsByFour(argsList):
if not argsList:
return None
newItems = [item * 4 for item in argsList]
return reduce(lambda x, y: x + y, newItems)
就像Alex Martelli一样,我在开头加了一个快速测试,用来处理空列表,这样会返回None。需要注意的是,如果你使用的是Python 3,你必须导入functools才能使用reduce()。
其实,reduce(lambda...)的解决方案和其他建议很相似,都是用第一个输入项来设置一个累加器,然后处理其余的输入项;不过这种写法更简洁。
def fivetimes(anylist):
return anylist * 5
如你所见,如果你有一个列表作为参数,就不需要任何赋值操作来“将其乘以给定的次数并返回结果”。你提到一个给定的列表;如果不是作为你函数的参数,那它是怎么给定给你的呢?当然,这并不太重要——即使它是一个全局变量,或者是你参数对象的一个属性,这也不需要任何赋值。
如果你被“作业”禁止使用列表的*
操作符,而只要求你自己实现,这就需要赋值,但不需要声明:
def multiply_the_hard_way(inputlist, multiplier):
outputlist = []
for i in range(multiplier):
outputlist.extend(inputlist)
return outputlist
你可以简单地让空列表“神奇地出现”:不需要“声明”它是什么,它就是一个空列表,Python编译器和你一样都知道这一点。将它绑定到名字outputlist
上也不需要你做任何特别的仪式,只需要绑定(也就是赋值)本身:名字没有类型,只有对象有类型……这就是Python!-)
编辑:原作者现在说输出不能是列表,而应该是整数、浮点数或字符串,并且没有给出具体指示。我已经请求澄清——乘以一个列表总是返回一个列表,所以显然他必须是指与他最初所说的不同的东西,即他必须乘以一个列表。与此同时,这里有另一个猜测。也许他必须返回一个列表,其中输入列表的每个项目都乘以相同的因子(无论该项目是整数、浮点数、字符串、列表……)。那么:
define multiply_each_item(somelist, multiplier):
return [item * multiplier for item in somelist]
看,妈,没有手^H^H^H^H^H赋值。(顺便说一下,这被称为“列表推导”)。
或者也许(不太可能,但我猜测的帽子可能受到铝箔帽的干扰,需要去疯帽子的商店调试一下)他需要(比如说)将每个列表项当作与第一个项相同的类型来乘,但返回它们的原始类型,比如说:
>>> mystic(['zap', 1, 23, 'goo'], 2)
['zapzap', 11, 2323, 'googoo']
>>> mystic([23, '12', 15, 2.5], 2)
[46, '24', 30, 4.0]
即使这个高度神秘的规范也可以适应……:
>>> def mystic(alist, mul):
... multyp = type(alist[0])
... return [type(x)(mul*multyp(x)) for x in alist]
...
……尽管我非常怀疑这就是作业中神秘符文实际编码的规范。几乎任何精确的规范都可以被实现,或者被证明在陈述的情况下可能是不可能的(比如要求你解决停机问题或要求P==NP;-)。这可能需要一些工作(例如“证明四色定理”;-)……但仍然比从一堆相互矛盾的观察、没有例子的情况下神奇地推测出实际规范要少得多。尽管在我们作为软件开发者的日常工作中(啊,真希望过去的日子里我们只需面对作业!-)我们当然会遇到很多这样的情况(并且必须解决它们以谋生;-)。
编辑编辑:终于看到一个精确的规范,我指出我已经实现了那个,反正,这里再来一次:
def multiplyItemsByFour(argsList):
return [item * 4 for item in argsList]
编辑编辑编辑:终于/终于看到一个更精确的规范,带有(奢侈!-)示例:
Input: ('a','b') Output: 'aaaabbbb' Input: (2,3,4) Output: 36
所以想要的是输入列表中每个项目乘以四的求和(而且你不能使用sum
,因为它对字符串无效)。我喜欢的解决方案:
def theFinalAndTrulyRealProblemAsPosed(argsList):
items = iter(argsList)
output = next(items, []) * 4
for item in items:
output += item * 4
return output
如果你被禁止使用某些构造,比如内置的items
和iter
,还有很多其他可能性(稍微差一些的)比如:
def theFinalAndTrulyRealProblemAsPosed(argsList):
if not argsList: return None
output = argsList[0] * 4
for item in argsList[1:]:
output += item * 4
return output
对于一个空的argsList
,第一个版本返回[]
,第二个版本返回None
——我不确定在这种边缘情况下你应该怎么做。
在Python中,这个过程非常简单。你需要先确定你列表中数据的类型——可以对第一个元素使用type()函数,也就是type(argsList[0])。接下来,为了初始化输出(现在你可能有一个????),你需要这个类型的“零”值或空值。就像int()、float()或str()函数会返回它们各自类型的零值一样,type(argsList[0])()也会返回你列表中数据类型的零值或空值。
所以,这里是你的函数,做了一个小小的修改:
def multiplyItemsByFour(argsList):
output = type(argsList[0])()
for arg in argsList:
output += arg * 4
return output
适用于:
argsList = [1, 2, 3, 4]
或 [1.0, 2.0, 3.0, 4.0]
或 "abcdef"
...等等。