2017-11-24 23 views
1

msgをよりクリーンな方法で作成できますか?各イベント(Ping、Pullリクエスト、Issue、Issueコメント、Repo、Create、Delete、プルrequsetレビュー、Push、Commitコメント)には、イベントをチェックし、アクションに従ってメッセージを作成するif節があります。Python if-else mess

data = request.json 
    event = request.headers['X-Github-Event'] 
    msg = "" 

    ... 

    # Pull request 
    elif event == "pull_request": 
     if data['action'] == "opened": 
      msg = PullRequest(data).opened() 
     elif data['action'] == "closed": 
      msg = PullRequest(data).closed() 
     elif data['action'] == "assigned": 
      msg = PullRequest(data).assigned() 

    # Issue 
    elif event == "issues": 
     if data['action'] == "opened": 
      msg = Issue(data).opened() 
     elif data['action'] == "reopened": 
      msg = Issue(data).reopened() 
     elif data['action'] == "closed": 
      msg = Issue(data).closed() 
     elif data['action'] == "labeled": 
      msg = Issue(data).labeled() 
     elif data['action'] == "assigned": 
      msg = Issue(data).assigned() 
    ... 
+1

'のgetattr(課題(データ)、データ[「行動」]) () 'と' PullRequest'と同様です。未知のアクションに対して 'else'節がある場合は、それをtry-exceptブロックで囲みます。 – Evert

答えて

2

lambda:Noneの背後にある考え方は、それがdata['action']かの呼び出し可能なデフォルトの略ということである要約

elif event == "pull_request": 
    getattr(PullRequest(data), data['action'], lambda:None)() 
elif event == "issues": 
    getattr(Issue(data), data['action'], lambda:None)() 

getattr(PullRequest(data), data['action'], lambda:None)() 

は、実際にPullRequest(data)またはIssue(data)の方法ではありません。


それともif-else文が気に入らない場合は、

callables = { 
    "pull_request":PullRequest, 
    "issues":Issue, 
} 

getattr(callables[event](data), data['action'], lambda:None)() 
+0

ラッパーは必要ありません。例えば ​​'lambda:PullRequest(d)'は 'PullRequest'と同じです。 – chepner

+0

@chepner。私はそれをラップしていません。必要がない場合は、PullRequestをインスタンス化する必要はありません。私のポイントが見えますか? – Kanak

+1

ファンクションと型はファーストクラスのオブジェクトです。それを単に参照するだけでは呼び出されません。 – chepner

2

のようなものは、適切なオブジェクトに文字列をマップdict sの条件文を交換してください。 (これは、あなたのメソッドの名前と一致する必要はありません調べる気に文字列で、カナックが提案しているものの一般化である。)

functions = { 
    "pull_requests": { 
     "opened" : methodcaller("opened"), 
     "closed" : methodcaller("closed"), 
     "assigned" : methodcaller("assigned") 
    }, 
    "issues": { 
     "opened" : methodcaller("opened"), 
     "reopened" : methodcaller("reopened"), 
     "closed" : methodcaller("closed"), 
     "assigned" : methodcaller("assigned"), 
     "labeled": methodcaller("labeled") 
    } 
} 

classes = { 
    "pull_requests": PullRequest, 
    "issues": Issue 
} 

obj = classes[event] 
msg = functions[event][data['action']](obj) 
+0

文字列引数を持つ 'methodcaller'を使うのではなく、' function'ディクショナリにバインドされていないメソッドへの参照を入れることができます。例えば。 'functions = {" pull_requests ":{"開いた ":PullRequest.opened、...}、...}'。 – Blckknght

+0

@Blckknghtこれは、クラスを参照する場所の数が増え、別のクラスを使用することを決めるときに変更を加える必要があります。 'methodcaller'をより直接的に使用することは、特定のクラスのメソッドを呼び出すのではなく、特定のインスタンスに対してメソッドを呼び出すことを直接反映しています。 – chepner