Czy jest jakaś różnica między wywołaniem len([1,2,3])
lub [1,2,3].__len__()
? Jeśli nie ma widocznej różnicy, co robi się inaczej za kulisami?różnica między len() i .__ len __()?
Odpowiedz
len
to funkcja pozwalająca uzyskać długość kolekcji. Działa poprzez wywołanie metody obiektu __len__
. Atrybuty __something__
są wyjątkowe i zwykle bardziej niż na pierwszy rzut oka, i generalnie nie powinny być wywoływane bezpośrednio.
Zdecydowano w pewnym momencie dawno coraz długość coś powinno być funkcją, a nie kod metoda, rozumowanie, że sens len(a)
„s byłoby jasne dla początkujących ale a.len()
nie byłoby tak oczywiste. Kiedy Python się rozpoczął __len__
nawet nie istniał, a len
był specjalną rzeczą, która działała z kilkoma typami obiektów. Niezależnie od tego, czy sytuacja, którą nam to pozostawia, ma sens, pozostajemy tutaj.
Zostanie na miejscu, ale nie zaszkodzi mieć również metody 'some_collection.length()'. Właściwie, '.size()' byłaby lepsza, ponieważ struktury danych oparte na drzewach mają rozmiar, ale nie są łatwo ilustrowane, aby mieć długość. –
@EvgeniSergeev Rzeczywiście, takie obiekty mają takie atrybuty - tablica numpy ma atrybut "shape" (który w ogóle nie jest metodą, ponieważ jest to właściwość obiektu, a nie akcja na obiekcie). –
fwi, jednym z prawdopodobnych powodów jest to, że python _really naprawdę_ nie lubi rezerwowania nazw metod - klasa 'Rectangle' może chcieć mieć' length' i 'width', a jeśli' .length() 'zostały skutecznie zarezerwowane, musiałbyś niezręcznie zmienić nazwę lub przerwać pisanie na maszynie. – Eevee
Można myśleć o len() jako grubsza odpowiada
def len(x):
return x.__len__()
Jedną z zalet jest to, że pozwala na pisanie rzeczy jak
somelist = [[1], [2, 3], [4, 5, 6]]
map(len, somelist)
zamiast
map(list.__len__, somelist)
lub
map(operator.methodcaller('__len__'), somelist)
Jest jednak trochę inne zachowanie. Na przykład w przypadku int
>>> (1).__len__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__len__'
>>> len(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
Zakładam, że masz na myśli 'operator.methodcaller' zamiast' operator.attrgetter'. – Elazar
@Elazar, tak, zrobiłem. dziękuje –
To często zdarza się, że „typowe” zachowanie wbudowany lub operator jest wywołanie (z różnych i ładniejsze składniowych) nadaje metod magicznych (te o nazwach takich jak __whatever__
) na przedmiotach. Często wbudowany lub operator ma "wartość dodaną" (może przyjmować różne ścieżki w zależności od obiektów) - w przypadku len
vs __len__
, to tylko trochę sprawdzenia poprawności na wbudowanym, którego brakuje z magicznym sposobem:
>>> class bah(object):
... def __len__(self): return "an inch"
...
>>> bah().__len__()
'an inch'
>>> len(bah())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer
Kiedy widzisz wywołanie len
wbudowany, jesteś pewien, że jeśli program jest kontynuowany po tym zamiast podniesienia wyjątek, rozmowa wróciła liczbę całkowitą , nieujemny i mniej niż 2 ** 31 - kiedy widzisz połączenie z xxx.__len__()
, nie masz pewności (z wyjątkiem tego, że autor kodu jest albo nie zna Pythona, albo do niczego dobrego ;-).
Inne wbudowane elementy zapewniają jeszcze więcej wartości dodanej niż proste testy poprawności i czytelność. Poprzez jednolite projektowanie całego Pythona do pracy za pośrednictwem wywołań do wbudowań i korzystania z operatorów, nigdy poprzez połączenia z magicznymi metodami, programiści są oszczędzani od ciężaru pamiętania, który przypadek jest który. (Czasami pojawia się błąd: do wersji 2.5 trzeba było zadzwonić pod numer foo.next()
- w wersji 2.6, mimo że nadal działa pod kątem kompatybilności wstecznej, należy wywołać next(foo)
, a w 3.*
metoda magiczna ma poprawną nazwę __next__
zamiast "oops- ey "next
! -).
Tak więc ogólną zasadą powinno być nigdy nie wywoływanie metody magicznej bezpośrednio (ale zawsze pośrednio poprzez wbudowane), chyba że wiesz dokładnie, dlaczego musisz to zrobić (np., kiedy nadpisujesz taką metodę w podklasie, jeśli podklasa musi odroczyć nadklasę, która musi zostać wykonana poprzez jawne wywołanie metody magicznej).
Jestem początkującym użytkownikiem Pythona (nie myślał o tym początkujący programista) i nie jestem pewien "Kiedy zobaczysz połączenie z wbudowanym lenem, jesteś pewien, że jeśli program będzie kontynuowany po tym, zamiast zgłaszać wyjątek ". Próbowałem tego: 'def len (x): \t return" Jestem ciągiem ". print (len (42)) print (len ([1,2,3])) 'i wydrukowano' I'm string' dwa razy. Czy możesz wyjaśnić to więcej? –
@ DarekNędza To nie ma nic wspólnego z powyższym, co dotyczy wbudowanego lena. Po prostu zdefiniowałeś swoją funkcję len, która może oczywiście przywrócić cokolwiek zechcesz. OP mówił o builtin len, który nazywa '__len__' specjalnym _method_ (nie funkcją) na rozważanym obiekcie. – Veky
@ Veky Jak mogę się upewnić, że wywołuję wbudowaną funkcję 'len', a nie inną funkcję (jak w moim przykładzie), która miała tę samą nazwę -' len'. Nie ma ostrzeżenia typu "Jesteś redefiniujesz wbudowaną funkcję len" lub coś podobnego. Moim zdaniem nie mogę być pewien, co Alex powiedział w swojej odpowiedzi. –
Można sprawdzić Pythond docs:
>>> class Meta(type):
... def __getattribute__(*args):
... print "Metaclass getattribute invoked"
... return type.__getattribute__(*args)
...
>>> class C(object):
... __metaclass__ = Meta
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print "Class getattribute invoked"
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
- 1. Jaka jest różnica między metodami len() i sys.getsizeof() w pythonie?
- 2. Profilowane wydajność len (zestaw) vs. zestawu .__ len __() w Pythonie 3
- 3. $ idx i $ len w warunkowym oświadczeniu dust.js
- 4. C++ odpowiada funkcji Python len()?
- 5. Czy można zmodyfikować zachowanie len()?
- 6. użyciu len() w Pandy dataframe
- 7. kształt vs len dla tablicy numpy
- 8. kolejka pythonów uzyskać rozmiar, użyć qsize() lub len()?
- 9. Dlaczego somelist [len (somelist)] generuje IndexError, ale nie somelist [len (somelist):]?
- 10. Count kontra len na Django QuerySet
- 11. Dlaczego nie len (plik) w Pythonie?
- 12. Jaka jest różnica między listą [-1:] [0] a listą [len (lista) -1]?
- 13. len() Vs długość danych() w sqlserver 2005
- 14. TypeError: obiekt typu 'Kursor' ma len()
- 15. Co to jest "moduł" w docstringie len?
- 16. TypeError: „int” obiekt nie jest wymagalne ,,, len()
- 17. Golang: W jaki sposób działają funkcje len() i make()?
- 18. Złożoność len() w odniesieniu do zestawów i list
- 19. Alternatywa dla 'for i in xrange (len (x))'
- 20. Nie można zaciągnąć pożyczki jako niezmiennej - String i len()
- 21. Dlaczego wiodące `+` w `j = + i + (i <0? Len: 0)` (pobrane z kodu źródłowego jQuery)
- 22. Błąd w getOctD (x, offset, len): niepoprawna cyfra ósemkowa
- 23. Dodawanie kolumny DataFrame z len() wartości innej kolumny
- 24. TypeError: obiekt typu „bool” ma len() długości sys.argv czeku
- 25. Dlaczego funkcja LEN() t-sql zignoruje końcowe spacje?
- 26. Dlaczego lista [:: - 1] nie równa się [: len (lista): - 1]?
- 27. Wykonywanie len na liście obiektu zip usuwa zip
- 28. Różnica między cleaned_data i cleaned_data.get w Django
- 29. Zalety posiadania funkcji statycznej, takiej jak len(), max() i min() nad odziedziczonymi wywołaniami metod
- 30. Różnica między unwrapObservable i()
Zobacz http://stackoverflow.com/questions/496009/is-there-any-case-where-lensomeobj-does-not-call-someobjs-len- function/497096 # 497096 –