【问题标题】:Can you create traditional fixed length and type arrays in Python?你能在 Python 中创建传统的固定长度和类型数组吗?
【发布时间】:2012-10-12 04:57:05
【问题描述】:

我正在剑桥考试委员会教授 A 级课程。实用论文中的一个典型问题是:

在您选择的编程语言中,声明一个由十个整数组成的数组,然后对其进行初始化。

我有这个:

myArray = []        #create the array

for i in range(10): # initializes to 0
    myArray.append(0)

我相信这是大多数人在 Python 中会做的事情?然而,与 Pascal 等不同,它并没有严格回答这个问题,因为 Python 中的列表本质上是动态数组,增加了不限制每个元素的数据类型的问题。我可以像在 Pascal 中那样声明一个特定大小的数组和类型,而不是一个空的动态列表,没有任何类型的循环并限制数组的类型吗?

类似(伪代码):

myArray[10] : integer

这不是一个商业问题,而是一个教育问题。

【问题讨论】:

标签: python


【解决方案1】:

这是一种更 Pythonic 的初始化列表的方式:

>>> l = [0] * 10
>>> l
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> l[1] = 1
>>> l
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

当然,这并没有回答如何创建像受限元素列表这样的非 Python 事物的问题。

【讨论】:

  • 感谢您的回复。这回答了三分之二的问题,但您仍然可以不添加任何整数。有没有办法防止除整数以外的任何内容。您还可以附加另一个整数而不会出现溢出错误,所以严格来说它不是固定数组?
  • @pythonMan 是的,您可以附加另一个整数或任何其他对象。 l 是一个常规的 Python 列表,没有特殊限制。
【解决方案2】:

您可以使用array module

a = array.array('i',(0 for _ in xrange(10)))

数组要求所有元素的类型相同,如创建时指定的那样。但是,它们仍然可以附加到

如果你真的下定决心,你可以使用ctypes 模块来构建一个C 数组。但是,这可能不是很pythonic,因为它迫使你做更多低级的事情。

import ctypes
intArray10 = ctypes.c_int * 10
myArray = intArray10(*(0 for _ in xrange(10)))

【讨论】:

  • 我认为和上面的答案一样,它只解决了部分问题。这有一个我试图省略的循环。另外,如果我附加一个 none int,它会按预期失败并阻止 a.append() 语句吗?
  • @pythonMan 我发布的代码中没有循环。它包含我为此示例特别选择的生成器表达式,因此在您创建数组之前,内存中永远不会存在完整列表。如果您尝试将None 附加到此数组,您将收到错误,因为None 的类型为NoneType,因此不是int
  • @pythonMan 数组模块示例将允许您追加。如果您不想允许追加,请使用 ctypes 中的数组。
  • 您提出了一个有效的观点。 C 不是所选择的语言,所以如果你说 Python 是你所选择的语言,它会在考试问题中失败。我认为 Python 根本没有在其核心中内置固定数组,而无需导入或解决方法。
  • @pythonMan 为什么考试题会失败? ctypes 是标准库的一部分,因此这是一个有效的 python 程序。它也符合要求(这比我在这里看到的任何其他解决方案都要好)。
【解决方案3】:

您可以尝试使用array module 来指定数组的类型:

import array
a = array.array('i') # Define an integer array.

然后您可以将所需的元素添加到数组中。不过,我不确定您是否可以预定义数组应具有的大小。如果你想要一个由十个整数元素组成的数组,每个元素为零,你可以这样做:

a = array.array('i', [0]*10)

如文档中所述,'i' 强制数组的元素为整数。如果您尝试在整数数组中插入浮点数,Python 2.6 将抛出 DeprecationWarning,但会将浮点数转换为 int:

>>> a[0]=3.14159
>>> a
>>> array('i', [3, 0, 0, 0, 0, 0, 0, 0, 0, 0])

或者,您可以使用numpy package,它允许您定义数组的大小和类型。

import numpy as np
a = np.empty(10, dtype=int) # Define a integer array with ten elements

np.empty 只是在内存中为数组保留一些空间,它不会初始化它。如果你需要一个 0 的数组,你可以这样做:

a[:] = 0

或直接使用np.zeros function:

a = np.zeros(10, dtype=int)

同样,在整数数组中插入浮点数会默默地将浮点数转换为整数。

请注意 numpy 和 array 之间的区别:一旦在 numpy 中定义了一个数组,就不能在不重新创建数组的情况下更改其大小。从这个意义上说,它满足了您对“10 个且只有 10 个整数”的要求。相比之下,array.array 对象可以看作是具有固定元素类型的列表:数组是动态的,您可以增加其大小。

【讨论】:

  • 这是我想到的一个解决方案,但 numpy 不是所选语言 Python 的一部分,而是一个添加的模块,可能是用另一种语言 C 编写的。但是,我也会向候选人提供这个。
  • 抱歉,您是对的。我的最后一个问题是:'i' 变量是否实际上将数组限制为整数,如果附加了另一种类型并且数组模块是用 Python 而不是 C 编写的,则会给出错误?如果是这样,这将是完美的答案吗?哦,好吧,我要开炮了:)
  • @pythonMan 没错,numpy 是一个额外的依赖。然而,一个包已经足够普遍了(尤其是在科学领域)。对于您的第二个问题:如果您尝试将 float 添加到 int 数组,array 会抱怨,而 numpy 会默默地将您的浮点数转换为 int。
  • @pythonMan 是的,正如我在其他地方的评论中所说,数组中的 'i' 确实将其限制为 ints。
  • 快到了。不幸的是,它通过了问题的所有部分,除了一个:它不固定为 10 个整数,但仍然是一个允许溢出的动态数组,尽管它不允许任何整数!
【解决方案4】:
class myTypedArray:

    def __init__(self,mytype):
        self._internalList =    []
        self._internalType =    mytype

    def add(self,x):
       if type(x) == self._internalType:
            self._internalList.append(x)
       #else raise an Error to warn User of typedArray                                                   

    def __str__(self):
       s = ""
       for x in self._internalList:
            s+=str(x)
       return s


x = myTypedArray(int)

x.add(1)
x.add("xyz") # will not be added

print x # output: 1

如果要限制大小,可以跟踪大小并抛出异常。因此,如您所见,在 Python 中扩展类型非常容易。诸如 C 之类的静态类型语言的全部意义在于更接近硬件。这个例子 myTypedArray 效率不高,所以通常没有理由使用静态类型。

【讨论】:

  • 恐怕这是一个教育问题,而不是一个实用的问题,我一直在寻找内置 Python 命令而不是解决方法和类定义。
  • 嗯,使用内置类型是不可能实现的。该解决方案有效。您可以将 maxsize 添加到定义中,并检查每个添加是否达到 maxsize。内置类型动态的,所以你必须自己重写这些方法。如果要创建自己的类型,则必须使用类。这就是它的用途。
  • 是的,我明白了,但最初的问题不是关于创建自己的类型;它是关于使用语言的原始内置功能。纸上只有 3-4 行代码的空间。无论如何,类都不会出现在本文中。我很欣赏你所说的一切都是正确的,但问题地址内置于数组而不是类。
  • 那么答案是,不可能。 Python 内置类型本质上是动态的。
  • phantOm:我收到了来自考试委员会的答复,只要学生评论他为什么使用动态数组,我的初始解决方案就可以了。然后一位老师在讨论线程上对此发表评论说它没有回答这个问题,因为我也向 stackflow 的观众提出了建议。所以总结一下:我的方法还行,但还是引起了老师们的争议!
【解决方案5】:

正如已经提到的,l = [0] * 10 用 10 个零初始化一个列表。

虽然可以添加更多元素,但不能误操作。

>>> l = [0] * 10
>>> l[10] = 1

Traceback (most recent call last):
    l[10] = 1
IndexError: list assignment index out of range

如果您想追加到列表中,您需要调用.append() 或其他添加新元素的方法。因此,您不能随意添加元素,您需要明确了解它。

在许多其他语言中,您可以将数组替换为具有不同大小的数组。重点是,您通常可以找到绕过这些限制的方法,而且我认为最好使用最简单且有效且易于理解的方法。

对我来说,那是

>>> l = [0] * 10

【讨论】:

    【解决方案6】:

    您可以使用array 模块来做到这一点。 array 模块是 python 标准库的一部分:

    from array import array
    from itertools import repeat
    
    a = array("i", repeat(0, 10))
    # or
    a = array("i", [0]*10)
    

    repeat 函数重复 0 值 10 次。它比 [0]*10 更节省内存,因为它不分配内存,而是重复返回相同的数量 x 次。

    【讨论】:

      猜你喜欢
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多