Cytat(qqrq @ 10.09.2007, 15:55:04 )

A ja się chciałem Szanownych Kolegów spytać - co to za magia z z tą całą pełną obiektowością ("wszystko jest obiektem")? Przy rozbudowanych programach/aplikacjach jest to rzecz b. przydatna, fakt, ale jak ktoś chce to może to sobie w PHP zaimplementować i tak. No a przy małych programikach? Ładniej (i bardziej przejrzysto, co ważniejsze) wygląda te 15 linijek pisanych strukturalnie, a nie klasa, prawda?
Wiesz, czym jest pełna obiektowość? Wprowadzeniem niech będzie: ani Java, ani PHP ani nawet C++ nie są językami w pełni obiektowymi. Czemu? Bo nie wszystko w nich jest obiektem.
A jak to jest w Pythonie? W Pythonie *wszystko* jest obiektem. W Pythonie każda operacja jest operacją na obiekcie.
Tzn. jest sobie system obiektowy, a Python to tylko system zarządzania tymi objetami. Język który je oraz interakcje między nimi definiuje.
Np.
Kod
a = 1 + 1
Tłumaczone jest do:
Kod
a = 1.__add__(1) # 1 jest obiektem typu types.IntType
W powyższym przykładzie a to tylko nazwa referencji do obiektu.
W Javie np. przykładowa klasa:
Kod
class Abc {}
I teraz Abc nie jest obiektem, a klasą. Natomiast Abc.class jest obiektem reprezentującym klasę, czy jakoś tak. I teraz swoją drogą jak w ogóle Abc może posiadać atrybut class skoro nie jest obiektem?
W Pythonie każda klasa jest obiektem. A raczej definicja klasy to nic innego jak zdefiniowanie referencji o pewnej nazwie do obiektu klasy. Dalej idąc, funkcje, czy raczej obiekty wykonywalne też są obiektami. Tego nie ma ani w Javie ani w PHP. Pomimo, że istnieje klasa Method w Javie, nie reprezentuje ona wykonywalnej metody, a jedynie ją obudowuje.
Rozważ np,
Kod
a = 1
b = "str"
class c:
pass
def d():
pass
e = c()
W powyższym przykładzie a,b,c,d oraz e to dokładnie to samo: referencje do obiektów. I pomimo, że niektóre obiekty można tworzyć inaczej niż poprzez Name(*args, **kwargs), to są to tylko skróty interpretera.
Każda funkcja zwraca jakiś obiekt, każda referencja odnosi się do jakiegoś obiektu. I tak np. możesz wykonywać operacje na obiektach zwróconych przez jakieś funkcje referencje.
Rozważ ten przykład z PHP.
<?php
class Cba {
public $a = 1;
}
class Abc {
public function getCba() { return new Cba();}
}
// i w ten sposób całkiem poprawne będzie napisanie:
echo new Abc
()->getCba()->a; // ale jakby getCba zwracało funkcje, czego swoją drogą w PHP nie da się zrobić, nie ma możliwości zrobienia:
//new Abc()->getCba()();
?>
Tymsamym, jak widizisz nie wszystko jest obiektem, a wartości są dużo bardziej powiązane ze zmiennymi niż teoretycznie powinny. W Pythonie jest dokładnie na odwrót. Rozważ ten przykład
Kod
def abc():
def bca():
return 1
return bca
// następujące wywołanie jest całkiem poprawne spowoduje wypisanie jedynki. Czemu? Bo abc() zwraca referencje do obiekty wykonywalnygo, a drugi zestaw nawiasów powoduje, że interpreter go wywołuje
print abc()()
// w rzeczywistości następuje takie oto wywołanie (pomijam, na co jest tłumaczony print)
print abc.__call__().__call__()
Teraz co do klas jeszcze. Jak powstają atrybuty klas? Nie inaczej, jak poprzez umieszczenie referencji do ich obiektów w tzw. słowniku klasy. Każda klasa ma atrybut __dict__, który jest słownikiem przechowującym jej atrybuty. Oczywiście __dict__ jest jakąś tam specjalną nazwą i nie znajduje się sam w sobie. A czym są metody? Metody klas to nic innego jak obiekty wykonywalne do których referencje przechowywane są w słowniku klasy... Tzn., że pomiędzy atrybutami nie ma żadnej różnicy ze strony klasy. Różnią się one tylko między sobą swoim typem.
I tak np. kolejne tłumaczenie
Kod
class A:
def b(self):
pass
anA = A()
anA.b()
// jest tłumaczone na
anA = A.__new__()
anA.__dict__["__init__"].__call__(anA)
anA.__dict__["b"].__call__(anA)
Mam nadzieje, że było to zrozumiałe i pouczające.
Pozdrawiam
Adam
PS. Mam wrażenie, że gdzieś już o tym pisałem