Reputation: 121
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
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
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
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
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