파이썬에서 중첩 if 문을 작성하는 더 좋은 방법이 있습니까? [닫은]


34

이것보다 다른 문장을 중첩 할 수있는 더 파이썬적인 방법이 있습니까?

def convert_what(numeral_sys_1, numeral_sys_2):

    if numeral_sys_1 == numeral_sys_2:      
        return 0
    elif numeral_sys_1 == "Hexadecimal":
        if numeral_sys_2 == "Decimal":
            return 1
        elif numeral_sys_2 == "Binary":
            return 2
    elif numeral_sys_1 == "Decimal":
        if numeral_sys_2 == "Hexadecimal":
            return 4
        elif numeral_sys_2 == "Binary":
            return 6
    elif numeral_sys_1 == "Binary":
        if numeral_sys_2 == "Hexadecimal":
            return 5
        elif numeral_sys_2 == "Decimal":
            return 3
    else:
        return 0

이 스크립트는 간단한 변환기의 일부입니다.


다른 데이터 구조를 사용하지 않으면 중첩 된 if-else 문을 and최상위 if-else 문 조건 으로 이동할 수 있습니다. 적어도 그런 식으로 읽을 수 있어야합니다. 안타깝게도 파이썬에는 switch 문이 없습니다.
adamkgray

이것은 이다 파이썬 방법입니다. 파이썬은 의도적으로 switch 문을 지원하지 않습니다. 참조 python.org/dev/peps/pep-3103
Jongmin 백

1
전혀 문제가되지는 않지만, 파이썬적인 것들을 만들려고한다면, 상수 값이나 반환 값에 대한 열거 형을 정의하는 방법은 어떻습니까? "매직 숫자"보다 독자에게는 더 좋습니다 ....
Mats Wichmann

답변:


13

@Aryerez 및 @SencerH.의 답변은 작동 하지만 값 쌍을 나열 할 때 numeral_sys_1가능한 값마다 반복 가능한 값을 작성해야 numeral_sys_2하므로 가능한 값 수가 증가하면 데이터 구조를 유지하기가 더 어려워집니다. 대신 중첩 된 if 문 대신 중첩 된 dict를 사용할 수 있습니다.

mapping = {
    'Hexadecimal': {'Decimal': 1, 'Binary': 2},
    'Binary': {'Decimal': 3, 'Hexadecimal': 5},
    'Decimal': {'Hexadecimal': 4, 'Binary': 6}
}
def convert_what(numeral_sys_1, numeral_sys_2):
    return mapping.get(numeral_sys_1, {}).get(numeral_sys_2, 0)

또는 itertools.permutations메소드 를 사용하여 맵핑 할 값 쌍을 생성 할 수 있습니다 . 순서는 입력 순서의 순서를 따릅니다.

mapping = dict(zip(permutations(('Hexadecimal', 'Decimal', 'Binary'), r=2), (1, 2, 4, 6, 3, 5)))
def convert_what(numeral_sys_1, numeral_sys_2):
    return mapping.get((numeral_sys_1, numeral_sys_2), 0)

29

유효한 모든 조합을의 dictionary에 삽입 tuple하고 조합이 없으면 0을 반환합니다.

def convert_what(numeral_sys_1, numeral_sys_2):
    numeral_dict = {
        ("Hexadecimal", "Decimal"    ) : 1,
        ("Hexadecimal", "Binary"     ) : 2,
        ("Decimal",     "Hexadecimal") : 4, 
        ("Decimal",     "Binary"     ) : 6,
        ("Binary",      "Hexadecimal") : 5,
        ("Binary",      "Decimal"    ) : 3
    }
    return numeral_dict.get((numeral_sys_1, numeral_sys_2), 0)

루프에서 함수를 사용하려는 경우 함수 외부에서 사전을 정의하는 것이 더 좋을 수 있으므로 함수를 호출 할 때마다 다시 작성되지는 않습니다.


2
except KeyError:
RomanPerekhrest

@RomanPerekhrest이 질문에 추가했지만 함수 자체에는 원래 함수와 다른 출력을 제공하는 다른 유형의 오류 가 없습니다 .
Aryerez

1
이 괄호는 [] 안에 중복되어 있습니다. 빈 튜플을 제외하고 괄호가 아닌 튜플을 만드는 것은 쉼표이며 일부 경우에는 작업 순서입니다.
gilch,

4
명령문 대신 dict .get()메소드를 0기본값으로 사용할 수 있습니다 try.
gilch November

@gilch 괄호를 삭제했습니다. 그러나 나는 try:... except:...구조를 좋아한다 .
Aryerez

17

다른 값이 numeric_sys_1 및 numeric_sys_2 변수로 설정되지 않았 음을 확신하는 경우 가장 단순하고 깨끗한 솔루션입니다.

반면에 "16 진수", "10 진수"및 "이진"이외의 값이있는 경우 사전을 사용 가능한 값과 조합하여 사전을 확장해야합니다.

여기의 논리는 다음과 같습니다. 사전 키의 변수 튜플이 지정된 변수 튜플과 같지 않으면 .get () 메서드는 "0"을 반환합니다. 주어진 가변 튜플이 사전의 키와 일치하면 일치하는 키의 값을 반환합니다.

def convert_what(numeral_sys_1, numeral_sys_2):
    return {
        ("Hexadecimal", "Decimal") : 1, 
        ("Hexadecimal", "Binary") : 2, 
        ("Binary", "Decimal") : 3,
        ("Decimal", "Hexadecimal") : 4,
        ("Binary", "Hexadecimal") : 5, 
        ("Decimal", "Binary") : 6, 
     }.get((numeral_sys_1, numeral_sys_2), 0)

발전기를 사용하는 것도 해결책이 될 수 있습니다. 훨씬 똑똑해 보이지만 어려운 코딩 사전은이 간단한 요구 사항에 생성기를 사용하는 것보다 빠릅니다.


마지막 'else : return 0'에 대한 나의 해석은 인수가 일치하지 않으며 목록의 인수 (예 : dict 키) 이외의 다른 것이 될 수 있다는 것입니다.
8:23에

@tocode 그렇습니다. 그러나이 방법은 동일한 기능을 제공합니다. 메소드에 주어진 인수 중 하나 또는 둘 다가 문자열이 아닌 경우에도 없음 유형 값입니다. 사전에 키가 없기 때문에 .get () 메소드가 "0"을 리턴합니다. 간단하지 않습니까?
Sencer H.

Aryerez 답변을 복사하지 않았습니까?
Martin

@Martin 아니요. 당신은 분명히 요점을 놓치고 있습니다. 무언가를하는 방법에는 여러 가지가 있지만 올바른 방법을 가르치는 것이 여기서 기꺼이합니다. 실제로 아래에 더 나은 답변이 있습니다. furkanayd의 솔루션을 살펴보십시오. 그것은 결함이 없으며 현상금을 받아야했습니다.
Sencer H.

@SencerH. 유일한 차이점은 원래 답변의 시도 / 제외가 기본적으로하는 dict의 메소드 get ()을 사용했다는 것입니다. 당신은 아이디어를 복사하고 수정하고 게시 한 내용을 아주 약간 (개선하지 않고) 약간 수정했다는 사실을 부인할 수 없습니다
Martin

3

중첩 목록을 사용하는 다른 방법입니다. 그것이 도움이되기를 바랍니다!

def convert_what(numeral_sys_1, numeral_sys_2):

    l1 = [["Hexadecimal","Decimal"],["Hexadecimal","Binary"],
            ["Decimal","Hexadecimal"],["Decimal","Binary"],
            ["Binary","Hexadecimal"],["Binary","Decimal"]]

    return l1.index([numeral_sys_1, numeral_sys_2]) + 1 if [numeral_sys_1,numeral_sys_2] in l1 else 0

2

내 생각에,이 convert_what기능 자체는 매우 파이썬이 아닙니다. 이 코드를 호출하는 코드에는 많은 if 문이 있고의 반환 값에 따라 변환을 수행합니다 convert_what(). 나는 이와 같은 것을 제안한다 :

첫 번째 단계는 모든 조합에 대해 하나의 기능을 만듭니다.

def hex_dec(inp):
    return 1234  # todo implement
# do the same for hex_bin, bin_dec, dec_hex, bin_hex, dec_bin

두 번째 단계는 함수 객체를 dict에 넣습니다. 함수 이름 뒤에 ()는 없습니다. 함수 객체를 저장하고 아직 호출하지 않기 때문입니다.

converter_funcs = {
    ("Hexadecimal", "Decimal"): hex_dec,
    ("Hexadecimal", "Binary"): hex_bin,
    ("Binary", "Decimal"): bin_dec,
    ("Decimal", "Hexadecimal"): dec_hex,
    ("Binary", "Hexadecimal"): bin_hex,
    ("Decimal", "Binary"): dec_bin,
}

세 번째이자 마지막 단계는 변환 기능을 구현하는 것입니다. if 문은 두 시스템이 동일한 지 확인합니다. 그런 다음 dict에서 올바른 기능을 가져 와서 호출합니다.

def convert(input_number, from_sys, to_sys):
    if from_sys == to_sys:
        return input_number
    func = converter_funcs[(from_sys, to_sys)]
    return func(input_number)

2

이것은 대부분의 다른 언어로 된 switch-case 문으로 수행됩니다. 파이썬에서는 식 사전과 함께 간단한 함수를 사용합니다.

암호:

def convert_what(numeral_sys_1, numeral_sys_2):
    myExpressions = {"Hexadecimal" : {"Decimal" : 1, "Binary" : 2},
                    "Decimal" : {"Hexadecimal" : 4, "Binary" : 6}, 
                    "Binary" : {"Hexadecimal" : 5, "Decimal" : 3}}
    return (myExpressions.get(numeral_sys_1, {})).get(numeral_sys_2, 0)

산출:

> convert_what("Hexadecimal", "Decimal")
> 1
> convert_what("Binary", "Binary")
> 0
> convert_what("Invalid", "Hexadecimal")
> 0

이것은 최고의 답변에 대한 좋은 대안이며 더 많은 가치로 확장하는 것이 더 쉽습니다.
gkhnavarro

이것은 이전 답변과 매우 유사합니다 : stackoverflow.com/a/58985114/1895261 . 또한 numeric_sys_1이 외부 dict에없는 경우 마지막 행이 0이 아닌 빈 dict를 반환해야한다고 생각합니다. return (myExpressions.get (numeral_sys_1, {})). get (numeral_sys_2, 0)
Sepia

질문의 @Sepia는 else 문에서 0을 제공합니다. 즉, 0은 주어진 식과 평등 상황에 맞지 않는 것을 반환합니다.
furkanayd

1
코드로 print (convert_what ( "invalid", "Hexadecimal"))를 실행 해보십시오. "AttributeError : 'int'개체에 'get'특성이 없습니다."라는 오류가 발생합니다. 첫 번째 0을 빈 dict ({})로 바꾸면 numeric_sys_1이 유효하지 않은 경우 함수가 0을 올바르게 리턴합니다.
세피아

1

일반적으로 중첩 된 if 작업에 대한 사전 솔루션으로 실행합니다. 특정한 경우에는 다른 접근 방식이있을 수 있습니다. 이 같은:

def convert_what(numeral_sys_1, numeral_sys_2):

    num = ['Hexadecimal','Decimal','Binary']
    tbl = [[0,1,2],
           [4,0,6],
           [5,3,0]]
    try:
        return tbl[num.index(numeral_sys_1)][num.index(numeral_sys_2)]
    except ValueError:
        return 0

1

어때요?

def convert_what(numeral_sys_1, numeral_sys_2):
    src = numeral_sys_1, numeral_sys_2
    if src == "Hexadecimal", "Decimal":
        return 1
    if src == "Hexadecimal", "Binary"
        return 2
    # You get the gist.... 
    if src == "Decimal", "Binary":
        return 6
    return 0 

1

아이디어는 목록을 사용하고 결과 색인을 가져옵니다.

def convert_what(numeral_sys_1, numeral_sys_2):
    if numeral_sys_1 == numeral_sys_2:      
        return 0
    return ["HexadecimalDecimal", "HexadecimalBinary", "BinaryDecimal", "DecimalHexadecimal", "BinaryHexadecimal", "DecimalBinary" ].index(numeral_sys_1 + numeral_sys_2) + 1

흥미있는 제안하지만 인수에 ValueError 결과 ( "진수", "없음")이다이 doesnot 작업 'DecimalNot은'목록에없는
tocode

1

@Sadap이 말했듯이

내 생각에,이 convert_what기능 자체는 매우 파이썬이 아닙니다. 이 코드를 호출하는 코드에는 많은 if 문이 있고 반환 값에 따라 변환을 수행합니다.convert_what(). 나는 이와 같은 것을 제안한다 :

정수에 대한 기본 변환을 구현하는 경우 어쨌든 공통 표현을 사용하는 것입니다. int 입니다. 각 염기 쌍에 대해 별도의 기능이 필요하지 않으며 관련된 두 염기가 서로를 알 필요조차 없습니다.

입력

숫자 시스템의 이름에서 기본으로의 맵핑을 작성하십시오.

BINARY = "Binary"
DECIMAL = "Decimal"
HEXADECIMAL = "Hexadecimal"

BASES = {
    BINARY: 2,
    DECIMAL: 10,
    HEXADECIMAL: 16,
}

로 입력을 읽을 수 있습니다 int(text, BASES[numeral_sys_1]).

산출

숫자 시스템의 이름에서 형식 지정 자로의 맵핑을 작성하십시오 .

FORMATTERS = {
    BINARY: "b",
    DECIMAL: "d",
    HEXADECIMAL: "x",
}

로 출력을 쓸 수 있습니다 format(n, FORMATTERS[numeral_sys_2]).

사용 예

def convert(text, numeral_sys_1, numeral_sys_2):
    n = int(text, BASES[numeral_sys_1])
    return format(n, FORMATTERS[numeral_sys_2])

또한 다른 int(x, base)정수 형식을 지원해야하거나 내장 정수 형식화 지원과 다른 출력 기반 을 지원해야하는 경우 값 함수를 대신 사용하여보다 일반적으로 사용할 수 있습니다 .


0

코드를 건조하게 유지하고 싶습니다.

def convert_what_2(numeral_sys_1, numeral_sys_2):
    num_sys = ["Hexadecimal", "Decimal", "Binary"]
    r_value = {0: {1: 1, 2: 2},
               1: {0: 4, 2: 6},
               2: {0: 5, 1: 3} }
    try:
        value = r_value[num_sys.index(numeral_sys_1)][num_sys.index(numeral_sys_2)]
    except KeyError: # Catches when they are equal or undefined
        value = 0
    return value

0

다른 답변이 제공하고 결합한 몇 가지 기술 사용 :

def convert(key1, key2):
    keys = ["Hexadecimal", "Decimal", "Binary"]
    combinations = {(0, 1): 1, (0, 2): 2, (1, 0): 4, (1, 2): 6, (2, 0): 5, (2, 1): 3} # use keys indexes to map to combinations
    try:
        return combinations[(keys.index(key1), keys.index(key2))]
    except (KeyError, ValueError): # if value is not in list, return as 0
        return 0

-1

이 방법이 더 빠른지 확실하지 않지만 numpy를 사용하여 수행 할 수도 있습니다.

conditions = [
    ("Hexadecimal", "Decimal"), ("Hexadecimal", "Binary"),
    ("Binary", "Decimal"), ("Decimal", "Hexadecimal"), ("Binary", "Hexadecimal"), ("Decimal", "Binary")]
choices = [1,2,3,4,5,6]

다음과 같이 사용할 수 있습니다.

 np.select(conditions, choices, default=0)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.