What to pass when passing arguments where a list or tuple is required?

旧城冷巷雨未停 提交于 2019-12-11 00:01:38

问题


Which of the following should I use and why?

import numpy as np
a = np.zeros([2, 3])
b = np.zeros((2, 3))

There are many cases where you can pass arguments in either way, I just wonder if one is more Pythonic or if there are other reasons where one should be preferred over the other.

I looked at this question where people tried to explain the difference between a tuple and a list. That's not what I'm interested in, unless there are reasons I should care which I ignore of course!

UPDATE:

Although numpy was used as an example this pertains generally to python. A non numpy example is as follows:

a = max([1, 2, 3, 5, 4])
b = max((1, 2, 3, 5, 4))

I'm not editing the above because some answers use numpy in their explanation


回答1:


I'm answering this in the context of passing a literal iterable to a constructor or function beyond which the type does not matter. If you need to pass in a hashable argument, you need a tuple. If you'll need it mutated, pass in a list (so that you don't add tuples to tuples thereby multiplying the creation of objects.)

The answer to your question is that the better option varies situationally. Here's the tradeoffs.

Starting with list type, which is mutable, it preallocates memory for future extension:

a = np.zeros([2, 3])

Pro: It's easily readable.

Con: It wastes memory, and it's less performant.

Next, the tuple type, which is immutable. It doesn't need to preallocate memory for future extension, because it can't be extended.

b = np.zeros((2, 3))

Pro: It uses minimal memory, and it's more performant.

Con: It's a little less readable.

My preference is to pass tuple literals where memory is a consideration, for example, long-running scripts that will be used by lots of people. On the other hand, when I'm using an interactive interpreter, I prefer to pass lists because they're a bit more readable, the contrast between the square brackets and the parenthesis makes for easy visual parsing.

You should only care about performance in a function, where the code is compiled to bytecode:

>>> min(timeit.repeat('foo()', 'def foo(): return (0, 1)'))
0.080030765042010898
>>> min(timeit.repeat('foo()', 'def foo(): return [0, 1]'))
0.17389221549683498

Finally, note that the performance consideration will be dwarfed by other considerations. You use Python for speed of development, not for speed of algorithmic implementation. If you use a bad algorithm, your performance will be much worse. It's also very performant in many respects as well. I consider this only important insomuch as it may scale, if it can ameliorate heavily used processes from dying a death of a thousand cuts.




回答2:


If the number of items is known at design time (e.g coordinates, colour systems) then I would go with tuples, otherwise go with lists.

If I am writing an interface, my code will tend to just check for whether the argument is iterable or is a sequence (rather than checking for a specific type, unless the interface needs a specific type). I use the collections module to do my checks - it feels cleaner than checking for particular attributes.



来源:https://stackoverflow.com/questions/26556410/what-to-pass-when-passing-arguments-where-a-list-or-tuple-is-required

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!