2010-07-04 11 views
59

False jest równoważna 0 i True jest równoznaczne 1 więc jest to możliwe, aby zrobić coś takiego:Czy Pythonic używa boolów jako ints?

def bool_to_str(value): 
    """value should be a bool""" 
    return ['No', 'Yes'][value] 

bool_to_str(True) 

zauważyć, jak wartość jest bool ale jest używany jako int.

Czy to jest tego rodzaju użycie Pythoniczne, czy powinno się go unikać?

+1

To jest w zasadzie kopią http://stackoverflow.com/questions/2764017/is-false-0-and-true-1-in-python-an-implementation-detail-or-is- to gwarancja, której odpowiedzi również stanowią ciekawą lekturę! – EOL

Odpowiedz

154

będę dziwny głos out (ponieważ wszystkie odpowiedzi są decrying wykorzystanie faktu, że False == 0 i True == 1, jako gwarancji językowych), a ja twierdzą, że korzystanie z tego faktu, aby uprościć kod jest perfekcyjnie.

Historycznie, operacje logiczne prawda/fałsz zwykle używają 0 dla false i 1 dla true; w trakcie cyklu życia Pythona 2.2, Guido zauważył, że zbyt wiele modułów rozpoczęło się od przydziałów takich jak false = 0; true = 1, a to spowodowało, że wznowiono standardową i bezużyteczną wariację (ta ostatnia, ponieważ kapitalizacja wartości true i false była wszędzie - niektóre używane all-caps, niektóre małe litery, niektóre początkowe cap) i tak wprowadzono podklasę bool z int i jej stałych True i.

Było sporo pushback w czasie, ponieważ wielu z nas obawiał się, że nowy typ i stałe zostaną wykorzystane przez początkujących Pythona do ograniczać zdolności języku, ale Guido był nieugięty, że byliśmy po prostu pesymistyczny: nikt nie zawsze rozumiem Pythona tak źle, na przykład, aby uniknąć całkowicie naturalnego wykorzystania indeksów listy, lub w podsumowaniu, lub innych tak doskonale zrozumiałych i przydatnych idiomów.

odpowiedź na tego wątku udowodnić mieliśmy rację: jak się obawialiśmy, całkowite niezrozumienie roli tego typu i stałych został pojawiły, a ludzie unikając, a gorzej !, zachęcając innych do uniknięcia , doskonale naturalny Python konstruuje na rzecz bezużytecznych zawirowań.

Walka pod prąd takiego nieporozumienia, wzywam wszystkich do używać Python jako Python, nie próbując zmusić go do formy z innych języków, których funkcjonalność i preferowany styl są zupełnie inne. W Pythonie, Prawda i fałsz są 99,9% jak 1 i 0, różniących wyłącznie w ich str(...) (a tym samym repr(...)) formie - dla każdy innej operacji oprócz stringification, po prostu czuć się swobodnie z nich korzystać bez skurczów. Że idzie do indeksowania, arytmetyki, operacji bitowych, etc, etc, etc.

+8

+1 Kontrast z Ruby, która wymusza "val? 1: 0" i podobne gimnastyczne śmieci, jeśli potrzebujesz potraktować bool jako int. –

+18

"nikt nie zrozumie tak źle Pythona, na przykład, aby uniknąć całkowicie naturalnego użycia Fałszywych i Prawdziwych jako wskaźników listy". Z pewnością nie jestem przeciwny używaniu ich w ten sposób, ale w żaden sposób nie uważam, że "naturalne" jest, aby ludzie indeksowali listę z typem boolowskim, chyba że zdają sobie sprawę, że podkategorie 'bool'' int' –

+3

Interesująca historia w rzeczywistości lekcja! Twierdzę jednak, że jest coś, co mówi o tym, że większość ludzi odróżnia booleany od liczb całkowitych (ja to robię ...). W pewnym sensie ludzie definiują, co to znaczy "używać Pythona jako Pythona": większość z nas uważa, że ​​istnieje logiczne rozróżnienie między tymi dwoma typami (matematyka w większości również: logika nie potrzebuje arytmetyki). Jestem całkiem zadowolony z faktu, że Python pozwala nam myśleć w ten sposób. – EOL

35

pewno:

def bool_to_str(value): 
    "value should be a bool" 
    return 'Yes' if value else 'No' 

jest bardziej czytelny.

+2

Chciałbym się z tym kłócić ...tak, używając 'x if foo else y' thingy jest bardziej pythonic, ale nadal uważam, że to wygląda po prostu brzydko i często nadpisuje kod. Myślę, że kod w pytaniu ** wygląda ** wyraźniej, może być mylący dla osób, które nie wiedzą o niejawnej konwersji bool na int, ale 'x jeśli foo else y' jest tak samo mylące dla kogoś, kto pochodzi z "foo? x: y' świat rzeczy. Chociaż muszę przyznać, że dla ludzi, którzy uczą się swojego pierwszego języka, "x if foo else y" może być najczystszym. –

+2

@Ivo, +1, ponieważ zgadzam się co do istoty, ale nie zgadzam się, że konstrukcja "trójskładnikowa" (z warunkiem w środku, a nie na początku jak w C) jest szczególnie naturalna lub jasna dla początkujących (jest to najmniejszy z zło w wielu przypadkach - to coś innego ;-). –

+0

nie jestem pewien, wygląda na to, że mam też, mniej więcej w tym samym czasie (a także bez komentarzy!). –

5

Właściwie jest to cecha języka, Fałsz i Prawda == 0 == 1 (nie zależy od realizacji): Is False == 0 and True == 1 in Python an implementation detail or is it guaranteed by the language?

Jednak zgadzam się z większością innych odpowiedzi: nie są bardziej czytelne sposoby na uzyskanie tego samego wyniku, co ['No', 'Yes'][value], poprzez użycie … if value else … lub słownika, który ma odpowiednie zalety wskazujące i stwierdzenie, że value jest boolowskie.

Plus, przestrzega zwykłej konwencji, że wartość inna niż 0 jest prawdziwa: działa również, gdy value == -2 (wartość jest prawdziwa), jak sugeruje dalia. Podejście do listy i dyktowania nie jest w tym przypadku tak silne, więc nie polecałbym ich.

+0

Dlaczego upadek? – EOL

13

Kod wydaje niedokładne w niektórych przypadkach:

>>> def bool_to_str(value): 
...  """value should be a bool""" 
...  return ['No', 'Yes'][value] 
... 
>>> bool_to_str(-2) 
'No' 

A ja polecam użyć tylko operatora warunkowego dla czytelności:

def bool_to_str(value): 
    """value should be a bool""" 
    return "Yes" if value else "No" 
+14

Nazwa funkcji to 'bool_to_str', z doc komentarzem' wartość powinna być boolem ', a ty jesteś zaskoczony, że daje błędną odpowiedź, gdy ją podajesz '-2' :) –

+0

Z drugiej strony, chciałbym się spierać że zwykle przyjmuje się, że non-0 oznacza True ... Jak pokazuje przykład Dahlia, metoda '... if ... else ...' pozwala na stworzenie kodu, który nie jest niepotrzebnie restrykcyjny. – EOL

+3

+1 Chociaż zgadzam się ogólnie z odpowiedzią Alexa Martellego, w tym przypadku wydaje się, że "bardziej Pythonicznie" korzysta z niejawnej konwersji na 'bool' zapewniany przez' ... if ... else ... '. Wtedy funkcja działa na sygnały i cokolwiek innego. Być może nie jest to najlepszy przykład, ponieważ nie zgadzam się z ideą używania bools jako ints. – shambulator

1

Użycie bool jako int jest całkiem w porządku, ponieważ bool jest podklasą o int.

>>> isinstance(True, int) 
True 
>>> isinstance(False, int) 
True 

O Twoim kodzie: Umieszczenie go w jednoliniowej funkcji, takiej jak ta, jest u góry. Czytelnicy muszą znaleźć źródło funkcji lub dokumenty i je przeczytać (nazwa funkcji nie mówi zbyt wiele). To przerywa przepływ. Po prostu wstaw to w linii i nie używaj listy (zbudowanej w czasie wykonywania), użyj krotki (zbudowanej w czasie kompilacji, jeśli wartości są stałe). Przykład:

print foo, bar, num_things, ("OK", "Too many!)[num_things > max_things] 
130

Jestem z Alexem. False==0 i True==1 i nie ma w tym nic złego.

Mimo to, w Pythonie 2.5 i później będę pisać odpowiedź na to konkretne pytanie korzystając wyrażenie warunkowe Pythona:

def bool_to_str(value): 
    return 'Yes' if value else 'No' 

W ten sposób nie ma wymogu, że argument jest rzeczywiście bool - podobnie jak if x: ... akceptuje dowolny typ dla x, funkcja bool_to_str() powinna zrobić to, co należy, gdy zostanie przekazana None, ciąg, lista lub 3.14.

0

Osobiście myślę, że to zależy od tego w jaki sposób chcesz wykorzystać ten fakt, oto dwa przykłady

  1. Wystarczy po prostu użyć jako wartość logiczną warunkowe stwierdzenie jest w porządku. Ludzie robią to cały czas.

    a = 0 
    if a: 
        do something 
    
  2. jednak, że chcesz policzyć ile przedmiotów ma odnieść sukces, kod może nie bardzo przyjazny dla innych ludzi do czytania.

    def succeed(val): 
        if do_something(val): 
         return True 
        else: 
         return False 
    
    count = 0 
    values = [some values to process] 
    for val in values: 
        count += succeed(val) 
    

Ale widzę wygląd kodu produkcja takiego.

all_successful = all([succeed(val) for val in values]) 
at_least_one_successful = any([succeed(val) for val in values]) 
total_number_of_successful = sum([succeed(val) for val in values]) 
Powiązane problemy