Helos35
Helos35

Reputation: 121

Get a python function attribute without running the function

I have a GUI which allows the user to run any function from a specific *.py file. I'd like some of the functions to run in a different manner than each other. In order to do that, I was trying to attach attributes to the function (Simple things like which inputs it needs). However, I found the only way to get those attributes was to run the code first.

Is there a way to get these attributes without running the code, or perhaps a more pythonic way to approach this task in general?

Very rudimentary example of my code:

FileA.py

def Beta(x):     
    Beta.input_stype = "Float"
    y = x + 0.5

    return y

def Gamma(x):  
    Gamma.input_stype = "String"
    y = x + "_blah_blah_blah"

    return y

def Delta(x): 
    Delta.input_stype = "String"
    y = x.index('WhereIsIt')

    return y

FileB.py

import FileA
import inspect

z = inspect.getmembers(Fiddle2, inspect.isfunction)

#### User selects the code value here ####

x = user_selection

executable = z[x][1] # Pulls the executable code

if executable.input_stype == "Float" :
    y = executable(45)
elif executable.input_stype == "String" :
    y = executable('Testing_the_WhereIsIt_stuff')

Upvotes: 2

Views: 259

Answers (4)

Brendan Abel
Brendan Abel

Reputation: 37539

You may also be able to make the code look a little cleaner, and keep the information closer to the function definition where people are more likely to look when reading your code, by using a decorator.

def input_stype(typ):
    def deco(f):
        f.input_stype = typ
        return f
    return deco

@input_stype('Float')
def Beta(x):
    ...

@input_stype('String')
def Gamma(x):
    ...

Upvotes: 4

DevLounge
DevLounge

Reputation: 8437

Another idea I wanted to suggest:

def validate_input_type(typ):
    from functools import wraps
    def decorator(f):
        f.input_type = typ
        @wraps(f)
        def wrapper(arg):
            try:
                assert isinstance(arg, typ)
            except AssertionError:
                raise TypeError('{} is not of type {}'.format(arg, typ))
            return f(arg)
        return wrapper   
    return decorator

To be used like this:

@validate_input_type(float)
def foo(x):
    pass

@validate_input_type(str)
def bar(x):
    pass

This creates validation of the type of the arg at runtime AND sets input_type on the function for introspection.

Tests:

foo(1) -> TypeError
bar(1) -> TypeError
foo(1.0) -> Ok
bar('aaa') -> Ok

foo.input_type -> float
bar.input_type -> str

Upvotes: 1

user2357112
user2357112

Reputation: 281012

Don't assign the attributes inside the function body:

def Beta(x):
    y = x + 0.5
    return y
Beta.input_stype = "Float"

While you're at it, you may want to use the actual float or str types instead of the strings "Float" and "String". If you're on Python 3, you may also want to use function annotations:

def Beta(x: float):
    y = x + 0.5
    return y

Upvotes: 5

Mike Müller
Mike Müller

Reputation: 85482

You can set the attribute right after the function definition:

def Beta(x):     
    y = x + 0.5
    return y

Beta.input_stype = "Float"

Upvotes: 3

Related Questions