7

How can I limit python function parameter to accept only arrays of some fixed-size?

I tried this but it doesn't compile:

def func(a : array[2]):

with

TypeError: 'module' object is not subscriptable

I'm new to this language.

7
  • 10
    Type Hints are expected to be shipped with Python 3.5, which is not ready yet. Commented Apr 19, 2015 at 17:10
  • My recommendation would be more closely related to what specifically you're trying to accomplish. Why only lists? Wouldn't other sequences be acceptable? And why exactly two elements? What do they represent? Why do you want them in a list as opposed to being passed as two separate arguments? Commented Apr 19, 2015 at 21:37
  • @myaut Will those type hints check at compile time or run-time? Also will it be supported directly by Python or external software will be required? Because as I see it - it's kinda too abstract and optional. Commented Apr 21, 2015 at 16:40
  • If you speak about CPython ("default" Python interpreter, but there are PyPy, Jython, and more), there is no such thing as compile time (code compiled as it called from other places because Python is dynamic), and that PEP will be implemented in CPython. And yes, using type hinting will be optional (actually just a sugar for Totem answer). Commented Apr 21, 2015 at 18:47
  • I see. So we won't be able for example to override functions by parameter type? Commented Apr 21, 2015 at 18:51

3 Answers 3

10

What about checking the length inside of the function? Here I just raised an error, but you could do anything.

def func(array):
    if len(array) != 2:
        raise ValueError("array with length 2 was expected")
    # code here runs if len(array) == 2
Sign up to request clarification or add additional context in comments.

Comments

6

1st way (you'll most probably want to use this)

You can just check for all the criteria inside your function by using if statements:

def func(a):
    if not isinstance(a, collections.abc.Sequence):
        raise TypeError("The variable has a wrong type")
    elif len(a) != 2:
        raise ValueError("Wrong length given for list")
    # rest of the code goes here

2nd way (only for debugging)

You can use assert as a workaround solution (meant for debugging):

def func(a):
    assert isinstance(a, collections.abc.Sequence) and len(a) == 2, "Wrong input given."
    # rest of the code goes here

So this will check if both criteria are met, otherwise an assertion error will be raised with the message Wrong Input Type.

2 Comments

No, don't use assert for things that may happen in production (i.e. outside of test cases): it will only raise an exception if __debug__ is falsey. See the documentation.
You shouldn't check for list; check for collections.abc.Sequence. Type checking, if you ever do it, should also use isinstance, rather than type. So you want something like if not isinstance(a, collections.abc.Sequence):
1

If you don't mind unpacking your arg list then you could do this to limit the second arg to a fixed size collection of two elements.

> def f(a,(b1,b2), c):
    b=[b1,b2]
    print(a)
    print(b)
    print(c)

Examples :

# ok to call with 2 elem array
> b=[1,2]
> f("A",l,"C")
A
[1, 2]
C

# but falls if call with other size array
> b=[1,2,3]
> f("A",b,"C")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in f
ValueError: too many values to unpack


# btw also ok if call with 2 elem tuple    
> f("A",(1,2),"B")
A
[1, 2]
C

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.