Nie ma specjalnego powodu. Python po prostu stosuje swoją ogólną zasadę niewykonania niejawnych konwersji, które są dobrze znanymi przyczynami problemów, szczególnie dla nowicjuszy, w językach takich jak Perl i Javascript.
int(some_string)
jest jawnym żądaniem konwersji łańcucha na format całkowity; reguły tej konwersji określają, że łańcuch musi zawierać prawidłową reprezentację literału w postaci liczby całkowitej. int(float)
jest jawnym żądaniem konwersji liczby zmiennoprzecinkowej na liczbę całkowitą; reguły tej konwersji określają, że część ułamkowa zmiennej zostanie obcięta.
Aby int("3.1459")
zwrócić, 3
interpreter musiałby niejawnie przekonwertować napis na zmiennoprzecinkowy. Ponieważ Python nie obsługuje niejawnych konwersji, zamiast tego wybiera zgłoszenie wyjątku.
type(3)
zwraca<type int>
. Jednak Python nie narzekafloat("3")
. Czy Python nie konwertuje niejawnie ciągu na int, a następnie na float?Jest to prawie na pewno przypadek zastosowania trzech zasad z Zen of Python :
int('1.23')
Przez pewien procent czasu ktoś wywołuje niewłaściwą konwersję dla swojego przypadku użycia i chce czegoś takiego jakfloat
lubdecimal.Decimal
zamiast tego. W takich przypadkach zdecydowanie lepiej jest, jeśli otrzymają natychmiastowy błąd, który mogą naprawić, zamiast po cichu podawać niewłaściwą wartość.W przypadku, że nie chce obciąć że do int, to jest trywialne jawnie zrobić poprzez przepuszczenie go przez
float
pierwszy, a następnie wywołanie jednej zint
,round
,trunc
,floor
lubceil
w stosownych przypadkach. To również sprawia, że twój kod jest bardziej samodokumentujący, chroniąc przed późniejszą modyfikacją „poprawiającą” hipotetyczneint
wywołanie cichego obcięciafloat
przez wyjaśnienie, że zaokrąglona wartość jest tym, czego chcesz.źródło
Czasami może się przydać eksperyment myślowy.
int('1.23')
kończy się niepowodzeniem z błędem. To jest istniejące zachowanie.int('1.23')
produkuje1
bez błędów. Oto, co proponujesz.W przypadku zachowania A uzyskanie efektu zachowania B jest proste i trywialne: użyj
int(float('1.23'))
zamiast tego.Z drugiej strony, w przypadku zachowania B uzyskanie efektu zachowania A jest znacznie bardziej skomplikowane:
def parse_pure_int(s): if "." in s: raise ValueError("invalid literal for integer with base 10: " + s) return int(s)
(a nawet z powyższym kodem nie mam całkowitej pewności, że nie ma jakiegoś narożnika, z którym źle sobie radzi).
Zachowanie A jest zatem bardziej wyraziste niż zachowanie B.
Kolejna rzecz do rozważenia:
'1.23'
to łańcuchowa reprezentacja wartości zmiennoprzecinkowej. Konwersja'1.23'
do całkowitej koncepcyjnie obejmuje dwie konwersje (ciąg pływaka do liczby całkowitej), aint(1.23)
iint('1')
każda konwersja obejmować tylko jeden.Edytować:
I rzeczywiście, istnieją przypadki narożne, których powyższy kod nie poradziłby:
1e-2
i1E-2
obie są również wartościami zmiennoprzecinkowymi.źródło
int('123E-2')
lubint('1L')
.Krótko mówiąc - to nie ta sama funkcja.
Są to 2 różne funkcje o tej samej nazwie, które zwracają liczbę całkowitą, ale są to różne funkcje.
„int” jest krótkie i łatwe do zapamiętania, a jego znaczenie przypisane do każdego typu jest intuicyjne dla większości programistów, dlatego właśnie go wybrali.
Nie ma żadnej sugestii, że zapewniają tę samą lub połączoną funkcjonalność, po prostu mają tę samą nazwę i zwracają ten sam typ. Równie łatwo można je nazwać „floorDecimalAsInt” i „convertStringToInt”, ale wybrali „int”, ponieważ jest łatwy do zapamiętania, (99%) intuicyjny i rzadko zdarzał się błąd.
Przetwarzanie tekstu jako liczby całkowitej dla tekstu zawierającego kropkę dziesiętną, taką jak „4,5”, spowodowałoby błąd w większości języków komputerowych i większość programistów oczekuje, że spowoduje to błąd , ponieważ wartość tekstowa nie reprezentuje liczby całkowitej i implikuje podają błędne dane
źródło
int
jest to typ (i do tego wbudowany). Jego twórca (__new__
) przyjmuje kilka możliwych typów argumentów. Jego zachowanie dla każdego typu jest dobrze zdefiniowane.int
w rzeczywistości nie jest funkcją, ale typem, którego metody__new__
i__init__
metody pobierają argumenty typu string lub float, obsługując odpowiednio każdy z nich. Dokładniej byłoby powiedzieć, że typ przetwarza dwa typy argumentów inaczej, ale jest tylko jedenint
.