Skip to main content
deleted 1 character in body
Source Link
BeetDemGuise
  • 4.1k
  • 11
  • 29
import functools

def returns(t):
""" Calls a function, and if it returns something of the wrong type,
    throws a TypeError
"""""""
    def outer(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            output = func(*args, **kwargs)
            if not isinstance(output, t):
                message = "function {} returned an invalid type: {} is a {}"
                raise TypeError(message.format(func.__name__,
                                               output,
                                               type(output)))
            else:
                return output
        return wrapper
    return outer

class accepts:
    def __init__(self, *artypes, **kwtypes):
        """ Pass it a list consisting of types or tuples of types.
        in other words, pass it things that will be valid second
        arguments to the isinstance(arg, type) method.
        """
        self.artypes = artypes
        self.kwtypes = kwtypes

    def checkTypes(self, args, kwargs):
        """ Checks each arg and kwarg for type validity, and if
            they fail, then it throws a TypeError. Not very descriptive,
            but it's just an example.
        """
        type_zip = zip(args, self.artypes)
        for arg, type_ in type_zip:
            if not isinstance(arg, type_):
                raise ValueError()

        for key, value in kwargs.items():
            if not isinstance(value, self.kwtypes[key]):
                raise ValueError()

    def __call__(self, func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            self.checkTypes(args, kwargs)
            return func(*args, **kwargs)
        return wrapper

@accepts(int)
def hitimes(times=1):
    return "hello " * times


@accepts(int, word=str)
def byetimes(times, word="bye"):
    return " ".join([word] * times)

print(hitimes(2)) # works
print(byetimes(5)) # works
print(byetimes(3, word="adios")) # works as expected
print(byetimes(3, word=[])) # fails as expected
import functools

def returns(t):
""" Calls a function, and if it returns something of the wrong type,
    throws a TypeError
""""
    def outer(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            output = func(*args, **kwargs)
            if not isinstance(output, t):
                message = "function {} returned an invalid type: {} is a {}"
                raise TypeError(message.format(func.__name__,
                                               output,
                                               type(output)))
            else:
                return output
        return wrapper
    return outer

class accepts:
    def __init__(self, *artypes, **kwtypes):
        """ Pass it a list consisting of types or tuples of types.
        in other words, pass it things that will be valid second
        arguments to the isinstance(arg, type) method.
        """
        self.artypes = artypes
        self.kwtypes = kwtypes

    def checkTypes(self, args, kwargs):
        """ Checks each arg and kwarg for type validity, and if
            they fail, then it throws a TypeError. Not very descriptive,
            but it's just an example.
        """
        type_zip = zip(args, self.artypes)
        for arg, type_ in type_zip:
            if not isinstance(arg, type_):
                raise ValueError()

        for key, value in kwargs.items():
            if not isinstance(value, self.kwtypes[key]):
                raise ValueError()

    def __call__(self, func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            self.checkTypes(args, kwargs)
            return func(*args, **kwargs)
        return wrapper

@accepts(int)
def hitimes(times=1):
    return "hello " * times


@accepts(int, word=str)
def byetimes(times, word="bye"):
    return " ".join([word] * times)

print(hitimes(2)) # works
print(byetimes(5)) # works
print(byetimes(3, word="adios")) # works as expected
print(byetimes(3, word=[])) # fails as expected
import functools

def returns(t):
""" Calls a function, and if it returns something of the wrong type,
    throws a TypeError
"""
    def outer(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            output = func(*args, **kwargs)
            if not isinstance(output, t):
                message = "function {} returned an invalid type: {} is a {}"
                raise TypeError(message.format(func.__name__,
                                               output,
                                               type(output)))
            else:
                return output
        return wrapper
    return outer

class accepts:
    def __init__(self, *artypes, **kwtypes):
        """ Pass it a list consisting of types or tuples of types.
        in other words, pass it things that will be valid second
        arguments to the isinstance(arg, type) method.
        """
        self.artypes = artypes
        self.kwtypes = kwtypes

    def checkTypes(self, args, kwargs):
        """ Checks each arg and kwarg for type validity, and if
            they fail, then it throws a TypeError. Not very descriptive,
            but it's just an example.
        """
        type_zip = zip(args, self.artypes)
        for arg, type_ in type_zip:
            if not isinstance(arg, type_):
                raise ValueError()

        for key, value in kwargs.items():
            if not isinstance(value, self.kwtypes[key]):
                raise ValueError()

    def __call__(self, func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            self.checkTypes(args, kwargs)
            return func(*args, **kwargs)
        return wrapper

@accepts(int)
def hitimes(times=1):
    return "hello " * times


@accepts(int, word=str)
def byetimes(times, word="bye"):
    return " ".join([word] * times)

print(hitimes(2)) # works
print(byetimes(5)) # works
print(byetimes(3, word="adios")) # works as expected
print(byetimes(3, word=[])) # fails as expected
deleted 8 characters in body; edited tags; edited title
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

How todo I clean up pythonthese Python decorators?

I wrote some type checking decorators for pythonPython. One checks the type that a funcitonfunction returns, the other checks the type that a function accepts.

Okay so forFor returns, I used nested functions, and for accepts I used the class style of decorator. But both of them get pretty unwieldy with respect to indentation levels. What can I do to make these cleaner?

How to clean up python decorators

I wrote some type checking decorators for python. One checks the type that a funciton returns, the other checks the type that a function accepts.

Okay so for returns, I used nested functions, and for accepts I used the class style of decorator. But both of them get pretty unwieldy with respect to indentation levels. What can I do to make these cleaner?

How do I clean up these Python decorators?

I wrote some type checking decorators for Python. One checks the type that a function returns, the other checks the type that a function accepts.

For returns, I used nested functions, and for accepts I used the class style of decorator. But both of them get pretty unwieldy with respect to indentation levels. What can I do to make these cleaner?

Source Link

How to clean up python decorators

I wrote some type checking decorators for python. One checks the type that a funciton returns, the other checks the type that a function accepts.

import functools

def returns(t):
""" Calls a function, and if it returns something of the wrong type,
    throws a TypeError
""""
    def outer(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            output = func(*args, **kwargs)
            if not isinstance(output, t):
                message = "function {} returned an invalid type: {} is a {}"
                raise TypeError(message.format(func.__name__,
                                               output,
                                               type(output)))
            else:
                return output
        return wrapper
    return outer

class accepts:
    def __init__(self, *artypes, **kwtypes):
        """ Pass it a list consisting of types or tuples of types.
        in other words, pass it things that will be valid second
        arguments to the isinstance(arg, type) method.
        """
        self.artypes = artypes
        self.kwtypes = kwtypes

    def checkTypes(self, args, kwargs):
        """ Checks each arg and kwarg for type validity, and if
            they fail, then it throws a TypeError. Not very descriptive,
            but it's just an example.
        """
        type_zip = zip(args, self.artypes)
        for arg, type_ in type_zip:
            if not isinstance(arg, type_):
                raise ValueError()

        for key, value in kwargs.items():
            if not isinstance(value, self.kwtypes[key]):
                raise ValueError()

    def __call__(self, func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            self.checkTypes(args, kwargs)
            return func(*args, **kwargs)
        return wrapper

@accepts(int)
def hitimes(times=1):
    return "hello " * times


@accepts(int, word=str)
def byetimes(times, word="bye"):
    return " ".join([word] * times)

print(hitimes(2)) # works
print(byetimes(5)) # works
print(byetimes(3, word="adios")) # works as expected
print(byetimes(3, word=[])) # fails as expected

Okay so for returns, I used nested functions, and for accepts I used the class style of decorator. But both of them get pretty unwieldy with respect to indentation levels. What can I do to make these cleaner?

Note that the wrappers are themselves pretty pointless.