在Python中如何在字符串中调用代码而不使用exec/eval

5 投票
3 回答
2852 浏览
提问于 2025-04-16 02:37

我有一段代码,当玩家尝试吃东西时会执行:

def eat(target='object'):
    global current_room
    global locations
    global inventory
    if target in inventory:
        items[target]['on_eat'] #This is showing no results.
    else:
        print 'You have no ' + target + ' to eat.'

还有这段关于物品的代码(简化过):

items = {
'strawberry': {
    'weight': 1,
    'text': 'The strawberry is red',
    'on_eat': "normal_eat('strawberry', 'pretty good, but not as sweet as you expected')"
    },
'trees': {
    'weight': 50,
    'text': 'The trees are tall with large, leaf filled branches blocking out a majority of sunlight.',
    'on_eat': "forcesay('Eating trees? What the hell is your problem?')"
    }
}

有没有什么好的方法可以调用 items[whatever]['on_eat'],而不需要使用像 exec() 或 eval() 这样奇怪的方式?如果没有,提供一个其他格式的例子也很不错。

在这之前,items[everyitems]['on_eat'] 的值不是字符串,但这段代码一运行就会立即执行每个物品的 on_eat。

我看到过很多类似问题的回答,但它们没有处理函数的参数,换句话说,它们更像是 这个

3 个回答

0

部分函数的另一种写法是这样写项目

items = {
'strawberry': {
    'weight': 1,
    'text': 'The strawberry is red',
    'on_eat': (normal_eat,('strawberry', 'pretty good, but not as sweet as you expected'))
    },
'trees': {
    'weight': 50,
    'text': 'The trees are tall with large, leaf filled branches blocking out a majority of sunlight.',
    'on_eat': (forcesay,('Eating trees? What the hell is your problem?',))
    }
}

然后这样调用它

def eat(target='object'):
    if target in inventory:
        func, args = items[target]['on_eat']
        func(*args)
    else:
        print 'You have no ' + target + ' to eat.'

如果你不打算重新给这些变量赋值,就不需要那些 global 声明

1

你可以使用代码模块

def eat(target='object'):
    import code
    console = code.InteractiveConsole(locals()) # make a python interpreter with local vars
    if target in inventory:
        console.push("items[target]['on_eat']")
    else:
        print 'You have no ' + target + ' to eat.'
6

你可以把你的函数和函数的参数存储为一个 partial

from functools import partial

items = { 
'strawberry': { 
    'weight': 1, 
    'text': 'The strawberry is red', 
    'on_eat': partial(normal_eat, 'strawberry', 'pretty good, but not as sweet as you expected') 
    }, 
'trees': { 
    'weight': 50, 
    'text': 'The trees are tall with large, leaf filled branches blocking out a majority of sunlight.', 
    'on_eat': partial(forcesay, 'Eating trees? What the hell is your problem?')
    } 

def eat(target='object'):  
    # those globals are probably not necessary
    if target in inventory:  
        items[target]['on_eat']()  #Add ()'s to call the partial
    else:  
        print 'You have no ' + target + ' to eat.'

撰写回答