How to enforce automatic parameter casting in function definitions?

10,890

Solution 1

In Python 3 you could use function annotations and then write a decorator that converts (or tries to convert) arguments to the types you specify.

In Python 2 you can't do this in the way you seem to want. Python 2's syntax doesn't support putting anything in the function definition except the arguments themselves, and you can't alter Python's syntax to let you put types in there as well.

Solution 2

First of all, you shouldn't really be doing this (even though some days I kind of want to as well…). Python is not statically-typed, so you shouldn't really be introducing cludgy static-typing.

Buuut, to answer you question. Decorators:

def ensure_int(fn):
    def wrapper(num):
        return fn(int(num))
    return wrapper

def test(num):
    return num + 2

@ensure_int
def test2(num):
    return num + 2

Works like:

> test("2") 
ERROR!!!

>test2("2")
4
Share:
10,890
bitmask
Author by

bitmask

I am a computer scientist, enthusiast programmer, and activist. Accept policy If you wonder why I didn't accept your answer, although it is obviously the right thing: Usually, I like to wait at least an hour before accepting anything, often I wait a day or so. More random information about me kernel: linux distro: debian interface: xmonad + mate text: vim web: firefox mail: thunderbird programming: mainly c++, some python, occasionally haskell, svg speak: de, en, es (read-only), limited support: fr, ru rcs: git scifi: The Matrix, Star Trek, Doctor Who, Firefly First to earn the the-matrix bronze badge on scifi.SE. Flair Bad Wolf

Updated on June 20, 2022

Comments

  • bitmask
    bitmask almost 2 years

    Consider this example of a function (and its use) that receives one parameter which is only meaningful as int:

    def fun(index):
        index = int(index)
        # do something with index
    
    def main():
        print fun(1e6)
    

    I find that I keep repeating this pattern on several functions that deal with integers since it ensures that I really receive some integer number (note that 1e6 is a floating point instance).

    This is a bit cumbersome and if forgotten once it could produce problems (there is code that reacts differently to floating-point/integer/string/... values). So could this be somehow encoded in the function signature?

    E.g. something along the lines of this pseudo-code:

    def fun(int index):
        # do something with index