Có cách nào tốt hơn để viết lồng nhau nếu các câu lệnh trong python? [đóng cửa]


34

Có cách nào khác để thực hiện lồng nhau nếu các câu lệnh khác hơn cách này không:

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

Kịch bản này là một phần của một trình chuyển đổi đơn giản.


Không sử dụng cấu trúc dữ liệu khác, bạn có thể di chuyển các câu lệnh if-other lồng vào các andđiều kiện cho các câu lệnh if-other cấp cao nhất. Nó ít nhất sẽ dễ đọc hơn theo cách đó. Đáng buồn thay, python không có báo cáo chuyển đổi.
adamkgray

Đây cách pythonic. Python cố tình không hỗ trợ các câu lệnh chuyển đổi. Xem python.org/dev/peps/pep-3103
Jongmin Baek

1
Không phải là câu hỏi, nhưng nếu bạn đang cố gắng tạo ra nhiều thứ hơn Pythonic, làm thế nào về việc xác định các hằng số hoặc một enum cho các giá trị trả về - tốt hơn cho người đọc so với "số ma thuật" ....
Mats Doesmann

Câu trả lời:


13

Trong khi câu trả lời của @Aryerez và @ SencerH. hoạt động, mỗi giá trị numeral_sys_1có thể phải được ghi lại cho mỗi giá trị có thể numeral_sys_2khi liệt kê các cặp giá trị, làm cho cấu trúc dữ liệu khó duy trì hơn khi số lượng giá trị có thể tăng lên. Thay vào đó, bạn có thể sử dụng một lệnh đọc lồng nhau thay cho các câu lệnh if lồng nhau của bạn thay vào đó:

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)

Ngoài ra, bạn có thể tạo các cặp giá trị cho ánh xạ với itertools.permutationsphương thức, thứ tự theo sau của chuỗi đầu vào:

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

Chèn tất cả các kết hợp hợp lệ vào a dictionarycủa tuples và nếu kết hợp không có ở đó, trả về 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)

Nếu bạn đang dự định sử dụng hàm trong một vòng lặp, có thể nên xác định từ điển bên ngoài hàm, vì vậy nó sẽ không được tạo lại trên mỗi lệnh gọi hàm.


2
except KeyError:
RomanPerekhrest

@RomanPerekhrest Tôi đã thêm nó, mặc dù trong câu hỏi cụ thể này, bản thân hàm không có các loại lỗi khác để tạo ra một đầu ra khác với hàm ban đầu của nó.
Aryerez

1
Các parens là dư thừa bên trong []. Ngoại trừ bộ dữ liệu trống, đó là dấu phẩy làm cho bộ dữ liệu đó, không phải dấu ngoặc đơn, chỉ dành cho thứ tự các thao tác trong một số trường hợp.
gilch

4
Bạn chỉ có thể sử dụng .get()phương thức dict với 0mặc định thay vì trycâu lệnh.
gilch

@gilch Mình bỏ dấu ngoặc đơn. Nhưng tôi thích try:... except:...cấu trúc.
Aryerez

17

Nếu bạn chắc chắn rằng không có giá trị nào khác có thể được đặt thành các biến num num_sys_1 và numeral_sys_2 thì đây là giải pháp đơn giản và sạch nhất.

Mặt khác, bạn phải mở rộng từ điển với các kết hợp của nó với các giá trị khả dụng, nếu bạn có bất kỳ giá trị nào khác ngoài "Hệ thập lục phân", "Số thập phân" và "Nhị phân"

Logic ở đây là; nếu các tuple biến trong các khóa từ điển không bằng tuple biến đã cho, phương thức .get () trả về "0". Nếu tuple biến được đưa ra khớp với bất kỳ khóa nào trong từ điển, do đó trả về giá trị của khóa khớp.

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)

Ngoài ra còn sử dụng máy phát điện có thể là một giải pháp. Trông thông minh hơn nhiều, nhưng tôi nghĩ rằng từ điển mã hóa cứng sẽ nhanh hơn sử dụng một trình tạo cho yêu cầu đơn giản này.


Giải thích của tôi về 'other: return 0' cuối cùng là các đối số không khớp và có thể là một cái gì đó khác bên cạnh những đối số trong danh sách (ví dụ: các khóa chính tả của bạn).
mã hóa

@tocode Vâng, bạn nói đúng. Nhưng phương pháp này cũng cung cấp chức năng tương tự. Nếu bất kỳ hoặc cả hai đối số được cung cấp cho phương thức, giả sử, không phải chuỗi, thậm chí là giá trị loại Không; Phương thức .get () trả về "0" do thiếu khóa trong từ điển. Nó không đơn giản sao?
Sencer H.

bạn không sao chép câu trả lời của Aryerez?
Martin

@Martin Không tôi không có. Bạn rõ ràng đang thiếu điểm. Có nhiều cách để làm một cái gì đó nhưng dạy cách chính xác là những gì tôi sẵn sàng làm ở đây. Trên thực tế có nhiều câu trả lời tốt hơn dưới đây. Hãy xem giải pháp của furkanayd. Thật hoàn hảo và phải nhận tiền thưởng.
Sencer H.

@ SencerH. Sự khác biệt duy nhất là bạn đã sử dụng phương thức của dict get (), về cơ bản là những gì câu trả lời ban đầu của thử / ngoại trừ. Bạn không thể phủ nhận thực tế, rằng bạn đã sao chép ý tưởng và rất rất ít (không cải thiện) được sửa đổi và xuất bản
Martin

3

Một cách khác để sử dụng danh sách lồng nhau. Hy vọng nó giúp!!

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

Theo tôi, convert_whatchức năng này tự nó không phải là rất pythonic. Tôi đoán mã gọi mã này cũng có một loạt các câu lệnh if và thực hiện chuyển đổi tùy thuộc vào giá trị trả về của convert_what(). Tôi đề nghị một cái gì đó như thế này:

Bước đầu tiên, tạo một chức năng cho mọi kết hợp:

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

Bước thứ hai, đặt các đối tượng chức năng trong một dict. Lưu ý rằng không có () sau tên hàm, vì chúng tôi muốn lưu trữ đối tượng hàm và chưa gọi nó:

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,
}

Bước thứ ba và cuối cùng, thực hiện chức năng chuyển đổi. Câu lệnh if kiểm tra nếu cả hai hệ thống giống nhau. Sau đó, chúng tôi nhận được chức năng đúng từ dict của chúng tôi và gọi nó:

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

Điều này được thực hiện bằng các câu lệnh chuyển đổi trong hầu hết các ngôn ngữ khác. Trong python, tôi sử dụng một hàm đơn giản với một từ điển biểu thức.

Mã số:

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)

Đầu ra:

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

đây là một lựa chọn tốt cho câu trả lời hàng đầu và cũng dễ dàng mở rộng thành nhiều giá trị hơn.
gkhnavarro

Điều này khá giống với câu trả lời trước: stackoverflow.com/a/58985114/1895261 . Ngoài ra, tôi nghĩ rằng dòng cuối cùng sẽ trả về dict trống thay vì 0 trong trường hợp numeral_sys_1 không nằm trong dict ngoài: return (myExpressions.get (numeral_sys_1, {})). Get (numeral_sys_2, 0)
Sepia

@Sepia trong câu hỏi Module_art đưa ra 0 ở câu lệnh khác, có nghĩa là trả về 0 bất cứ điều gì không phù hợp với các biểu thức đã cho và tình huống bình đẳng.
furkanayd

1
Hãy thử chạy print (convert_what ("không hợp lệ", "Hệ thập lục phân")) với mã của bạn. Nó sẽ đưa ra một lỗi: "AttributionError: 'int' object không có thuộc tính 'get'". Thay thế 0 đầu tiên bằng dict trống ({}) sẽ làm cho hàm trả về 0 chính xác trong trường hợp numeral_sys_1 không hợp lệ.
Sepia

1

Nói chung tôi sẽ chạy với giải pháp từ điển cho lồng nhau nếu tác vụ. Một số trường hợp cụ thể có thể mang đến một cách tiếp cận khác. Như cái này:

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

Làm thế nào về một cái gì đó như:

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

Một ý tưởng đang sử dụng một danh sách và nhận chỉ số kết quả, tức là.

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

Đề xuất thú vị nhưng điều này không hoạt động khi các đối số là ("Số thập phân", "Không"), dẫn đến ValueError: 'DecimalNot' không có trong danh sách
mã hóa

1

Như @Sadap đã nói,

Theo tôi, convert_whatchức năng này tự nó không phải là rất pythonic. Tôi đoán mã gọi mã này cũng có một loạt các câu lệnh if và thực hiện chuyển đổi tùy thuộc vào giá trị trả về của convert_what(). Tôi đề nghị một cái gì đó như thế này:

Nếu bạn đang thực hiện chuyển đổi cơ sở cho số nguyên, có lẽ bạn cũng sẽ trải qua một đại diện chung : int. Một chức năng riêng biệt cho mỗi cặp căn cứ là không cần thiết và hai cơ sở liên quan thậm chí không cần biết về nhau.

Đầu vào

Tạo ánh xạ từ tên của một hệ thống số đến cơ sở của nó:

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

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

cho phép bạn đọc đầu vào với int(text, BASES[numeral_sys_1]).

Đầu ra

Tạo ánh xạ từ tên của một hệ thống số sang một bộ xác định định dạng :

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

cho phép bạn viết kết quả đầu ra với format(n, FORMATTERS[numeral_sys_2]).

Ví dụ sử dụng

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

Thay vào đó, dict cũng có thể được tạo ra tổng quát hơn bằng cách tạo các hàm giá trị, nếu bạn cần hỗ trợ một bộ định dạng khác hơn int(x, base)hoặc nhiều cơ sở đầu ra hơn các hỗ trợ định dạng số nguyên tích hợp.


0

Tôi thích giữ mã khô:

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

Sử dụng một số kỹ thuật mà các câu trả lời khác cung cấp và kết hợp chúng:

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

Mặc dù không chắc cách tiếp cận này có nhanh hơn không, nhưng cũng có thể được thực hiện bằng cách sử dụng numpy:

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

và có thể được sử dụng như:

 np.select(conditions, choices, default=0)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.