Should I force Python type checking?

前端 未结 7 1958
一个人的身影
一个人的身影 2020-12-09 04:56

Perhaps as a remnant of my days with a strongly-typed language (Java), I often find myself writing functions and then forcing type checks. For example:

def o         


        
7条回答
  •  我在风中等你
    2020-12-09 05:52

    Two things.

    First, if you're willing to spend ~$200, you can get a pretty good python IDE. I use PyCharm and have been really impressed. (It's by the same people who make ReSharper for C#.) It will analyze your code as you write it, and look for places where variables are of the wrong type (among a pile of other things).

    Second:

    Before I used PyCharm, I ran in to the same problem--namely, I'd forget about the specific signatures of functions I wrote. I may have found this somewhere, but maybe I wrote it (I can't remember now). But anyway it's a decorator that you can use around your function definitions that does the type checking for you.

    Call it like this

    @require_type('paramA', str)
    @require_type('paramB', list)
    @require_type('paramC', collections.Counter)
    def my_func(paramA, paramB, paramC):
        paramB.append(paramC[paramA].most_common())
        return paramB
    

    Anyway, here's the code of the decorator.

    def require_type(my_arg, *valid_types):
        '''
            A simple decorator that performs type checking.
    
            @param my_arg: string indicating argument name
            @param valid_types: *list of valid types
        '''
        def make_wrapper(func):
            if hasattr(func, 'wrapped_args'):
                wrapped = getattr(func, 'wrapped_args')
            else:
                body = func.func_code
                wrapped = list(body.co_varnames[:body.co_argcount])
    
            try:
                idx = wrapped.index(my_arg)
            except ValueError:
                raise(NameError, my_arg)
    
            def wrapper(*args, **kwargs):
    
                def fail():
                    all_types = ', '.join(str(typ) for typ in valid_types)
                    raise(TypeError, '\'%s\' was type %s, expected to be in following list: %s' % (my_arg, all_types, type(arg)))
    
                if len(args) > idx:
                    arg = args[idx]
                    if not isinstance(arg, valid_types):
                        fail()
                else:
                    if my_arg in kwargs:
                        arg = kwargs[my_arg]
                        if not isinstance(arg, valid_types):
                            fail()
    
                return func(*args, **kwargs)
    
            wrapper.wrapped_args = wrapped
            return wrapper
        return make_wrapper
    

提交回复
热议问题