2011-08-31 5 views
2

가능한 중복 :
Calling a function from a string with the function's name in Python파이썬에서 메뉴 만들기

내가 이런 짓을 했을까 끔찍한 코드를 작성할 수 있다고 생각하지만, 나는 차라리 '클린 버전을 볼 거라고 '.

나에게 좋은 접근 방법은 주어진 객체가 사용할 수있는 다양한 기능을 보유하고있는 사전을 만드는 것입니다. 그런 다음 사용자가 무엇을하고 있는지 객체에 알리라는 지시를 받으면 해당 명령을 기반으로 메뉴가 열립니다.

나는 조금 주위를 수색했기 때문에 실제로 나에게 적용되는 것을 보지 못했고 그래서 나는 그것을 시도 할 것이라고 생각했다. 음, 작동하지 않았습니다. '갑'또는 '바'중 하나를 입력,이 경우 - 경우

class Man(object): 
    def __init__(self): 
     self.cmds = ['foo', 'bar'] 

    def foo(self): 
     print "Foo called." 

    def bar(self): 
     print "Bar called." 

    def junk(self): 
     print "Junk called." ##not in dict, on purpose, will explain 

    def menu(self): 
     while True: 
      print "List of actions:" 
      for acts in self.cmds: 
       print acts 
      cmd = raw_input("> ") 
      if cmd in self.cmds: 
       cmd() ##doesn't work. 
         ##neither did self.cmd() (got AttributeError, obviously) 

       result = getattr(self, cmd)() ## this works! thanks cdhowie 
      else: 
       pass 

Stick = Man() 
Stick.menu() 

은 내가 경우 - 다른 사람이 사실로보고 뭔가를 입력 할 때마다 프로그램이 형식 오류를 제공, 명확하지 않다. 여기에 문제가 있습니다. 여기에 너무 오래 못생긴 if-else를 작성하여이 예제가 작동하도록 할 수 있습니다. 그러나 self.cmds를 추가/제거하여 개체의 기능을 변경하고 싶습니다. 따라서 세 번째 함수 Junk(); Stick은 현재 dict-menu에서 'Junk()'에 액세스 할 수 없지만 약간의 self.cmds.append 작업 만 수행하면됩니다.

Freaking Python, 어떻게 작동합니까? 이것이 올바른 방향인지, 아니면 더 간단한 방법이 있습니까?

편집 : 내 대답은 getattr의 마법에서 발견되었습니다. 감사합니다 cdhowie. 트릭은 while 루프를 다음과 같이 변경하는 것이 었습니다. result = getattr (self, cmd)()

이제 내 다음 임무는 getattr()이 실제로하는 일을 마침내 파악하는 것입니다. ㅎ, 내가 코드를 어떻게 알지 :) 내 멍청한 놈 상태를 용서

최종 편집

: cdhowie의 예는 원래의 프로그램으로 작동하는 동안, 나는 ders에 '대답은 나를 기능적으로 일을 할 수 있다는 점을 발견하기 때문에 것을 나는 않을 것 getattr()로 할 수있었습니다. ders '솔루션을 사용하면 Man의 init에있는 다른 객체에서 함수를 쉽게 사용할 수있었습니다.'객체 합성 '이라고 생각합니까? 어쨌든 getattr()은 AttributeError 대신에 Man이 아닌 다른 곳에서 self.cmds에 추가 된 모든 함수를 사용합니다. 아니면 그냥 이상하게 다시 할 수도 있습니다. 그러나 FTW를 말하는 것으로 충분합니다.

+3

[이 질문] (http://stackoverflow.com/questions/3061/calling-a-function-from -a-string-with-the-python-functions-name)은 이름으로 메소드를 호출하려는 경우 적합합니다. – cdhowie

+0

오, 그 * 트릭을 않습니다 * 않습니다. 빨리 '쉬운 답변, 민트 주셔서 감사합니다. –

+0

문제를 해결하는 코드 업데이트로 질문을 편집 했습니까? 그렇다면이 Q를 삭제하거나 닫아야합니다. – dkamins

답변

1

예제에서 Man.cmds는 사전이 아닌 목록입니다. 따라서 self.cmds 목록의 문자열을 함수로 호출하면 TypeError가 발생합니다.

함수 이름이 함수 자체와 쌍을 이루는 딕셔너리를 만듭니다.

def __init__(self): 
     self.cmds = {'foo':self.foo, 'bar':self.bar} 

사용자가 올바른 함수 이름을 입력했는지 확인하십시오. 그렇다면 사전에서 꺼내어 호출하십시오.

  if cmd in self.cmds: 
       command = self.cmds[cmd] 
       command() 
      else: 
       pass 

동적으로 정크 기능을 추가하려면 수 다음 update CMDS :

Stick.cmds.update({'junk':Stick.junk}) 
+0

*이 * 대답은 내가 실제로 필요한 경로로 나를 데려갔습니다. 굉장해. 감사. –

+0

'Stick.cmds'에 단일 항목을 추가하기 위해'update'를 사용하지 마십시오. 단지'Stick.cmds [ 'junk'] = Stick.junk'를 사용하십시오. – agf