Podczas definiowania metody w klasie w Pythonie wygląda to mniej więcej tak:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
Ale w niektórych innych językach, takich jak C #, istnieje odwołanie do obiektu, z którym metoda jest powiązana, za pomocą słowa kluczowego „this” bez deklarowania go jako argumentu w prototypie metody.
Czy była to celowa decyzja dotycząca projektu języka w Pythonie, czy też są jakieś szczegóły implementacji, które wymagają podania „siebie” jako argumentu?
self
aby uzyskać dostęp do członków - stackoverflow.com/questions/910020/…Odpowiedzi:
Lubię cytować zen Pythona Petersa. „Wyraźne jest lepsze niż ukryte”.
W Javie i C ++
this.
można wydedukować „ ”, chyba że masz nazwy zmiennych, które uniemożliwiają wywnioskowanie. Więc czasami tego potrzebujesz, a czasami nie.Python decyduje się, aby takie rzeczy były jawne, a nie oparte na regułach.
Ponadto, ponieważ nic nie jest implikowane ani zakładane, części implementacji są ujawniane.
self.__class__
,self.__dict__
I innych „wewnętrzne” struktury dostępne są w oczywisty sposób.źródło
Ma to na celu zminimalizowanie różnicy między metodami i funkcjami. Umożliwia łatwe generowanie metod w metaklasach lub dodawanie metod w czasie wykonywania do wcześniej istniejących klas.
na przykład
>>> class C(object): ... def foo(self): ... print "Hi!" ... >>> >>> def bar(self): ... print "Bork bork bork!" ... >>> >>> c = C() >>> C.bar = bar >>> c.bar() Bork bork bork! >>> c.foo() Hi! >>>
To także (o ile wiem) ułatwia implementację środowiska uruchomieniowego Pythona.
źródło
self
deklaracji funkcji (pamiętaj, być może jest to wyrzucanie kamieni ze szklanego domu, ponieważ JavaScript ma dość skomplikowanąthis
semantykę wiązania)Proponuję przeczytać blog Guido van Rossuma na ten temat - Dlaczego jawne ja musi zostać .
źródło
Python nie zmusza cię do używania "self". Możesz nadać mu dowolną nazwę. Musisz tylko pamiętać, że pierwszy argument w nagłówku definicji metody to odwołanie do obiektu.
źródło
@staticmethod
nim nie ma.Pozwala również na to: (w skrócie, wywołanie
Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5)
zwróci 12, ale zrobi to w najbardziej szalony sposób.class Outer(object): def __init__(self, outer_num): self.outer_num = outer_num def create_inner_class(outer_self, inner_arg): class Inner(object): inner_arg = inner_arg def weird_sum_with_closure_scope(inner_self, num) return num + outer_self.outer_num + inner_arg return Inner
Oczywiście trudniej to sobie wyobrazić w językach takich jak Java i C #. Wyraźnie określając odniesienie do siebie, możesz swobodnie odwoływać się do dowolnego obiektu za pomocą tego odniesienia. Ponadto taki sposób grania z klasami w czasie wykonywania jest trudniejszy do wykonania w bardziej statycznych językach - niekoniecznie jest to dobre lub złe. Chodzi tylko o to, że jawne ja pozwala istnieć całym tym szaleństwu.
Co więcej, wyobraź sobie: Chcielibyśmy dostosować zachowanie metod (do profilowania lub jakiejś szalonej czarnej magii). Może to nas skłonić do myślenia: co by było, gdybyśmy mieli klasę,
Method
której zachowanie moglibyśmy zmienić lub kontrolować?Cóż, oto jest:
from functools import partial class MagicMethod(object): """Does black magic when called""" def __get__(self, obj, obj_type): # This binds the <other> class instance to the <innocent_self> parameter # of the method MagicMethod.invoke return partial(self.invoke, obj) def invoke(magic_self, innocent_self, *args, **kwargs): # do black magic here ... print magic_self, innocent_self, args, kwargs class InnocentClass(object): magic_method = MagicMethod()
A teraz:
InnocentClass().magic_method()
będzie działać zgodnie z oczekiwaniami. Metoda zostanie powiązana zinnocent_self
parametrem toInnocentClass
i zmagic_self
instancją MagicMethod. Dziwne co? To tak, jakby 2 słowa kluczowethis1
ithis2
w językach takich jak Java i C #. Taka magia pozwala frameworkom robić rzeczy, które w innym przypadku byłyby znacznie bardziej szczegółowe.Ponownie, nie chcę komentować etyki tych rzeczy. Chciałem tylko pokazać rzeczy, które byłyby trudniejsze do zrobienia bez wyraźnego odniesienia do siebie.
źródło
OuterClass.this
aby uzyskać „self” z klasy zewnętrznej, ale nadal możesz używać jejthis
jako odniesienia do siebie; bardzo podobne do tego, co robisz tutaj w Pythonie. Nie było mi trudniej to sobie wyobrazić. Może zależy to od biegłości w danym języku?Something
, która z kolei jest zdefiniowana w kolejnej anonimowej implementacjiSomething
? W Pythonie możesz oczywiście odwołać się do dowolnego z zakresów.this
. Niejawne odwołania są niemożliwe w Javie.this
wyniku. Na przykładObject self1 = this;
(użyj Object lub czegoś mniej ogólnego). Następnie, jeśli masz dostęp do zmiennej w wyższych zakresach, można mieć dostęp doself1
,self2
...selfn
. Myślę, że powinny one zostać uznane za ostateczne lub coś w tym rodzaju, ale może zadziałać.Myślę, że prawdziwym powodem oprócz „Zen of Python” jest to, że funkcje są obywatelami pierwszej klasy w Pythonie.
Co zasadniczo czyni je przedmiotem. Teraz podstawową kwestią jest to, że jeśli twoje funkcje również są obiektami, w jaki sposób w paradygmacie zorientowanym obiektowo wysyłasz komunikaty do obiektów, gdy same komunikaty są obiektami?
Wygląda na problem z jajami kurzymi. Aby zmniejszyć ten paradoks, jedynym możliwym sposobem jest przekazanie kontekstu wykonania do metod lub wykrycie go. Ale ponieważ Python może mieć funkcje zagnieżdżone, byłoby to niemożliwe, ponieważ kontekst wykonania zmieniłby się dla funkcji wewnętrznych.
Oznacza to, że jedynym możliwym rozwiązaniem jest jawne przekazanie „siebie” (kontekstu wykonania).
Więc uważam, że jest to problem z implementacją Zen pojawił się znacznie później.
źródło
Myślę, że ma to związek z PEP 227:
źródło
Jak wyjaśniono w self w Pythonie, Demystified
class Point(object): def __init__(self,x = 0,y = 0): self.x = x self.y = y def distance(self): """Find distance from origin""" return (self.x**2 + self.y**2) ** 0.5
Modły:
>>> p1 = Point(6,8) >>> p1.distance() 10.0
w tym () definiuje trzy parametry, ale właśnie przekazaliśmy dwa (6 i 8). Podobnie distance () wymaga podania jednego, ale nie przekazano żadnych argumentów.
Dlaczego Python nie narzeka na niezgodność numeru tego argumentu ?
źródło
Parametr „self” zachowuje bieżący obiekt wywołujący.
class class_name: class_variable def method_name(self,arg): self.var=arg obj=class_name() obj.method_name()
tutaj argument self przechowuje obiekt obj. Stąd wyrażenie self.var oznacza obj.var
źródło
Jest też inna bardzo prosta odpowiedź: zgodnie z zenem Pythona , „wyraźne jest lepsze niż niejawne”.
źródło