사용자 입력에서 함수를 호출하고 싶지만 인수는 괄호 안에 포함하고 싶습니다. 예를 들어, 나는 하나 개의 인수받는 함수가있는 경우 :사용자 입력을 기반으로 인수가있는 Python 함수를 호출하십시오.
def var(value):
print(value)
내가 다음 인수와 함께 함수를 호출 명령 및 인수에 대한 사용자를 부탁드립니다 :
Input Command: var("Test")
Test
사용자 입력에서 함수를 호출하고 싶지만 인수는 괄호 안에 포함하고 싶습니다. 예를 들어, 나는 하나 개의 인수받는 함수가있는 경우 :사용자 입력을 기반으로 인수가있는 Python 함수를 호출하십시오.
def var(value):
print(value)
내가 다음 인수와 함께 함수를 호출 명령 및 인수에 대한 사용자를 부탁드립니다 :
Input Command: var("Test")
Test
하게 분할을 인수에서 함수 이름. 사전 정의 된 맵을 사용하여 함수를 이름으로 찾습니다. 인수를 literal_eval
으로 구문 분석하십시오. 인수를 사용하여 함수를 호출하십시오.
available = {}
def register_func(f):
available[f.__name__] = f
@register_func
def var(value):
print(value)
from ast import literal_eval
def do_user_func(user_input):
name, args = user_input.split('(', 1)
return available[name](*literal_eval('(' + args[:-1] + ',)'))
do_user_func("var('test')") # prints "test"
이것은 무효 입력 (예 잊고 괄호 또는 잘못된 함수 이름) 실패 여전히 엄청나게 취성이다. 더 강력하게 만드는 것은 당신에게 달려 있습니다.
literal_eval
은 많은 양의 메모리로 평가되는 작은 문자열을 구성 할 수 있으므로 신뢰할 수없는 입력에서는 여전히 안전하지 않습니다. '[' * 10 + ']' * 10
, 안전하지만 시범적인 예입니다.
마지막으로 은 신뢰할 수없는 사용자 입력에 eval
을 사용하지 마십시오. There is no practical way to secure it from malicious input. 예상되는 멋진 입력을 평가하는 동안, 예를 들어 모든 파일을 삭제할 코드도 평가합니다.
'eval'을'dir()'카테고리에서 색인하려고 했으므로 원하는대로 할 수 있습니다. 이론에 의하면. – MasterHolbytla
@ MasterHolbytla 그게 무슨 뜻인지 전혀 모르겠지만, 아니, 갑자기 'eval'이 안전하지 않다고 수정하지 않았습니다. 나는 그것을 보증한다. – davidism
동의합니다. 나는 단지'eval' 승인 함수들에 대해서만 일할 것이다. – MasterHolbytla
난 당신 같은 간단한 입력 다루고있는 가정하에, 대안으로이 솔루션을 게시 할 예정입니다 :
var(arg)
또는 위치의 목록을 취할 수있는 하나의 함수 호출 인수.
eval
을 사용하면 이미 언급 한 것처럼 끔찍한 권장하지 않는 아이디어가됩니다. 제 생각에 그것은 당신이 읽었던 보안 위험이라고 생각합니다.
이 방법을 수행하는 가장 좋은 방법은 실행하려는 메서드에 문자열을 매핑하는 사전을 만드는 것입니다.
또한이 작업을 수행 할 수있는 다른 방법을 고려해 볼 수 있습니다. 인수를 사용하여 함수를 호출하는 방법을 알기 위해 공백으로 분리 된 입력이 있어야합니다. 이 같은 입력을 고려 : 그래서
"var arg1 arg2"
을 할 때 입력하는 것이 : 당신은 지금해야합니다
call = input().split()
:
['var', 'arg1', 'arg2']
이제 첫 번째 인수 기능, 그리고 모든 것을 고려할 수 있습니다 그렇지 않으면 함수에 전달할 인수를 가져옵니다. 그래서, 기능 예를 들어 :
가def var(some_arg, other_arg):
print(some_arg)
print(other_arg)
d = {"var": var}
call = input().split()
d[call[0]](*call[1:])
데모 :
이var foo bar
foo
bar
대신 평가를 사용하여, 당신은 스스로를 구문 분석 할 수 있습니다. 이렇게하면 각 함수가 사용자 입력의 인수를 구문 분석/역 직렬화하는 방법을 제어 할 수 있습니다.당신이 좀 더 오류 검사 및 역 직렬화 기능을 개선하고 기능 추가를 모듈화에 의해 얻을 수 있지만
import sys, re
def custom_print(value):
print value
def custom_add(addends):
print sum(addends)
def deserialize_print(args):
# just print it as is
custom_print(args)
def deserialize_add(args):
# remove all whitespace, split on commas, parse as floats
addends = [float(x) for x in re.sub(r"\s", "", args).split(",")]
# send to custom_add function
custom_add(addends)
def get_command():
cmd_input = raw_input("Command: ")
# -- check that the command is formatted properly
# and capture command groups
match = re.match(r"^([a-zA-Z0-9]+)(\(.*\))?$", cmd_input)
if match:
# extract matched groups to separate variables
(cmd, argstring) = match.groups()
# strip parenthesis off of argstring
if argstring:
args = argstring[1:-1]
# send the whole argument string to its corresponding function
if cmd == "print":
deserialize_print(args)
elif cmd == "add":
deserialize_add(args)
elif cmd == "exit":
sys.exit()
else:
print "Command doesn't exist."
else:
print "Invalid command."
# recurse until exit
get_command()
# -- begin fetching commands
get_command()
이것은 꽤 거친 설정입니다.
분리 된 deserialize 함수가 너무 많이 보인다면 사용자 지정 함수 자체로 deserialization을 이동할 수도 있습니다.
cmd 모듈을 조사해야합니다. 이것은 셸 명령과 유사한 입력을 구문 분석 할 수 있지만 괄호가 명세의 중요한 부분 인 경우 구분자를 변경하고 구분 기호를 변경할 수 있다고 생각합니다.
호출 및 인수를 캡처하고 호출을 파싱하려면 파서를 작성해야합니다. 신뢰할 수없는 입력에'eval'을 사용해서는 안됩니다. – davidism
@ davidism 정의한 함수에만'eval'을 사용할 수 있습니까? – MasterHolbytla
@MasterHolbytla는 항상'var (arg1, arg2, arg3)'만큼 간단한 입력이 될 것입니까? 아니면 더 복잡합니까? – idjaw