1

在 Python中,很容易以编程方式创建新函数。我如何将其分配给当前范围内以编程方式确定的名称?

这就是我想做的(在非工作代码中):

obj_types = ('cat', 'dog', 'donkey', 'camel')
for obj_type in obj_types:
    'create_'+obj_type = lambda id: id

在上面的例子中,赋值lambda给一个待确定的函数名显然是行不通的。在实际代码中,函数本身将由函数工厂创建。

背景是懒惰和不要重复自己:我有十几个对象类型,我会为其分配一个生成的函数。所以代码目前看起来像:

create_cat   = make_creator('cat')
# ...
create_camel = make_creator('camel')

函数create_cat等在解析器中使用硬编码。

如果我以编程方式将类创建为新类型,如文档types.new_class()中所见,这似乎是解决方案。(错误)使用这种方法是我最好的选择吗?

4

2 回答 2

3

完成您尝试做的事情(但不创建具有动态名称的函数)的一种方法是dict使用名称作为键将 lamda 存储在 a 中。而不是打电话给create_cat()create['cat']()。这将与解析器逻辑中的非硬编码名称很好地吻合。

于 2013-04-24T13:52:15.257 回答
0

Vaughn Cato 指出,可以直接分配到locals()[object_type] = factory(object_type). 但是Python 文档禁止这样做:“注意:不应修改此字典的内容;更改可能不会影响解释器使用的局部变量和自由变量的值”

D. Shawley 指出,使用dict()条目将保存函数的对象会更明智。create['cat']()在解析器中使用会很简单。虽然这很引人注目,但我不喜欢括号和刻度所需的语法开销。

JF Sebastian 指着类。这就是我最终得到的结果:

# Omitting code of these classes for clarity
class Entity:
    def __init__(file_name, line_number):
        # Store location, good for debug, messages, and general indexing

# The following classes are the real objects to be generated by a parser
# Their constructors must consume whatever data is provided by the tokens
# as well as calling super() to forward the file_name,line_number info.
class Cat(Entity): pass
class Camel(Entity): pass

class Parser:
    def parse_file(self, fn):
        # ...

        # Function factory to wrap object constructor calls
        def create_factory(obj_type):
            def creator(text, line_number, token):
                try:
                    return obj_type(*token,
                                    file_name=fn, line_number=line_number)
                except Exception as e:
                    # For debug of constructor during development
                    print(e)
            return creator

        # Helper class, serving as a 'dictionary' of obj construction functions
        class create: pass
            for obj_type in (Cat, Camel):
                setattr(create,
                        obj_type.__name__.lower(),
                        create_factory(obj_type))

        # Parsing code now can use (again simplified for clarity):
        expression = Keyword('cat').setParseAction(create.cat)

这是用于部署pyparsing 解析器的帮助代码。D. Shawley 是正确的,因为 dict 实际上更容易允许动态生成解析器语法。

于 2013-04-24T14:42:02.933 回答