2012-03-19 2 views
3

文字列を関数にマップするハッシュテーブルがあるとします。私の例では、それをCOMMANDSと呼んでいます。私はそれを文字列にマップする(のがcmd_addそれを呼びましょう)後、ハッシュテーブル、いくつかの機能の定義を置き、その後、私はそれを起動しようとすると、私はエラーを取得する:関数のシンボルがPythonでバインドされるのはいつですか?前方宣言は可能ですか?

COMMANDS = {'add': cmd_add} 

def cmd_add(): 
    print 'ADD' 

COMMANDS['add']() 

# NameError: name 'cmd_add' is not defined 

は今すぐことがわかり私は単にCOMMANDSの定義の前に関数定義を移動した場合、それだけで罰金うまくいく:

def cmd_add(): 
    print 'ADD' 

COMMANDS = {'add': cmd_add} 

COMMANDS['add']() 

# NO ERROR! 

なぜこれが本当ですか?私が理解していないPythonバインドについて何かありますか?

答えて

2

に登録するデコレータとcmd_addはcmd_addがあなたのソース内の関数への参照であるディを参照するから、それを止めるものは何も存在しないにもかかわらず、Pythonは動的言語であることを忘れないでくださいさまざまな時代のオブジェクトを対象とする。

しかし、JavaScriptは動的言語で通訳が関数が定義されているラインを通過して、あなたが参照を削除するか、または何か他のもの

+0

にそれを再バインドするまで、それはその関数を参照するとしてPythonバインディングを作成します - と'FunctionDeclaration'構造体と' var'構造体の前方参照を持っています。 (つまり、この答えはすべての動的言語に固有の性質ではないため、解明が必要です) –

+0

ああ、ありがとう、最初の例がPythonicの観点からは意味をなさないことが分かりました。 – apc

0

Pythonスクリプトでは、式は上から下に評価されるため、を定義してからを定義することはできません。

3

まあ、モジュールは上から下に解釈されます。あなたの最初のスニペットでは、それはまだcmd_addを見ていない、それはNameError

を投げるので、あなたはあなたの第二のスニペット、またはこのような何かのようにそれを行うことができます。

COMMANDS = {} 

def cmd_add(): 
    print 'ADD' 

def register_commands(): 
    COMMANDS.update({'add': cmd_add}) 

register_commands() 

それとも、空想やラップを得ることができますCOMMANDS

COMMANDS = {} 

# command decorator to register command functions 
class command(object): 
    def __init__(self, name): 
     self.name = name 
    def __call__(self, func): 
     COMMANDS[self.name] = func 
     return func 

@command('add') 
def cmd_add(): 
    print 'ADD' 

COMMANDS['add']() 
関連する問題