Rozważ ten kod:

def say_hi(english: bool, name: str) -> str:
    if name != "":
        if english:
            greeting = f"Hi, {name}!"
    else:
        if english:
            greeting = "Hey there!"
    if english:
        greeting = greeting + "foo bar"
    if not english:
        greeting = "I speak only English, sorry."
    return greeting

Jaki jest najlepszy sposób na zoptymalizowanie tego kodu, aby nie był trzykrotnie taki sam, jeśli statmenet (if english:) w jednym bloku kodu? A może inne pytanie - czy ten powtarzający się kod instrukcji if jest zgodny ze standardami PEP Pythona?

-3
neisor 12 styczeń 2022, 12:27
1
Czego oczekujesz od greeting, jeśli english jest fałszywe?
 – 
khelwood
12 styczeń 2022, 12:29
if not english: raise NameError u góry funkcji, a następnie usuń zaznaczenie w innych miejscach…
 – 
deceze
12 styczeń 2022, 12:30
W tym przypadku to nie jest ważne. Powyższy kod służy jako przykład. To nie jest fragment kodu, którego należy użyć, a jedynie fragment kodu, aby zademonstrować moje pytanie.
 – 
neisor
12 styczeń 2022, 12:31
2
Jest to po prostu źle ustrukturyzowana logika lub przynajmniej nieefektywnie wyrażona logika. Nie potrzebujesz do tego PEP i w dużej mierze zależy to od konkretnego przypadku, w jaki sposób logika może być wyrażona w bardziej kompaktowy, ale nadal łatwy w utrzymaniu sposób.
 – 
deceze
12 styczeń 2022, 12:40

6 odpowiedzi

Najlepsza odpowiedź

Dlaczego po prostu nie odwrócić kolejności instrukcji if?

def say_hi(english: bool, name: str) -> str:
    if english:
        if name != "":
                greeting = f"Hi, {name}!"
        else:
                greeting = "Hey there!"
        greeting = greeting + "foo bar"
    else:
        greeting = "I speak only English, sorry."
    return greeting
2
matszwecja 12 styczeń 2022, 12:33

Możesz zrobić coś takiego:

def say_hi(english: bool, name: str) -> str:
    if not english:
        greeting = "I speak only English, sorry."
    else:
        greeting = (f"Hi, {name}!" if name else "Hey there!") + "foo bar"
    return greeting
2
Jakob Madsen 12 styczeń 2022, 12:37

To nie jest specyficzne dla Pythona i nie wymaga żadnego PEP, to po prostu część pisania Dobrego kodu™ i powinno być zastosowane do każdego kodu, który piszesz. Przejrzyj go i krok po kroku stosuj uproszczenia, aby sprowadzić go do najbardziej minimalnej, prostej, zrozumiałej formy.

Używam tutaj Twojego oryginalnego kodu, ponieważ pokazuje on dodatkową ważną lekcję:

def say_hi(english: bool, name: str) -> str:
    if name != "":
        if english:
            greeting = f"Hi, {name}!"
    else:
        if english:
            greeting = "Hey there!"
    if english:
        greeting = greeting + "foo bar"
    return greeting
  1. Rozpoznaj, że obie pierwsze gałęzie if..else zawierają ten sam test if english i że obie nic nie robią, jeśli english jest fałszywe. Możesz więc odwrócić tę kontrolę:

    if english:
        if name != "":
            greeting = f"Hi, {name}!"
        else:
            greeting = "Hey there!"
    
  2. Pamiętaj, że możesz wstawić ten wewnętrzny if..else:

    if english:
        greeting = f"Hi, {name}!" if name != "" else "Hey there!"
    

    Jest to dyskusyjne i zależy od twoich osobistych preferencji, ale myślę, że ma to zastosowanie tutaj.

  3. Rozpoznaj, że teraz masz dwukrotnie tę samą kontrolę stanu:

    if english:
        greeting = f"Hi, {name}!" if name != "" else "Hey there!"
    if english:
        greeting = greeting + "foo bar"
    

    Skróć to do:

    if english:
        greeting = f"Hi, {name}!" if name != "" else "Hey there!"
        greeting = greeting + "foo bar"
    
  4. Teraz coś, co istniało tylko w oryginalnym kodzie: rozpoznaj, że masz teraz błąd w swojej funkcji:

    def say_hi(english: bool, name: str) -> str:
        if english:
            greeting = f"Hi, {name}!" if name != "" else "Hey there!"
            greeting = greeting + "foo bar"
        return greeting
    

    Twoja funkcja w zasadzie nic nie robi, jeśli english jest fałszem i wygeneruje NameError w ostatniej linii. Jest to teraz łatwiejsze do rozpoznania dzięki uproszczonej logice. Tak więc, aby wyraźnie potwierdzić to zachowanie i wytworzyć dokładnie to samo zachowanie przy mniejszej ilości kodu, byłoby to tak:

    def say_hi(english: bool, name: str) -> str:
        if not english:
            raise NameError
    
        greeting = f"Hi, {name}!" if name != "" else "Hey there!"
        greeting = greeting + "foo bar"
        return greeting
    
  5. Rozpoznaj, że możesz skondensować dwie ostatnie linijki:

    def say_hi(english: bool, name: str) -> str:
        if not english:
            raise NameError
    
        greeting = f"Hi, {name}!" if name != "" else "Hey there!"
        return greeting + "foo bar"
    

    mógłbyś ponownie skondensować ostatnie dwie linijki, ale nie zrobiłbym tego ze względu na czytelność.

  6. Rozpoznaj, że puste ciągi są fałszywe, a wszystkie inne są prawdziwe, więc uprość sprawdzanie name != "":

    greeting = f"Hi, {name}!" if name else "Hey there!"
    

I oczywiście zamiast raise NameError zwrócisz inną wiadomość, tak jak w Twoim stałym kodzie:

def say_hi(english: bool, name: str) -> str:
    if not english:
        return "I speak only English, sorry."

    greeting = f"Hi, {name}!" if name else "Hey there!"
    return greeting + "foo bar"

W ten sposób skondensowaliśmy sześć gałęzi logicznych do jednej i pół (język w policzek).

1
deceze 12 styczeń 2022, 13:08

Poszedłbym z

def say_hi(english: bool, name: str) -> str:
    if name != "" and english:
        greeting = f"Hi, {name}!"
    elif name == "" and english:
        greeting = "Hey there!"
    return greeting + "foo bar" if english else /*greeting*/
0
anthino12 12 styczeń 2022, 12:33
def say_hi(english: bool, name: str) -> str:
    if name != "":
        if english: #   return True
            greeting = f"Hi, {name}!"
    else:
        if english: # return True
            greeting = "Hey there!"
    if english: #return True
        greeting = greeting + "foo bar"
    return greeting

Dlatego podczas wywołania funkcji z wartością False zostało przekazane, ponieważ angielski zgłosi błąd , ponieważ wszystkie napisane instrukcje if zawsze zwrócą True

Aby tego uniknąć, dodaj instrukcję if blokuje uchwyt w języku angielskim, gdy jest to Flase w ten sposób

def say_hi(english: bool, name: str) -> str:
    
    if name != "" and english:
            greeting = f"Hi, {name}! foo bar" 
    elif english:
            greeting = "Hey there!"
        
    else:
        greeting = "False" 
0
naif123321 12 styczeń 2022, 12:55
  • Zawodzi szybko. tj. Umieść kod, który szybko się nie powiedzie, na górze.
  • tam, gdzie to możliwe, zmienne logiczne powinny zaczynać się od „is”
# Without Foo bar
def say_hi_2(is_english_speaker: bool, name: str):
    if not is_english_speaker:
        return "I speak only English, sorry."

    if not name:
        return "Hey There"

    return f"Hi, {name}"

# With foo bar
def say_hi(is_english_speaker: bool, name: str):
    if not is_english_speaker:
        return "I speak only English, sorry."

    greeting_template = "{} foo bar"
    if not name:
        return greeting_template.format("Hey There")

    return greeting_template.format(f"Hi, {name}")

1
Antonio Mande 12 styczeń 2022, 12:52