我刚刚编写了一个程序,其中有一个继承自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
时,Python让我传递tuple
作为参数?
答案 0 :(得分: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
这清楚地表明,将list
作为参数传递的速度比tuple
略慢,几乎可以忽略不计,而且它们的性能几乎相等。
答案 1 :(得分:1)
你没有说任何你希望tup
成为元组的地方。您显式传入了一个列表,并且Python中的参数未经过类型检查。你可以像这样限制参数的类型:
if type(tup) is not type(()):
raise ValueError('Expected a tuple')
然而,这并非真的有必要。做这样的事情的Pythonic方法不是关心你拥有的对象的类型,而是它是否支持你想要执行的操作。
答案 2 :(得分:1)
tuple
描述了董事会本身的内容,而不是传递给初始化程序的任何参数的内容。
初始化程序的参数不一定代表对象本身;它们可能是新对象的参数之类的东西。鉴于你的函数实际上没有对输入做任何事情,你可以传递任何字面意思。
答案 3 :(得分: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而不是基类型。
答案 4 :(得分:0)
如果您只想tuple
作为__init__
的参数,则可以执行以下操作:
class Board(tuple):
def __init__(self, tup):
if not isinstance(tup, tuple):
raise Exception('Invalid type')
super().__init__()
但它真的糟糕的主意。它不是蟒蛇方式。
答案 5 :(得分:-1)
您的代码基本上是这样做的。
>>> tuple([1,2,3]) # tuple() takes a list
(1, 2, 3) # turns it into a tuple
从tuple
进行子类化并不会将class'es参数限制为tuple
;它只包含与tuple
个实例相同的方法。