Array methods function in Python?
Python arrays
Declaring a python function with an array parameters and passing an array argument to the function call? - Stack Overflow
delegates - Calling functions by array index in Python - Stack Overflow
I'm following roadmap.sh/python to learn python. I'm at the DSA section.
I understand the concept of arrays in DSA, but what I don't understand is how to represent them in Python.
Some tutorials I've seen use lists to represent arrays (even though arrays are homogeneous and lists are heterogeneous).
I've seen some other tutorials use the arrays module to create arrays like array.array('i') where the array has only integers. But I have never seen anybody use this module to represent arrays.
I've also seen some tutorials use numpy arrays. Which I don't understand their difference from the normal arrays module.
What should I use to represent arrays?
So far I've solved a couple of arrays exercises using Python lists.
What you have is on the right track.
def dosomething( thelist ):
for element in thelist:
print element
dosomething( ['1','2','3'] )
alist = ['red','green','blue']
dosomething( alist )
Produces the output:
1
2
3
red
green
blue
A couple of things to note given your comment above: unlike in C-family languages, you often don't need to bother with tracking the index while iterating over a list, unless the index itself is important. If you really do need the index, though, you can use enumerate(list) to get index,element pairs, rather than doing the x in range(len(thelist)) dance.
Maybe you want to unpack elements of an array, I don't know if I got it, but below an example:
def my_func(*args):
for a in args:
print(a)
my_func(*[1,2,3,4])
my_list = ['a','b','c']
my_func(*my_list)
tl;dr: Write an out(n) function rather than out1(), out2(), ..., outN() and don't bother with this hack.
I cannot imagine a reasonable scenario where this question would come up in practice. Please reconsider the architecture of the problem; there is likely to be a much better way to do this (because storing them in a list implies there is nothing meaningful about the functions except the index; for example, I can only imagine that you'd want to do this if you were creating a bunch of dynamically-generated thunks where their temporal ordering matters, or something similar). Especially any novice users you are reading this answer, consider making a more general function that can handle everything, or associating to each function some more identifying information, or sticking it as part of a class, etc.
That said, this is how you'd do it.
myFuncs = [f0,f1,f2]
myFuncs2 #calls f2
or
myFuncs = {'alice':f1, 'bob':f2}
myFuncs'alice' #calls f1
this is just the following two steps in one step:
myFuncs = [f0,f1,f2]
f = myFuncs[i]
f(...) #calls fi
or if you don't have a registry of functions 'myFunc' like the OP said above, you can use globals(), though it is extremely hackish form and to be avoided (unless you want those functions to be available in your module namespace, in which case maybe it's fine... but this is probably rarely the case, and you'd probably rather define those functions in a submodule then from mysubmodule import * them, which is in turn slightly frowned upon):
def fN(n):
return globals()['f'+str(n)]
def f2():
print("2 was called!")
fN(2)(...) #calls f2
here are two other ideas (added after answer was accepted and first two comments):
You can also create a decorator like this:
>>> def makeRegistrar():
... registry = {}
... def registrar(func):
... registry[func.__name__] = func
... return func # normally a decorator returns a wrapped function,
... # but here we return func unmodified, after registering it
... registrar.all = registry
... return registrar
and use it like so:
>>> reg = makeRegistrar()
>>> @reg
... def f1(a):
... return a+1
...
>>> @reg
... def f2(a,b):
... return a+b
...
>>> reg.all
{'f1': <function f1 at 0x7fc24c381958>, 'f2': <function f2 at 0x7fc24c3819e0>}
then you can call reg.all['f1']. You could adapt the reg decorator to keep track of the indexing and do something like:
registry = []
index = int(re.regextofindthenumber(func.__name__))
if not index==len(registry):
raise Exception('Expected def f{} but got def f{}')
else:
registry[index] = func
Alternatively, to avoid globals(), you could define a class:
class Funcs(object):
def f1():
...
def f2():
...
def num(n):
[code goes here]
If your number of functions is small, you could get away with ['f1','f2','f3'][i].
Of course without further information, all these suggestions are just ignoring the real problem: this situation should never come up, and is a possibly a sign of a serious architecture flaw, when you'd probably rather have something (to use your example) like:
# a possibly-better world
def out(n):
# output to N, whatever that means
rather than
# what you have now
def out1():
# output to 1
def out2():
# output to 2
def outN(n):
# ???
One can access methods through a dictionary:
def one1():
print("Method one1 called")
def one2():
print("Method one2 called")
def one3():
print("Method one3 called")
methodDictionary = {1: one1, 2:one2, 3: one3}
method1 = methodDictionary[1]
method1()
method2 = methodDictionary[2]
method2()
method3 = methodDictionary[3]
method3()
When you define your function using this syntax:
def someFunc(*args):
for x in args
print x
You're telling it that you expect a variable number of arguments. If you want to pass in a List (Array from other languages) you'd do something like this:
def someFunc(myList = [], *args):
for x in myList:
print x
Then you can call it with this:
items = [1,2,3,4,5]
someFunc(items)
You need to define named arguments before variable arguments, and variable arguments before keyword arguments. You can also have this:
def someFunc(arg1, arg2, arg3, *args, **kwargs):
for x in args
print x
Which requires at least three arguments, and supports variable numbers of other arguments and keyword arguments.
You can pass lists just like other types:
l = [1,2,3]
def stuff(a):
for x in a:
print a
stuff(l)
This prints the list l. Keep in mind lists are passed as references not as a deep copy.