Hallo zusammen,
ich kann mir vorstellen, dass dieses Thema oft vorkommt.
Aber folgendes: Ich komme von Java und beschäftige mich grade mit Python. Hab ich vor langer Zeit schon mal gemacht, hab's dann aber wieder aus den Augen verloren.
Und nun verstehe ich ja, warum man self benutzt, um Parameter von Objekt-Prametern zu unterscheiden (z.B. im Konstruktor).
Das ist wie this in Java.
Aber warum muss ich das Objekt selbst nochmal in der Parameterliste referenzieren?
Wenn ich in Java einen Konstruktor schreibe, dann schreib ich ja in die Parameterliste auch nicht this rein.
Danke
self
Weil Python das eben so festgelegt hat. Einen wirklichen Grund, der irgendwie zwingend wäre, gibt es nicht. Man hätte auch membern eine @ voranstellen können, oder einen . Aber man hat halt einfach festgelegt, dass das erste Argument die Instanz ist. Du kannst die auch anders nennen, aber man bleibt aus Konvention bei self.
Moin,
wenn man `self` nicht explizit angibt, wie soll dann die Methode wissen, auf welchem Objekt sie aufgerufen wurde? Zum Beispiel in diesem Beispiel:
In Java muss man `this` nicht explizit angeben, weil eine Methode „weiß“, zu welcher Klasse sie gehört. In Python weiß eine Funktion nicht mal, dass sie eine Methode ist (und auch nicht, zu welcher Klasse sie gehört; wenn man unbedingt will, kann die gleiche Funktion sogar eine Methode auf mehreren Klassen sein).
Außerdem natürlich auch “Explicit is better than implicit.”.
wenn man `self` nicht explizit angibt, wie soll dann die Methode wissen, auf welchem Objekt sie aufgerufen wurde? Zum Beispiel in diesem Beispiel:
Code: Alles auswählen
class Foo:
pass
def __init__(self):
self.x = 42
def method(self):
print(self.x)
Foo.__init__ = __init__
Foo.method = method
def main():
foo = Foo()
foo.method()
if __name__ == "__main__":
main()
Außerdem natürlich auch “Explicit is better than implicit.”.
Aber weiß die Methode auch dann nicht, zu welcher Klasse sie gehört, wenn man die Methodendefinition einrückt? So:
Code: Alles auswählen
class Foo:
pass
def __init__(self):
self.x = 42
def method(self):
print(self.x)
- __blackjack__
- User
- Beiträge: 13191
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@PyTimmi: Man könnte die Frage auch umgekehrt stellen: Warum ist das `this` bei Java einfach auf magische Weise da ohne, das man das angegeben hat? Hätten die Java-Entwickler ja auch anders lösen können.
@__deets__: Man könnte die `main()` in dem Beispiel von narpfel auch so schreiben:
*Das* stelle ich mir mit einem impliziten `this`/`self` schwierig vor wie man *das* lösen will. So etwas in der Richtung wird in Python ja auch tatsächlich manchmal gemacht, das man die ungebundene Methode verwendet, auch wenn das nicht so schön ist, weil man damit Polymorphie über Bord schmeisst. Also Beispiel so etwas wie ``map(str.upper, words)``. In diesem Fall könnte man eine „comprehension“ schreiben, aber manchmal hat man ja eine API wo man eine Rückruffunktion angeben kann und eine ungebundene Methode da prima passt.
@__deets__: Man könnte die `main()` in dem Beispiel von narpfel auch so schreiben:
Code: Alles auswählen
def main():
foo = Foo()
method(foo)
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
@__blackjack__: Das geht in Java auch (fast):
Code: Alles auswählen
import java.util.ArrayList;
public class Foo {
private final int x = 42;
private void method() {
System.out.println(this.x);
}
public static void main(String[] args) {
final var foos = new ArrayList<Foo>();
foos.add(new Foo());
foos.stream().forEach(Foo::method); // works
final var foo = new Foo();
Foo::method(foo); // compiler error, because Java is consistent.
}
}
- __blackjack__
- User
- Beiträge: 13191
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@narpfel: Naja, aber ”nur” weil es dort keine freien Funktionen gibt, sondern nur Methoden die zwingend zu einer Klasse gehören auf die das `this` sich dann bezieht. Bei Python stellt sich an so einer Stelle wo `method()` ausserhalb einer Klasse als Funktion definiert wird, was `this` beziehungsweise `self` dann sein soll.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
Nunjaaa... auch in Java und C++ wird die Instanz beim Methodenaufruf als erster Parameter übergeben. Dies erfolgt jedoch implizit, so daß ein eigenes Schlüsselwort dafür notwendig wurde, nämlich "this". In Python wurde dagegen entschieden, diese Übergabe explizit zu machen (siehe dazu auch PEP 20, Satz 2: "Explicit is better than implicit") und den Parameter per Konvention "self" zu nennen. Dies hier:__deets__ hat geschrieben: ↑Dienstag 15. Juni 2021, 17:33 Weil Python das eben so festgelegt hat. Einen wirklichen Grund, der irgendwie zwingend wäre, gibt es nicht. Man hätte auch membern eine @ voranstellen können, oder einen . Aber man hat halt einfach festgelegt, dass das erste Argument die Instanz ist. Du kannst die auch anders nennen, aber man bleibt aus Konvention bei self.
Code: Alles auswählen
class A:
def __init__(this, dingsi):
this.dingsi = dingsi
def oho(klaus):
return klaus.dingsi
if __name__ == '__main__':
a = A('uiuiui')
print(a.oho())
Diese Frage wurde in diesem Thread bereits beantwortet:Aber warum muss ich das Objekt selbst nochmal in der Parameterliste referenzieren?
https://neopythonic.blogspot.com/2008/1 ... -stay.html
Rust hat auch ein explizites self als erstes Argument bei Methoden. Allerdings mit dem Unterschied dass darüber auch geregelt wird ob es eine "Klassenmethode" (assoziierte Funktion) oder "Instanzmethode" (Methode) ist.
Rust Playground zum ausprobieren
Rust ist zugegebenermaßen deutlich jünger als Python, vielleicht war Python da auch etwas inspirierend.
Code: Alles auswählen
struct MyStruct;
impl MyStruct {
fn class_method() {
println!("Hello from class_method!");
}
fn instance_method(&self) {
println!("Hello from instance_method!")
}
}
fn main() {
MyStruct::class_method();
let my_struct = MyStruct {};
my_struct.instance_method();
// my_struct.class_method(); <- results in a "no method named class_method error"
}
Rust ist zugegebenermaßen deutlich jünger als Python, vielleicht war Python da auch etwas inspirierend.
Wenig überraschend hat man auch in der C++-Welt gesehen, dass es ein explizites `this`/`self` geben kann und es sieht so aus, als wenn das hier ab C++23 möglich sein wird:
Code: Alles auswählen
#include <print>
struct Foo final {
int x = 42;
auto method(this auto const& self) -> void {
std::println("{}", self.x);
}
};
auto main() -> int {
auto const foo = Foo{};
foo.method();
}