在Python中声明未知类型变量?

时间:2009-10-04 02:10:01

标签: python types

我有Python(咳嗽,家庭作业)的情况,我需要在给定的对象列表中将EACH ELEMENT乘以指定的次数并返回元素的输出。问题是给出的样本输入是不同类型的。例如,一种情况可以输入一个字符串列表,其元素我需要相乘而其他元素可能是整数。所以我的回归类型需要改变。我想这样做而不必测试每种类型的对象是什么。有没有办法做到这一点?我知道在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 个答案:

答案 0 :(得分:6)

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! - )

编辑:OP现在说输出不能是列表,而是int,float或者字符串,并且没有给出任何指示。我已经要求澄清了 - 乘以一个列表总是返回一个列表,所以显然他必须表达与他原先说的不同的东西,他必须乘以一个列表。与此同时,这是另一种思维阅读的尝试。也许他必须返回一个列表,其中输入列表的每个ITEM乘以相同的因子(无论该项是int,float,string,list,......)。好吧:

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,说;-)。这可能需要一些工作(例如,“证明四色定理”; - )......但仍然比神奇的实际规范IS,从一系列相互矛盾的观察,没有例子等神奇地划分神奇虽然在我们作为软件开发人员的日常工作中(对于我们所有人不得不面对的好时光啊!)我们当然会遇到很多这样的情况(并且必须解决这些问题才能获得我们的日常面包; - )。

EditEdit :最后看到一个精确的规范我指出我已经实现了那个,无论如何,这里再次出现:

def multiplyItemsByFour(argsList):
  return [item * 4 for item in argsList]

EditEditEdit :终于/终于看到更精确的规格,(豪华! - )示例

Input: ('a','b') Output: 'aaaabbbb' Input: (2,3,4) Output: 36

那么,输入列表中的项目的求和(并且你不能使用sum,因为它不能用于字符串),每个乘以4 。我的首选解决方案:

def theFinalAndTrulyRealProblemAsPosed(argsList):
  items = iter(argsList)
  output = next(items, []) * 4
  for item in items:
    output += item * 4
  return output

如果您被禁止使用其中某些构造,例如内置插件itemsiter,则还有许多其他可能性(略逊一筹),例如:

def theFinalAndTrulyRealProblemAsPosed(argsList):
  if not argsList: return None
  output = argsList[0] * 4
  for item in argsList[1:]:
    output += item * 4
  return output

对于空argsList,第一个版本返回[],第二个版本返回None - 不确定无论如何你应该在该角落案例中做什么。

答案 1 :(得分:2)

我的猜测是,你的作业的目的是让你接受“打字”。基本的想法是你不要太担心类型,你只关心行为是否正常工作。一个典型的例子:

def add_two(a, b):
    return a + b

print add_two(1, 2)  # prints 3

print add_two("foo", "bar")  # prints "foobar"

print add_two([0, 1, 2], [3, 4, 5])  # prints [0, 1, 2, 3, 4, 5]

请注意,当您在Python中def函数时,不会在任何地方声明返回类型。同一个函数根据其参数返回不同的类型是完全可以的。它被认为是一种美德,甚至;考虑到在Python中我们只需要add_two()的一个定义,我们可以添加整数,添加浮点数,连接字符串以及连接列表。静态类型语言需要多个实现,除非它们有variant之类的转义,但Python是动态类型的。 (Python是强类型的,但是是动态类型的。有些人会告诉你Python是弱类型的,但事实并非如此。在JavaScript这样的弱类型语言中,表达式1 + "1"会给你2的结果;在Python这个表达式只会引发TypeError异常。)

尝试测试参数以找出它们的类型,然后根据类型做事情被认为是非常糟糕的风格。如果您需要使代码健壮,则可以始终使用try块:

def safe_add_two(a, b):
    try:
        return a + b
    except TypeError:
        return None

另见duck typing上的维基百科页面。

答案 2 :(得分:2)

您确定这适用于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 ...)解决方案与使用第一个输入项设置累加器,然后处理其余输入项的其他建议非常相似;但更简洁。

答案 3 :(得分:2)

Python很容易。您需要获取列表中的数据类型 - 在第一个项目上使用type()函数 - type(argsList [0])。然后初始化输出(你现在有????)你需要该类型的'零'或零值。因此,正如int()或float()或str()返回其类型的零或零所以将键入(argsList [0])()返回列表中任何类型的零或零值。 / p>

所以,这是你的功能,只有一个小修改:

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" ...等,

答案 4 :(得分:1)

您不需要在python中声明变量类型;变量具有分配给它的任何类型。

编辑:

要解决重新说明的问题,请尝试以下方法:

def multiplyItemsByFour(argsList):

output = argsList.pop(0) * 4

for arg in argsList:
        output += arg * 4

return output

(这可能不是最好的方式,但它至少应该以正确的类型开始输出变量,假设整个列表的类型相同)

答案 5 :(得分:1)

Python是动态类型的,您不需要声明变量的类型,因为变量没有类型,只有值。 (任何变量都可以存储任何值,值在其生命周期内永远不会更改其类型。)

def do_something(x):
    return x * 5

这适用于您传递给它的任何x,实际结果取决于x中的值的类型。如果x包含一个数字,它将只进行常规乘法,如果它包含一个字符串,该字符串将连续重复五次,对于列表,它将重复列表五次,依此类推。对于自定义类型(类),它取决于类是否具有为乘法运算符定义的操作。

答案 6 :(得分:1)

您提供了以下示例输入和输出:

输入:('a','b')输出:'aaaabbbb'输入:(2,3,4)输出:36

我不想为你的作业写出解决方案,但我确实想引导你走向正确的方向。但我仍然不确定我理解你的问题是什么,因为我理解的问题对于Python类的介绍似乎有点困难。

解决此问题的最简单方法是将参数传递到列表中。然后,您可以查看列表中的第一项,并从中开始工作。这是一个函数,要求调用者传入两个项目的列表:

def handle_list_of_len_2(lst):
   return lst[0] * 4 + lst[1] * 4

现在,我们如何才能延长两个项目?好吧,在您的示例代码中,您不确定要为变量输出分配什么。如何分配lst [0]?然后它总是具有正确的类型。然后你可以循环遍历lst中的所有其他元素,并在编写时使用+ =累积到输出变量。如果您不知道如何遍历项目列表但跳过列表中的第一项内容,Google会搜索“python list slice”。

现在,我们怎样才能让这不需要用户将所有内容打包到列表中,只需调用该函数即可?我们真正想要的是接受用户想要传递给函数的任何参数,并从中列出一个列表。也许有一种特殊的语法来声明一个函数,你告诉Python你只需要将参数捆绑到一个列表中。您可以查看good tutorial并查看其中有关如何定义函数的说明。

现在我们已经(非常普遍地)介绍了如何使用+ =积累答案,让我们考虑其他方法来积累答案。如果您知道如何使用列表推导,则可以使用其中一个基于参数列表返回新列表,并对每个参数执行乘法运算;然后你可以以某种方式将列表缩减为单个项目并返回它。 Python 2.3和更新版本有一个名为sum()的内置函数,你可能想要阅读它。 [编辑:哦,drat,sum()仅适用于数字。见最后添加的注释。]

我希望这会有所帮助。如果您仍然感到困惑,我建议您联系您的老师并要求澄清。祝你好运。

P.S。 Python 2.x有一个名为reduce()的内置函数,可以使用sum()实现reduce()。但是,Python的创建者认为最好只使用sum(),事实上他从Python 3.0中删除了reduce()(好吧,他将其移动到一个名为functools的模块中)。

P.P.S。如果你让列表理解工作,那么还有一件事需要考虑。如果使用列表推导然后将结果传递给sum(),则构建一个要使用一次然后丢弃的列表。如果我们能得到结果,它不是很整洁,但是不是构建整个列表然后丢弃它我们可以让sum()函数尽可能快地消耗列表项吗?您可能需要阅读此内容: Generator Expressions vs. List Comprehension

编辑:哦,亲爱的,我认为Python的sum()内置将使用duck typing。实际上,只记录了数字。我很失望!我将不得不搜索并查看是否有任何讨论,并了解他们为什么这样做;他们可能有充分的理由。同时,你也可以使用你的+ =解决方案。对不起。

编辑:好的,通过阅读其他答案,我现在注意到有两种方法可以剥离列表中的第一个元素。

为简单起见,因为你看起来像是Python初学者,我建议只使用output = lst[0],然后使用列表切片跳过列表中的第一项。但是,Wooble在他的回答建议使用output = lst.pop(0)这是一个非常干净的解决方案:它在列表中得到第0个东西,然后你可以循环遍历列表并自动跳过第0个事情。但是,这会“改变”这个名单!如果像这样的函数没有“副作用”,例如修改传递给它的列表,那就更好了。 (除非列表是为该函数调用而创建的特殊列表,例如*args列表。)另一种方法是使用“列表切片”技巧制作具有第一项的列表的副本除去。 Alex Martelli提供了一个如何使用名为iter()的Python特性创建“迭代器”的示例,然后使用迭代器来获取“下一个”事物。由于迭代器还没有被使用,接下来就是列表中的第0件事。这不是一个真正的初学者解决方案,但它是用Python做到这一点的最优雅方式;你可以将一个非常庞大的列表传递给该函数,而Alex Martelli的解决方案既不会改变列表,也不会通过复制列表来浪费内存。

答案 7 :(得分:0)

无需测试物体,只需相乘即可!

'this is a string' * 6
14 * 6
[1,2,3] * 6

一切正常

答案 8 :(得分:0)

试试这个:

def timesfourlist(list):
 nextstep = map(times_four, list)
 sum(nextstep)

map执行传入列表中每个元素的函数(返回一个新列表),然后求和列表中的+ =。

答案 9 :(得分:0)

如果您只是想填写代码中的空白,可以尝试设置object=arglist[0].__class__(),使其为该类的零等效值。

>>> def multiplyItemsByFour(argsList):
    output = argsList[0].__class__()
    for arg in argsList:
            output += arg * 4
    return output

>>> multiplyItemsByFour('ab')
'aaaabbbb'
>>> multiplyItemsByFour((2,3,4))
36
>>> multiplyItemsByFour((2.0,3.3))
21.199999999999999

如果列表为空,这将崩溃,但您可以在函数开头检查该情况并返回您认为合适的任何内容。

答案 10 :(得分:0)

感谢Alex Martelli,您有最好的解决方案:

def theFinalAndTrulyRealProblemAsPosed(argsList):
    items = iter(argsList)
    output = next(items, []) * 4
    for item in items:
        output += item * 4
    return output

这是美丽而优雅的。首先我们使用iter()创建一个迭代器,然后我们使用next()来获取列表中的第一个对象。然后,当我们遍历列表的其余部分时,我们会累积,然后我们就完成了。我们永远不需要知道argsList中对象的类型,实际上它们可以是不同的类型,只要所有类型都可以应用运算符+。这是鸭子打字。

昨天晚上我感到很困惑,并且认为你想要一个函数,而不是采用明确的列表,只需要一个或多个参数。

def four_x_args(*args):
    return theFinalAndTrulyRealProblemAsPosed(args)

该函数的*args参数告诉Python收集该函数的所有参数并从中生成一个元组;然后元组绑定到名称args。您可以轻松地从中列出一个列表,然后您可以使用.pop(0)方法从列表中获取第一个项目。这会花费内存和构建列表的时间,这就是iter()解决方案如此优雅的原因。

def four_x_args(*args):
    argsList = list(args)  # convert from tuple to list
    output = argsList.pop(0) * 4
    for arg in argsList:
        output += arg * 4
    return output

这只是Wooble的解决方案,改写为使用* args。

调用它的示例:

print four_x_args(1)  # prints 4
print four_x_args(1, 2)  # prints 12
print four_x_args('a')  # prints 'aaaa'
print four_x_args('ab', 'c') # prints 'ababababcccc'

最后,我会恶意并抱怨你接受的解决方案。该解决方案取决于具有合理null或零的对象的基类,但并非所有类都具有此。 int()返回0str()返回''(空字符串),因此它们可以正常工作。但是这个怎么样:

class NaturalNumber(int):
    """
    Exactly like an int, but only values >= 1 are possible.
    """
    def __new__(cls, initial_value=1):        
        try:
            n = int(initial_value)
            if n < 1:
                raise ValueError
        except ValueError:
            raise ValueError, "NaturalNumber() initial value must be an int() >= 1"
        return super(NaturalNumber, cls).__new__ (cls, n)


argList = [NaturalNumber(n) for n in xrange(1, 4)]

print theFinalAndTrulyRealProblemAsPosed(argList)  # prints correct answer: 24

print NaturalNumber()  # prints 1
print type(argList[0])()  # prints 1, same as previous line

print multiplyItemsByFour(argList)  # prints 25!

祝你学习顺利,我希望你像我一样喜欢Python。