4

我只是在编写一个程序,其中有一个继承自tuple. 但是,当我将参数作为列表传递时,它仍然有效。这是我的一些代码:

class Board(tuple):    
    def __init__(self, tup):
        print(type(tup))
        super().__init__()

board = Board([[Cell(False) for i in range(10)] for j in range(10)])
print(type(board))

该程序然后输出:

<class 'list'>
<class '__main__.Board'>

我的问题如下:list当我说我会传递 a 时,为什么 Python 让我将 a 作为参数传递tuple

4

6 回答 6

5
def __init__(self, tup):

就像其他功能一样。你已经传递了一个tup参数列表。您无法限制python中参数的类型。子类tuple化只是意味着您从 继承属性tuple,而不是它只能接受元组作为参数。

编辑:如果你非常想要一种方法来确保只接受元组,出于某种原因。你可以像这样引发异常

class Board(tuple):
    def __init__(self, tup):
        if not isinstance(tup, tuple):
            raise TypeError("Constrcutor argument to Board should be a tuple")
        super().__init__()

print Board([1, 2])

输出

TypeError: Constrcutor argument to Board should be a tuple

tuple和之间的性能比较list

class Board(tuple):
    def __init__(self, tup):
        for i in tup:
            pass
myList, myTuple = range(10), tuple(xrange(10))

from timeit import timeit
print timeit("Board(myList)", "from __main__ import myList, Board", number = 1000000)
print timeit("Board(myTuple)", "from __main__ import myTuple, Board", number = 1000000)

输出

0.44806599617
0.413192987442

这清楚地表明,将 alist作为参数传递的速度非常慢tuple,几乎可以忽略不计,并且它们的性能几乎相等。

于 2013-10-28T14:28:57.123 回答
1

你没有在任何地方说你希望tup成为一个元组。您显式传入了一个列表,并且 Python 中的参数没有经过类型检查。您可以像这样限制参数的类型:

if type(tup) is not type(()):
    raise ValueError('Expected a tuple')

但是,这并不是真正必要的。Pythonic 做这样的事情的方式不是关心你拥有的对象的类型,而是关心它是否支持你想要执行的操作。

于 2013-10-28T14:27:47.753 回答
1

描述板本身的tuple内容,而不是传递给初始化程序的任何参数的内容。

初始化器的参数不一定代表对象本身;它们可能是新对象的参数之类的东西。鉴于您的函数实际上并没有对输入做任何事情,您实际上可以传递任何东西。

于 2013-10-28T14:28:17.207 回答
0

列表和元组通常作为序列互换使用。

如果您尝试将列表和元组用作哈希,则列表和元组之间的区别变得很重要:

class Board(tuple):    
    def __init__(self, tup):
        print(type(tup))
        d={}
        d[tup]='test'          # this will fail with an unhashable type, like a list
        super().__init__()

b1=Board(tuple([1,2,3]))
b2=Board([1,2,3])

印刷:

<class 'tuple'>
<class 'list'>
Traceback (most recent call last):
  File "Untitled 8.py", line 9, in <module>
    b2=Board([1,2,3])
  File "Untitled 8.py", line 5, in __init__
    d[tup]='test'
TypeError: unhashable type: 'list'

Python中通常没有类型检查。它是一种EAFP语言。

如果您想要更“正式”的区别并对类型的子类进行一些正式检查,请考虑使用collections.abc而不是基类型。

于 2013-10-28T14:30:26.893 回答
0

如果您只想tuple作为参数,__init__您可以执行以下操作:

class Board(tuple):    
    def __init__(self, tup):
        if not isinstance(tup, tuple):
            raise Exception('Invalid type')
        super().__init__()

但这真是个坏主意。这不是蟒蛇的方式。

于 2013-10-28T14:36:49.407 回答
-1

您的代码基本上就是这样做的。

>>> tuple([1,2,3])  # tuple() takes a list
(1, 2, 3)           # turns it into a tuple

子类化 fromtuple不会将类的参数限制为tuple; 它只包含与tuple实例相同的方法。

于 2013-10-28T14:28:57.070 回答