【问题标题】:Get a python function attribute without running the function在不运行函数的情况下获取python函数属性
【发布时间】:2016-05-16 20:06:37
【问题描述】:

我有一个 GUI,它允许用户从特定的 *.py 文件运行任何功能。我希望某些功能以彼此不同的方式运行。为了做到这一点,我试图将属性附加到函数(简单的事情,比如它需要哪些输入)。但是,我发现获取这些属性的唯一方法是先运行代码。

有没有一种方法可以在不运行代码的情况下获取这些属性,或者可能是一种更 Python 的方式来处理这个任务?

我的代码的非常基本的示例:

文件A.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

文件B.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')

【问题讨论】:

标签: python


【解决方案1】:

不要在函数体内分配属性:

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

当您使用它时,您可能希望使用实际的floatstr 类型,而不是字符串"Float""String"。如果您使用的是 Python 3,您可能还想使用函数注释:

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

【讨论】:

  • 是的,做到了。谢谢!
【解决方案2】:

您还可以通过使用装饰器使代码看起来更简洁,并使信息更接近人们在阅读您的代码时更有可能看到的函数定义。

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):
    ...

【讨论】:

  • 哦,我刚刚注意到你的回答......我正在处理我的代码并且没有刷新屏幕
  • 这很好用,只要我将 def input_stype(type) 函数移动到另一个 py 文件。我正在提取给定文件中的所有函数,这会为其添加另一个函数。谢谢回答
【解决方案3】:

你可以在函数定义之后设置属性:

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

Beta.input_stype = "Float"

【讨论】:

    【解决方案4】:

    我想提出的另一个想法:

    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
    

    这样使用:

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

    这会在运行时创建 arg 类型的验证,并在函数上设置 input_type 以进行自省。

    测试:

    foo(1) -> TypeError
    bar(1) -> TypeError
    foo(1.0) -> Ok
    bar('aaa') -> Ok
    
    foo.input_type -> float
    bar.input_type -> str
    

    【讨论】:

    • 较新版本的 python (>=3.4) 使用 functools.singledispatch 内置了类似的功能。不过,您仍然需要像您这样的包装器才能在单个装饰器中完成所有操作。它还有一个额外的限制,你只能有一个参数,这似乎是一个奇怪的限制。坦率地说,我对这个功能完全融入 python 感到有点惊讶。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2012-09-23
    • 1970-01-01
    • 2022-07-21
    相关资源
    最近更新 更多