Python:没有类使用“__getattr__”?

时间:2014-10-13 14:28:36

标签: python attributes

示例代码文件:

MyCode.py

def DoSomething(data):
    # data is a string
    # find a function in the same scope as this one that has the name contained
    # in "data"
    try:
        func = getattr(self,data) # this is wrong
    except AttributeError:
        print "Couldn't find function %s." % data
        return

    # execute the function
    func()

def AFunction():
    print "You found a function!"

def Add():
    print "1 + 1 = %d." % ( (1+1) )

def test():
    # unit test
    DoSomething("AFunction")

--------

test.py

import MyCode

# Try executing some functions
MyCode.DoSomething("AFunction") # should print You found a function!
MyCode.DoSomething("Add") # should print 1+1=2.
MyCode.DoSomething("IDoNotExist") # should run the exception handler

# Try executing a function from inside the module
MyCode.test() # should print You found a function!

如果我正在处理类对象,那么getattr语句最终将检索类中与所提供名称匹配的函数的引用。然后,如图所示,我可以直接从其变量名执行该函数。

但是,由于这些函数不在类中,而是在模块/文件级别,因此我们没有getattr引用,因此在自己上使用self将不起作用一个类实例。

我的问题是:是否有必要将此函数及其所有支持函数包装在一个类中并实例化该类只是为了具备此功能?或者,是否有另一种方法可以使用getattr,以便我可以访问文件级定义的函数。

注意两种用例:在文件本身内,“test”函数需要调用这些函数,但也需要从外部调用,运行任意其他函数的函数可能需要运行。

建议表示赞赏。

谢谢!

2 个答案:

答案 0 :(得分:1)

import sys
current_module = sys.modules[__name__]
getattr(current_module, 'AFunction')

使用课程包装所有内容会更安全。

答案 1 :(得分:0)

getattr适用于任何对象,而在Python中,大多数都是一个对象,包括类和模块。因此,从纯粹的技术POV中,您可以将您的函数存储在类中(可能为staticmethods)并在该类上使用getattr,或者甚至使用由freakish发布的hack直接从模块中检索它们。

但是...

但解决问题不是RightWay(tm)。

在它最简单的形式中,一个对象(类,实例,模块,等等)主要是dict,类和属性解析运算符的组合 - 这通常最终会在一个对象上进行简单的查找dict或另一个(即实例的dict,类的dict,然后是父类等)。在上面的例子中,你需要的只是一个简单的dict查找,显而易见的解决方案就是使用普通的旧dict - 记住,在Python中,一切都是一个对象,包括函数:

MyCode.py

FUNCTIONS = {}

def DoSomething(data):
    # data is a string
    # find a function in the same scope as this one that has the name contained
    # in "data"
    func = FUNCTIONS.get(data)
    if func is None:
        print "Couldn't find function %s." % data
        return

    # execute the function
    func()

def AFunction():
    print "You found a function!"

FUNCTIONS["AFunction"] = AFunction

def Add():
    print "1 + 1 = %d." % ( (1+1) )

FUNCTIONS["Add"] = Add

def test():
    # unit test
    DoSomething("AFunction")

现在您可能会发现FUNCTIONS["whatever"] = whatever模式有点无聊 - 但希望我们可以通过装饰器语法使其更加性感:

FUNCTIONS = {}

def register(func):
    FUNCTIONS[func.__name__] = func      
    return func

def DoSomething(data):
    # data is a string
    # find a function in the same scope as this one that has the name contained
    # in "data"
    func = FUNCTIONS.get(data)
    if func is None:
        print "Couldn't find function %s." % data
        return

    # execute the function
    func()

@register    
def AFunction():
    print "You found a function!"

@register            
def Add():
    print "1 + 1 = %d." % ( (1+1) )

作为一个额外的好处:您可以完全控制并通过DoSomething()

自动记录哪些功能可以访问