Domanda

So che python ha una funzione len () che viene utilizzata per determinare la dimensione di una stringa, ma mi chiedevo perché non fosse un metodo dell'oggetto stringa.

Aggiorna

Ok, mi sono reso conto di essermi sbagliato in modo imbarazzante. __len __ () è in realtà un metodo di un oggetto stringa. Sembra strano vedere il codice orientato agli oggetti in Python usando la funzione len sugli oggetti stringa. Inoltre, è anche strano vedere __len__ come il nome anziché solo len.

È stato utile?

Soluzione

Le stringhe hanno un metodo di lunghezza: __len__()

Il protocollo in Python è di implementare questo metodo su oggetti che hanno una lunghezza e usano il len () , che la chiama per te, in modo simile al modo in cui implementeresti __iter __ () e usa la funzione iter () integrata (o utilizza il metodo dietro le quinte per te) su oggetti iterabili.

Vedi Emulazione dei tipi di contenitori per ulteriori informazioni.

Ecco una buona lettura sull'argomento dei protocolli in Python: Python e il principio del minimo stupore

Altri suggerimenti

La risposta di Jim a questa domanda può aiutare; Lo copio qui. Citando Guido van Rossum:

  

Prima di tutto, ho scelto len (x) su x.len () per motivi di HCI (def __len __ () è venuto molto più tardi). In realtà ci sono due motivi intrecciati, entrambi HCI:

     

(a) Per alcune operazioni, la notazione con prefisso è semplicemente migliore di postfisso & # 8212; le operazioni con prefisso (e infisso!) hanno una lunga tradizione in matematica a cui piacciono le notazioni in cui la grafica aiuta il matematico a pensare a un problema. Confronta la facilità con cui riscriviamo una formula come x * (a + b) in x a + x b alla goffaggine di fare la stessa cosa usando una notazione OO grezza.

     

(b) Quando leggo il codice che dice len (x) so che sta chiedendo la lunghezza di qualcosa. Questo mi dice due cose: il risultato è un numero intero e l'argomento è una specie di contenitore. Al contrario, quando leggo x.len (), devo già sapere che x è un tipo di contenitore che implementa un'interfaccia o eredita da una classe che ha un standard len (). Prova la confusione che occasionalmente abbiamo quando una classe che non implementa una mappatura ha un metodo get () o keys (), o qualcosa che non è un file ha un metodo write ().

     

Dicendo la stessa cosa in un altro modo, vedo & # 8216; len & # 8216; come operazione integrata. Non odio perderlo. / & # 8230; /

Esiste un metodo len :

>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>

Python è un linguaggio di programmazione pragmatico e le ragioni per cui len () è una funzione e non un metodo di str , list , dict ecc. sono pragmatici.

La funzione integrata len () si occupa direttamente dei tipi predefiniti: l'implementazione CPython di len () restituisce effettivamente il valore di ob_size nel PyVarObject C struct che rappresenta qualsiasi oggetto incorporato di dimensioni variabili in memoria. Questo è molto più veloce rispetto alla chiamata di un metodo: non deve avvenire la ricerca degli attributi. Ottenere il numero di elementi in una raccolta è un'operazione comune e deve funzionare in modo efficiente per tipi di base e diversi come str , list , array.array ecc.

Tuttavia, per promuovere la coerenza, quando si applica len (o) a un tipo definito dall'utente, Python chiama o .__ len __ () come fallback. __len__ , __abs__ e tutti gli altri metodi speciali documentati nel Python Data Model semplifica la creazione di oggetti che si comportano come gli incorporati, consentendo le API espressive e altamente coerenti che chiamiamo "Pythonic".

Implementando metodi speciali i tuoi oggetti possono supportare l'iterazione, sovraccaricare gli operatori di infissi, gestire i contesti in con blocchi ecc. Puoi pensare al modello di dati come un modo di usare lo stesso linguaggio Python come framework in cui gli oggetti creati possono essere integrati senza problemi.

Un secondo motivo, supportato da citazioni di Guido van Rossum come questo , è che è più facile leggere e scrivere len (s) rispetto a s.len () .

La notazione len (s) è coerente con gli operatori unari con notazione prefisso, come abs (n) . len () è usato molto più spesso di abs () e merita di essere facile da scrivere.

Potrebbe esserci anche un motivo storico: nel linguaggio ABC che ha preceduto Python (ed è stato molto influente nel suo design), c'era un operatore unario scritto come #s che significava len (s) .

met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.

Ci sono delle ottime risposte qui, e quindi prima di dare la mia vorrei evidenziare alcune delle gemme (nessun gioco di rubini previsto) che ho letto qui.

  • Python non è un linguaggio OOP puro: è un linguaggio multi-paradigma per scopi generici che consente al programmatore di utilizzare il paradigma con cui si trova più a suo agio e / o il paradigma più adatto alla propria soluzione.
  • Python ha funzioni di prima classe, quindi len è in realtà un oggetto. Ruby, d'altra parte, non ha funzioni di prima classe. Quindi l'oggetto funzione len ha i suoi metodi che puoi esaminare eseguendo dir (len) .

Se non ti piace il modo in cui funziona nel tuo codice, è banale implementare nuovamente i contenitori usando il tuo metodo preferito (vedi esempio sotto).

>>> class List(list):
...     def len(self):
...         return len(self)
...
>>> class Dict(dict):
...     def len(self):
...         return len(self)
...
>>> class Tuple(tuple):
...     def len(self):
...         return len(self)
...
>>> class Set(set):
...     def len(self):
...         return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
...     print container.len()
...
15
2
15
15

Puoi anche dire

>> x = 'test'
>> len(x)
4

Uso di Python 2.7.3.

Non è così?

>>> "abc".__len__()
3
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top