Wann sollte ich in Python eine Funktion anstelle einer Methode verwenden?
Den Zen of Python hinweist, dass es sollte nur eine Möglichkeit sein, Dinge zu tun - doch Häufig hatte ich das problem zu entscheiden, wenn Sie eine Funktion verwenden, versus, wenn eine Methode zu verwenden.
Nehmen wir mal ein triviales Beispiel - ein Schachbrett-Objekt. Sagen wir, wir müssen einige Weg, um alle rechtlichen König bewegt sich auf das Brett. Wir schreiben Schachbrett.get_king_moves() oder get_king_moves(chess_board)?
Hier sind einige Fragen, die ich angeschaut:
- Warum funktioniert die python verwenden 'magischen ' Methoden'?
- Gibt es einen Grund, Python-strings nicht eine Zeichenfolge, die length-Methode?
Die Antworten, die ich bekam, waren weitgehend ergebnislos:
Warum Python-Methoden benutzen, um einige Funktionen (z.B. Liste.index()) funktioniert aber auch für andere (z.B. len(Liste))?
Ist das der Hauptgrund dafür ist die Geschichte. Funktionen verwendet wurden für diese Operationen, die generisch für eine Gruppe von Arten und die waren
sollte die Arbeit auch für Objekte, die nicht über Methoden auf allen
(z.B. Tupel). Es ist auch praktisch, um eine Funktion haben kann
leicht angewendet werden, um eine amorphe Sammlung von Objekten, wenn Sie verwenden
die funktionellen Eigenschaften von Python (Karte(), apply() et al.).In der Tat, die Umsetzung der len(), max(), min() als built-in-Funktion ist tatsächlich weniger code als die Umsetzung als Methoden für jeden Typ.
Man kann Haarspalterei über einzelne Fälle, sondern es ist ein Teil von Python und
es ist zu spät, um derart grundlegende Veränderungen, die jetzt. Die Funktionen haben
zu bleiben, zu vermeiden, riesige code Bruch.
Während interessant, die oben nicht wirklich viel sagen, welche Strategie zu verabschieden.
Dies ist einer der Gründe - mit benutzerdefinierten Methoden, die Entwickler wäre
frei zu wählen, eine andere Methode name, wie getLength(), length(),
getlength() oder was auch immer. Python erzwingt strenge benennen, so dass die
gemeinsame Funktion len() kann verwendet werden.
Etwas interessanter. Mein nehmen ist, dass die Funktionen werden in einem Sinn, der Pythonic version von Schnittstellen.
Schließlich von Guido selbst:
Reden über die Fähigkeiten/Schnittstellen hat mich zum nachdenken über einige unserer
"rogue" spezielle Methode Namen. In der Sprachreferenz, es sagt, "Ein
Klasse umsetzen können bestimmte Operationen, die aufgerufen werden, indem spezielle
syntax (wie z.B. arithmetische Operationen oder subscripting und schneiden) von
die Definition von Methoden mit speziellen Namen." Aber es gibt alle diese Methoden, die
mit speziellen Namen wie__len__
oder__unicode__
die zu sein scheinen
zur Verfügung gestellt für den nutzen von eingebauten Funktionen, als zum
Unterstützung der syntax. Vermutlich in einer interface-basierten Python, diese
Methoden erweisen würden, in regelmäßigen Abständen, benannten Methoden, die auf einer ABC, so dass
__len__
werden würdeclass container: ... def len(self): raise NotImplemented
Obwohl, denken Sie darüber etwas mehr, ich sehe nicht ein, warum alle syntaktische
Operationen würden nicht nur aufrufen, die entsprechende Regel-Methode mit dem Namen
auf eine bestimmte ABC. "<
", zum Beispiel, würde vermutlich aufrufen
"object.lessthan
" (oder vielleicht "comparable.lessthan
"). Also eine andere
Vorteil wäre die Fähigkeit zu entwöhnen Python-Weg von diesem
mangled-name Ungereimtheit, und das scheint mir ein HCI-Verbesserung.Hm. Ich bin mir nicht sicher, ob ich einverstanden (Abbildung aus :-).
Gibt es zwei Teile von "Python Begründung" das würde ich gerne erklären
erste.Erste von allen, die ich wählte, len(x) über x.len() für die HCI Gründen (
def
kam erst viel später). Es sind zwei Ineinander verschlungenen Gründen eigentlich beide HCI:
__len__()(a) Für einige Operationen, die Präfix-notation, nur liest sich besser als
postfix -- prefix (und infix!) Operationen haben eine lange tradition in der
Mathematik, die mag Notationen, wo die visuals helfen, die
Mathematiker denken über ein problem. Vergleichen Sie das einfach mit, die wir
umschreiben einer Formel, wiex*(a+b)
inx*a + x*b
auf die Ungeschicklichkeit des
tun die gleiche Sache mit einem raw-OO-notation.(b), Wenn ich Lesen Sie code, der sagt
len(x)
ich wissendass es zu Fragen für
die Länge von etwas. Das sagt mir zwei Dinge: das Ergebnis ist ein
integer, und das argument ist eine Art von container. Im Gegenteil,
wenn ich lesex.len()
, ich muss schon wissen, dassx
ist eine Art von
container-Implementierung einer Schnittstelle oder Erben von einer Klasse, die
hat eine standard -len()
. Zeugen der Verwirrung, die wir gelegentlich haben, wenn
eine Klasse, die nicht die Implementierung eines mapping hat eineget()
oderkeys()
Methode, oder etwas, das nicht eine Datei hat einewrite()
Methode.Sagen, die gleiche Sache in einer anderen Weise, ich seh 'len' als built-in
Betrieb. Ich würde es hassen, zu verlieren. Ich kann nicht sicher sagen, ob man gemeint ist oder nicht, aber 'def len(self): ...' klingt wie Sie
möchten herabstufen es um eine gewöhnliche Methode. Ich bin stark -1.Das zweite bit von Python Begründung, die ich versprochen zu erklären, ist nicht der Grund
warum entschied ich mich für die speziellen Methoden zu suchen__special__
und nicht nur
special
. Ich war Antizipation viele Operationen, die Klassen könnten wollen
zu überschreiben, einige Standards (z.B.__add__
oder__getitem__
), manche nicht so
standard (z.B. Gurke ist__reduce__
für eine lange Zeit hatte keine Unterstützung in C
code). Ich wollte nicht, dass diese speziellen Operationen zu verwenden gewöhnlichen
Methodennamen, weil dann bereits vorhandenen Klassen oder Klassen die schriftliche durch
Benutzer ohne ein enzyklopädisches Gedächtnis für alle speziellen Methoden,
haftet versehentlich Vorgänge zu definieren, die Sie nicht bedeuten, zu
implementieren, mit möglicherweise katastrophalen Folgen. Ivan Krstić
das erklärt mehr prägnant in seiner Botschaft, die ankam, nachdem ich
dies alles geschrieben.--
--Guido van Rossum (Homepage: http://www.python.org/~guido/)
Mein Verständnis davon ist, dass in bestimmten Fällen, die Präfix-notation macht einfach mehr Sinn (ie, Ente.quack macht mehr Sinn als quack(Ente) aus linguistischer Sicht.) und wieder werden die Funktionen "Schnittstellen".
In diesem Fall, meine Vermutung wäre die Umsetzung get_king_moves ausschließlich auf Basis der Guido ist der erste Punkt. Aber das lässt immer noch eine Menge offene Fragen zu sagen, die Implementierung einer stack-und queue-Klasse mit ähnlichen push und pop Methoden - sollten diese Funktionen oder Methoden? (hier würde ich vermuten-Funktionen, weil ich wirklich wollen, um zu signalisieren push-pop-Schnittstelle)
TLDR: Kann jemand erklären, was die Strategie für die Entscheidung, Wann Funktionen vs. Methoden sollten?
InformationsquelleAutor der Frage Ceasar Bautista | 2011-11-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
Meine Allgemeine Regel lautet - ist die operation, die auf das Objekt oder durch das Objekt?
wenn es durch das Objekt, sollte es einem Mitglied-Betrieb. Wenn, könnte es für andere Sachen auch, oder ist getan, indem Sie etwas anderes auf das Objekt, dann sollte es eine Funktion (oder vielleicht ein Mitglied von etwas anderem).
Als Einführung in die Programmierung, es ist traditionell (wenn auch die Umsetzung falsch), um Objekte zu beschreiben in Bezug auf die Gegenstände der realen Welt wie Autos. Sie erwähnen eine Ente, also gehen wir mit.
Im Rahmen der "Objekte sind Reale Dinge" - Analogie, es ist der "richtige" ist, um eine Klasse Methode für alles, was das Objekt tun kann. So sagen, ich will töten, Ente, füge ich ein
.kill (), um die Ente? Nein... soweit ich weiß, Tiere nicht Selbstmord Begehen. Also wenn ich will, zu töten, eine Ente sollte ich dies tun:
Weg von dieser Analogie, warum verwenden wir Methoden und Klassen? Denn wir wollen die Daten enthalten, und hoffentlich strukturieren den code in einer solchen Weise, dass es wiederverwendbar und erweiterbar in der Zukunft. Dies bringt uns zu dem Begriff der Kapselung, die so lieb OO-design.
Kapselung der wichtigsten ist wirklich, was das kommt darauf an: als designer sollten Sie sich verstecken, alles über die Durchführung und die Klasse Einbauten, die es nicht absolut notwendig für jeden Anwender oder Entwickler-Zugang. Weil wir mit Instanzen von Klassen, diese reduziert sich auf "Vorgänge von entscheidender Bedeutung auf dieser Instanz". Wenn eine operation ist nicht Instanz-spezifisch, dann sollte es nicht sein, eine member-Funktion.
TL;DR:
was @Bryan sagte. Wenn es operiert auf einer Instanz und der Zugriff auf Daten, die intern die Klasse, Instanz, sollte es eine member-Funktion.
InformationsquelleAutor der Antwort arrdem
Eine Klasse verwenden, wenn Sie möchten:
1) Isolieren Sie den Aufruf-code von der Umsetzung der details-nutzen Abstraktion und Kapselung.
2) Wenn Sie möchten, werden substituierbaren für andere Objekte -- nutzen Polymorphie.
3) Wenn Sie möchten, um die Wiederverwendung von code, die für ähnliche Objekte -- nutzen Vererbung.
Verwenden eine Funktion für Anrufe, die Sinn machen über viele verschiedene Objekt-Typen-zum Beispiel das eingebaute len und repr Funktionen gelten für viele Arten von Objekten.
That being said, ist die Wahl manchmal kommt unten zu einer Angelegenheit des Geschmacks. Denken Sie in Bezug auf das, was am bequemsten ist und lesbar für typische Aufrufe. Zum Beispiel, was wäre dann besser
(x.sin()**2 + y.cos()**2).sqrt()
odersqrt(sin(x)**2 + cos(y)**2)
?InformationsquelleAutor der Antwort Raymond Hettinger
Ist hier eine einfache Faustregel: wenn der code wirkt auf eine einzelne Instanz eines Objekts, eine Methode verwenden. Noch besser: verwenden Sie eine Methode, es sei denn, es gibt einen zwingenden Grund, es zu schreiben, als eine Funktion.
In Ihrem konkreten Beispiel, Sie wollen es so Aussehen:
Nicht über ihn denken. Verwenden Sie immer Methoden bis zu dem Punkt kommt, wo Sie zu sich selbst sagen: "es macht keinen Sinn, um diese eine Methode", in diesem Fall können Sie eine Funktion.
InformationsquelleAutor der Antwort Bryan Oakley
Denke ich gewöhnlich an ein Objekt wie eine person.
Attribute sind die person, die name, Größe, Schuhgröße, etc.
Methoden und Funktionen sind Operationen, die die person ausführen kann.
Wenn die operation konnte durchgeführt werden durch irgendein ol' person, ohne dass etwas einzigartiges auf diese eine bestimmte person (und ohne etwas zu ändern auf dieser eine bestimmte person), dann ist es ein Funktion und sollte so geschrieben werden, als solche.
Wenn eine operation ist die auf die person (z.B. Essen, gehen, ...) oder erfordert etwas einzigartiges zu dieser person, sich zu engagieren (wie tanzen, ein Buch zu schreiben, ...), dann sollte es ein Methode.
Natürlich ist es nicht immer trivial zu und übersetzt diese in das jeweilige Objekt, mit dem Sie arbeiten, aber ich finde es ist ein guter Weg, um daran zu denken.
InformationsquelleAutor der Antwort Thriveth
Generell halte ich die Verwendung von Klassen zu implementieren, die einen logischen Satz von Funktionen für einige Sacheso dass der rest von meinem Programm, ich kann die Vernunft über die Sachenicht zu müssen, sorgen über all die kleinen sorgen, dass seine Umsetzung.
Alles, was Teil der Kern-Abstraktion von "was Sie tun können, mit einem Sache" sollte in der Regel eine Methode. Dies umfasst in der Regel alles ändern können, auf eine Sachewie die interne Daten-Zustand ist in der Regel als private und nicht Teil der logischen Idee ", was Sie tun können, mit einem Sache".
Wenn Sie kommen, um höhere level-Operationen, vor allem, wenn Sie mit mehreren Dingeich finde Sie sind in der Regel die meisten natürlich, ausgedrückt als Funktionen,, wenn Sie gebaut werden kann, aus der öffentlichen Abstraktion eines Sache ohne Zugriff auf die Interna (es sei denn, Sie sind Methoden eines anderen Objekts). Das hat den großen Vorteil, dass, wenn ich entscheide, Sie komplett neu schreiben die Interna, wie mein Sache arbeiten (ohne Veränderung der Oberfläche), ich habe nur eine kleine Kerngruppe der Methoden neu zu schreiben, und dann alle externen Funktionen, die in Bezug auf diese Methoden wird Nur die Arbeit. Ich finde, die darauf bestehen, dass alle Operationen zu tun mit der Klasse X werden die Methoden der Klasse X führt zu über-kompliziert Klassen.
Kommt es auf den code, den ich Schreibe, obwohl. Für einige Programme, die ich modellieren Sie Sie als eine Sammlung von Objekten, deren Interaktionen Anlass, um das Verhalten des Programms; hier werden die meisten wichtigen Funktionen ist eng gekoppelt an ein einzelnes Objekt, und so ist implementiert Methoden, mit einer Streuung von utility-Funktionen. Für andere Programme der wichtigsten Sachen ist ein Satz von Funktionen, die Daten manipulieren, und die Kurse werden nur zu implementieren, die natürlichen "duck-Typen", die manipuliert werden durch die Funktionen.
InformationsquelleAutor der Antwort Ben
Können Sie sagen, dass, "im Angesicht der Ungewissheit, weigern, der Versuchung zu erraten".
Jedoch ist es nicht sogar eine Vermutung. Sind Sie absolut sicher, dass die Ergebnisse beider Ansätze sind sich darin gleich, dass Sie Ihr problem lösen.
Ich glaube, es ist nur eine gute Sache, die Sie haben mehrere Möglichkeiten zur Erfüllung Ihrer Ziele. Ich würde demütig sagen Sie, wie andere Nutzer schon getan, zu beschäftigen, welche "besser schmeckt" /fühlt sich mehr intuitivein Bezug auf die Sprache.
InformationsquelleAutor der Antwort João Silva