Strona główna Polish Python Coders Group
   Strona główna   Pomoc Zaloguj się Rejestracja  
Witamy, Gość. Zaloguj się lub zarejestruj.
Czy dotarł do Ciebie email aktywacyjny?

Zaloguj się podając nazwę użytkownika, hasło i długość sesji

Aktualności:
Szukaj Szukaj
Strony: [1] 2   Do dołu
Drukuj
Wątek: Metody i atrybuty klas - a metody i atrybuty instancji  (Przeczytany 66695 razy)
« : 01:14 09/07/09 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


Temat pojawia się co pewien czas w postach początkujących, dziś ktoś mnie o to pytał na privie - może więc warto objaśnić rzecz raz a dobrze ,,prostym żołnierskim językiem'', na prostych przykładach i bez teoretyzowania. (Być może moderatorzy uznają, że warto ten wątek ,,przykleić'' u góry, nie obrażę się :)).

[Celowo w przykładach kodu podaję definicje klas bez pustych wierszy między definicjami metod - dzięki temu przykłady te można łatwiej przekopiowywać do Pythona uruchomionego w trybie interaktywnym]

1. Wstęp: klasy i instancje klas
Tak tworzymy klasę...

Kod
class MojaKlasa:
   pass  # (pass czyli "nic nie rób" - ta klasa jest całkiem pusta)

...a jeżeli używamy Pythona w wersji 2.x (a nie 3.x), to lepiej tak:

Kod
class MojaKlasa(object):
   pass  # (pass czyli "nic nie rób" - ta klasa jest całkiem pusta)

(patrz też punkt 6.)

Tak tworzymy poszczególne instancje tejże klasy:

Kod
instancja = MojaKlasa()
inna_instancja = MojaKlasa()
kolejna_instancja = MojaKlasa()

Po co nam klasy i instancje? Prosty przykład: jeżeli klasa odpowiada pewnemu typowi dokumentu - np. Faktura - to jej instancje odpowiadają konkretnym dokumentom - np. faktura 77/2012 wystawiona firmie Chlupociński i Synowie na 120 zł...

Cechy wspólne dla wszystkich faktur (że każda ma numer, dane kontrahenta, kwotę w złotówkach itp., że każdą można wystawić, rozliczyć, oznaczyć jako przeterminowaną itp.) ustalone są w klasie. Natomiast to, co jest cechą konkretnej faktury (że ma np. numer 2/2011, wystawiona jest na pana Piptasińskiego, na kwotę 13 zł, i że w danym momencie jest wystawiona ale nierozliczona itp.), ustawione jest w instancji.


2. Atrybuty
W Pythonie wszelkie dane są obiektami. I do prawie każdego obiektu - w tym również do klasy lub do instancji - możemy dodawać atrybuty (czyli zmienne składowe) dowolnych typów:

Kod
MojaKlasa.atrybut_klasy = ['a', 'b', 'c', True, False]
instancja.atrybut_instancji = (6, 7, 8)
inna_instancja.atrybut_instancji = "tralala"

Atrybuty można też pobierać i coś z nimi dalej robić (np. w poniższym przykładzie wypisujemy je za pomocą print):

Kod
print MojaKlasa.atrybut_klasy  # -> ['a', 'b', 'c', True, False]
print instancja.atrybut_instancji  # -> (6, 7, 8)
print inna_instancja.atrybut_instancji  # -> tralala
print kolejna_instancja.atrybut_instancji  # błąd AttributeError - nie ma takiego atrybutu

Zauważmy, że atrybut klasy można pobrać (ale nie ustawić) również poprzez jej instancję:

Kod
print kolejna_instancja.atrybut_klasy  # -> ['a', 'b', 'c', True, False]
print instancja.atrybut_klasy  # -> ['a', 'b', 'c', True, False]
# ale oczywiście nie tak:
print MojaKlasa.atrybut_instancji  # błąd AttributeError - nie ma takiego atrybutu

Atrybuty można też usuwać:

Kod
del MojaKlasa.atrybut_klasy
print MojaKlasa.atrybut_klasy  # błąd AttributeError - nie ma takiego atrybutu
print instancja.atrybut_klasy  # błąd AttributeError - nie ma takiego atrybutu
 
del instancja.atrybut_instancji
print instancja.atrybut_instancji  # błąd AttributeError - nie ma takiego atrybutu
print inna_instancja.atrybut_instancji  # -> tralala

Następny przykład pokazuje, że atrybut klasy można dla danej instancji ,,zakryć'' (przesłonić) atrybutem instancji - co nie znaczy usunąć:

Kod
MojaKlasa.jakis_atrybut = (1, 2, 5)
print MojaKlasa.jakis_atrybut  # -> (1, 2, 5)
print instancja.jakis_atrybut  # -> (1, 2, 5)
 
instancja.jakis_atrybut = [9, 8, 7, 6]              # <- przesłaniamy
print MojaKlasa.jakis_atrybut  # -> (1, 2, 5)
print instancja.jakis_atrybut  # -> [9, 8, 7, 6]
 
del instancja.jakis_atrybut                              # <- odsłaniamy
print MojaKlasa.jakis_atrybut  # -> (1, 2, 5)
print instancja.jakis_atrybut  # -> (1, 2, 5)

I jeszcze jedna sprawa - dotyczy atrybutów klasy: zamiast najpierw tworzyć klasę, a potem dodawać do niej atrybuty - możemy umieścić je od razu w definicji klasy (i tak się zwykle robi dla wygody i czytelności):

Kod
class MojaKlasa(object):
   atrybut_klasy = 444
   inny_atrybut_klasy = [1, 3, 5, 4, 2]
   jeszcze_inny = 'blablabla'
   def atrybut_klasy_bedacy_funkcja(self):  # (czyli metoda)
       print self

3. Metody
Przy wywoływaniu metody - czyli funkcji będącej atrybutem klasy, pobranej z instancji lub z klasy - pierwszym argumentem tejże metody musi być instancja klasy (są od tej zasady wyjątki, ale tym razem nie będziemy się nimi zajmować).

UWAGA: W typowej sytuacji czyli gdy wywołujemy metodę pobraną z instancji, ten pierwszy argument pomijamy - użyta instancja jest pod niego podstawiana automatycznie (patrz: ostatnia linijka poniższego listingu).

Kod
class MojaKlasa(object):
   def metoda(argument, drugi_argument):
       print "Oto:", argument, drugi_argument
 
instancja = MojaKlasa()  # tworzymy instancję
 
# błędne wywołanie metody pobieranej z klasy:
MojaKlasa.metoda('tralala', 'hophop')  # błąd (w Pythonie 2.x powodujący wyjątek TypeError) - pierwszym argumentem metody powinna być instancja klasy MojaKlasa
 
# prawidłowe wywołanie tej samej metody, pobieranej z klasy:
MojaKlasa.metoda(instancja, 'cip-cip')  # -> Oto: <__main__.MojaKlasa instance at 0x..........> cip-cip
 
# prawidłowe wywołanie tej samej metody, pobieranej z instancji:
instancja.metoda('cip-cip')  # -> Oto: <__main__.MojaKlasa instance at 0x..........> cip-cip

(Zauważmy, że dwa ostatnie wywołania w powyższym przykładzie są równoznaczne).

Jest zwyczaj (niebędący formalnym wymogiem Pythona), by wewnątrz definicji metody ten pierwszy argument - pod który podstawiana jest instancja - nazywać self (co po angielsku znaczy z grubsza: "własne ja", "ja sam(a)" itp.). Zgodnie z tą konwencją definicja naszej przykładowej klasy powinna wyglądać tak:

Kod
class MojaKlasa(object):
   def metoda(self, drugi_argument):
       print "Oto:", self, drugi_argument

4. Metoda specjalna __init__()
W Pythonie mamy zestaw metod, które posiadają specjalne znaczenie (ich nazwy zaczynają się i kończą dwoma znakami podkreślenia - nie powinno się samemu wprowadzać nowych nazw skonstruowanych w ten sposób).

Najczęściej stosowaną metodą specjalną jest __init__(). Metoda ta wywoływana jest automatycznie zaraz po utworzeniu nowej instancji - jest więc ona dobrym miejscem na ustawienie artybutów instancji, których będziemy używać:

Kod
class Samochod(object):
   kolejny_nr_seryjny = 1  # atrybut klasy
   def __init__(self):  # self to nowo utworzona instancja
       # ustawiamy atrybuty instancji (teraz widzimy, po co nam self)
       self.predkosc = 0
       self.nr_seryjny = self.kolejny_nr_seryjny  # używamy atrybutu klasy "kolejny_nr_seryjny"
       # zwiększamy wartość atrybutu klasy "kolejny_nr_seryjny"
       self.__class__.kolejny_nr_seryjny = self.kolejny_nr_seryjny + 1
       # (^ mamy tu operację przypisania, dlatego dobieramy się
       #  do atrybutu poprzez klasę - by przypisać wartość atrybutowi
       #  klasy, a *nie* przesłonić atrybut klasy atrybutem instancji
       #  o identycznej nazwie)
       print 'nr', self.nr_seryjny
   def wypisz_predkosc(self):
       print 'nr', self.nr_seryjny, '- predkosc:', self.predkosc, 'km/h'
   def dodaj_gazu(self, o_ile):
       self.predkosc += o_ile
       self.wypisz_predkosc()
   def hamuj(self, o_ile):
       self.predkosc -= o_ile
       self.wypisz_predkosc()
 
s1 = Samochod()  # -> nr 1
s2 = Samochod()  # -> nr 2
s1.dodaj_gazu(50)  # -> nr 1 - predkosc: 50 km/h
s2.dodaj_gazu(30)  # -> nr 2 - predkosc: 30 km/h
s1.hamuj(28)  # -> nr 1 - predkosc: 22 km/h
s2.hamuj(28)  # -> nr 2 - predkosc: 2 km/h
 
Samochod.kolejny_nr_seryjny = 100
s3 = Samochod()  # -> nr 100
Samochod.kolejny_nr_seryjny = 0
s4 = Samochod()  # -> nr 0

Metoda __init__() nazywana bywa konstruktorem (nie do końca słusznie, bo w momencie jej wykonywania instancja klasy już istnieje).

Do metody __init__() trafiają ewentualne argumenty podane przy tworzeniu instancji:

Kod
class NazwanyKolorowy(object):
   def __init__(self, nazwa, kolor):
       self.nazwa = nazwa
       self.kolor = kolor
 
nk1 = NazwanyKolorowy('Fiat', 'zielony')
nk2 = NazwanyKolorowy('Suzuki', 'czerwony')
print nk1.nazwa, nk1.kolor  # -> Fiat zielony
print nk2.nazwa, nk2.kolor  # -> Suzuki czerwony

5. Dziedziczenie
Często potrzebujemy zdefiniować kilka klas, które posiadają pewne wspólne cechy. Tu przydatne jest dziedziczenie - zobaczmy to na przykładach wykorzystujących 2 ostatnie klasy z poprzednich przykładów:

Kod
class NazwanyKolorowyDlugi(NazwanyKolorowy):  # <- nowa klasa będzie dziedziczyć z klasy NazwanyKolorowy
   def __init__(self, nazwa, kolor, dlugosc):
       NazwanyKolorowy.__init__(self, nazwa, kolor)  # używamy konstruktora klasy podstawowej
       self.dlugosc = dlugosc # i dodajemy nowe cechy
 
nkd = NazwanyKolorowyDlugi('Porshe', 'srebrny', 3.5)
print nkd.nazwa, nkd.kolor, nkd.dlugosc  # -> Porshe srebrny 3.5

Jak widzimy, to co jest dziedziczone to atrybuty klas.

Dziedziczona jest też ,,klasowa tożsamość'' - dzięki czemu np. wbudowana funkcja isinstance() (służąca do sprawdzania czy dany obiekt jest instancją danej klasy) traktuje instancję klasy dziedziczącej (zwanej też podklasą lub klasą pochodną) również jako instancję klasy podstawowej (bazowej):

Kod
print isinstance(nkd, NazwanyKolorowyDlugi)  # -> True
print isinstance(nkd, NazwanyKolorowy)  # -> True
# ale:
print isinstance(nk1, NazwanyKolorowyDlugi)  # -> False
print isinstance(nk1, NazwanyKolorowy)  # -> True

W Pythonie klasa może dziedziczyć z więcej niż jednej klasy:

Kod
class SamochodNKD(Samochod, NazwanyKolorowyDlugi):
   def __init__(self, nazwa, kolor, dlugosc):
       Samochod.__init__(self)
       NazwanyKolorowyDlugi.__init__(self, nazwa, kolor, dlugosc)
   def wypisz_predkosc(self):
       print self.kolor, self.nazwa, '(dlugosc:', self.dlugosc, 'm) -',
       Samochod.wypisz_predkosc(self)
 
s1 = SamochodNKD('Fiat', 'zolty', 3)  # -> nr 1
s2 = SamochodNKD('Mercedes', 'bialy', 5)  # -> nr 2
s3 = SamochodNKD('Wolga', 'czarna', 4.5)  # -> nr 3
 
s1.dodaj_gazu(100)  # -> zolty Fiat (dlugosc: 3 m) - nr 1 - predkosc: 100 km/h
s2.dodaj_gazu(60)  # -> bialy Mercedes (dlugosc: 5 m) - nr 2 - predkosc: 60 km/h
s3.dodaj_gazu(30)  # -> czarna Wolga (dlugosc: 4.5 m) - nr 3 - predkosc: 30 km/h
 
s1.hamuj(45)  # -> zolty Fiat (dlugosc: 3 m) - nr 1 - predkosc: 55 km/h
s2.dodaj_gazu(23)  # -> bialy Mercedes (dlugosc: 5 m) - nr 2 - predkosc: 83 km/h
s3.dodaj_gazu(31)  # -> czarna Wolga (dlugosc: 4.5 m) - nr 3 - predkosc: 61 km/h

6. Klasy w starym i w nowym stylu
W Pythonie 2.x (od wersji 2.2) na ogół lepiej unikać definiowania klas, które z niczego nie dziedziczą (i dziedziczenia z takich klas). Jeżeli chcemy stworzyć klasę "od zera", każmy jej dziedziczyć ze specjalnego ,,pustego'' typu wbudowanego object.

Po co dziedziczyć z object? Dzięki temu klasa (i wszystkie klasy z niej dziedziczące) będzie klasą w nowym stylu. Najprościej mówiąc, udostępnia to pewne zaawansowane możliwości (niedostępne przed wersją 2.2 Pythona), a także ułatwia życie w niektórych sytuacjach... Dociekliwych odsyłam do zagadnienia klas w starym i w nowym stylu - czyli old-style (classic) classes i new-style classes.

Problem nie dotyczy Pythona 3.x, w którym wszystkie klasy są klasami w nowym stulu - a więc dziedziczenie z object jest automatyczne (nie trzeba go robić jawnie).

7. Co dalej
https://pl.python.org/docs/tut/node11.html (po polsku - stare)
http://docs.python.org/tutorial/classes.html (po angielsku - aktualne)
http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie/Definiowanie_klas (po polsku)


PS. Dotyczy pierwszego z trzech powyższych linków: od czasów Pythona 2.2 zastrzeżenie ,,typy wbudowane nie mogą być użyte jako klasy bazowe klas zdefiniowanych przez użytkownika'' jest nieaktualne.

Jak napisałem wyżej, jak najbardziej można dziedziczyć z typów wbudowanych, a wręcz jest to zalecane. Klasy w nowym stylu to właśnie klasy dziedziczące z typów wbudowanych (np. z object).
Zapisane
« Odpowiedz #1 : 01:48 09/07/09 »
LQC Offline
Python God

Zobacz profil
*****

Reputacja: 226
Płeć: Mężczyzna
Wiadomości: 1000



Cytuj
Tak tworzymy klasę:

Kod
class A:
   pass  # (pass czyli "nic nie rób" - ta klasa jest całkiem pusta)

Dopóki Python 3.x nie zostanie standardem, to ja jednak proponuje pisać:

Kod
class A(object):
   pass # pusta klasa nowej generacji :)

To naprawdę ma znaczenie, szczególnie w kontekście tego o czym piszesz - czyli znajdowania atrybutów.

Poza tym, całość wygląda całkiem przyjaźnie, chociaż trochę przydługie wyszło. Może ktoś wymyśli jak to skrócić?
Zapisane

Dołącz do projektu Wolnelektury.pl na github (open-source, pro publico bono)
« Odpowiedz #2 : 02:19 09/07/09 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


Klasy w starym i nowym stylu to trochę nie ten poziom zagadnień, ale zgoda, że różnice są spore -- więc dodałem osobny punkt (6.).

Co do długości -- obawiam się, że skracanie musiałoby się odbyć kosztem zrozumiałości. To jest tekst napisany z myślą o naprawdę początkujących.
Zapisane
« Odpowiedz #3 : 00:49 16/07/09 »
Traper Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 34


Hej.

Przeczytałem dokładnie cały artykuł. Niestety dalej rozumiem użycia "self":

Kod
class Samochod():
  def __init__(self):
# ustawiamy atrybuty instancji (teraz widzimy, po co nam  self)
     self.predkosc = 0

Ja do końca nie widzę, co się stanie gdy zrobimy (jest coś nie tak):

Kod
class Samochod():
  def __init__():
# ustawiamy atrybuty instancji
     predkosc = 0

Ok, modyfikuję swój post, znalazłem odpowiedź na to pytanie...

http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie/Definiowanie_klas#Kiedy_u.C5.BCywa.C4.87_self_i_init

Jeśli ktoś ma wątpliwości, trzeba to bardzo dokładnie przeczytać. W tym temacie kluczowe jest zdanie:

Cytuj
"W metodzie __init__ self odwołuje się do właśnie utworzonego obiektu; w innych metodach klasy, self odwołuje się do instancji, z której wywołaliśmy daną metodę."

Być może w tym artykule była na to odpowiedź, lecz jej nie zauważyłem.

Pozdrawiam.

(Używam Pythona 3.0 stąd moje wątpliwości)
Zapisane

^^
« Odpowiedz #4 : 01:00 16/07/09 »
LQC Offline
Python God

Zobacz profil
*****

Reputacja: 226
Płeć: Mężczyzna
Wiadomości: 1000


Weźmy

Kod
class Samochod():
  def __init__():
# ustawiamy atrybuty instancji
     predkosc = 0

Pomijając fakt, że __init__ musi przyjmować conajmniej 1 argument, to pomyśl co robi "predkosc = 0". Jak dla mnie, to tworzy nową zmienną lokalną o nazwie "predkosc" i przypisuje jej 0. Skąd Python ma wiedzieć, że ty chcesz przypisać coś na właściciela tej metody ? W języku takim jak Java, do tego służy niejawny argument "this". W Pythonie argument ten jest jawny i może mieć dowolną nazwę. Np.:

Kod
class Samochod():
  def __init__(alamakota):
# ustawiamy atrybuty instancji
     alamakota.predkosc = 0
Zapisane

Dołącz do projektu Wolnelektury.pl na github (open-source, pro publico bono)
« Odpowiedz #5 : 01:51 16/07/09 »
Traper Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 34


W interaktywnym Pythonie, wychodzi na to, że __init__ nie musi mieć żadnego argumentu. Jest jednak ALE, jeśli __init__ nie będzie miało argumentów, nie dodamy nowej instancji do tej klasy.

Moje pytanie nr 2 jest: co z atrybutami pod __init__ ? gdy nie użyjemy self.
Zapisane

^^
« Odpowiedz #6 : 01:54 16/07/09 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


@Traper:
Ad to, co napisał LQC (a przy okazji ad Twoje pytanie nr 2, o ile dobrze je zrozumiałem): napisanie wewnątrz funkcji lub metody (__init__ czy o jakiejkolwiek innej nazwie):

Kod
predkosc = 0

-- oznacza, że każesz Pythonowi stworzyć zmienną, która z chwilą zakończenia wykonywania metody zostanie zapomniana [edit: czyli tak zwaną zmienną lokalną -- NIE jest ona atrybutem klasy ani instancji klasy].

Tu widać istotną różnicę między definicją funkcji/metody (def...) a definicją klasy (class...):

Kod zawarty wewnątrz definicji funkcji/metody będzie wykonany dopiero z chwilą wywołania funkcji/metody, a zawarte w nim przypisania niepoprzedzone nazwą żadnego obiektu w typowej sytuacji odnoszą się do zmiennych lokalnych.

Kod
def nic():
   tralala = 3  # zmienna lokalna
 
print nic.tralala  # AttributeError: 'function' object has no attribute 'tralala'

Kod zawarty wewnątrz definicji klasy jest wykonywany od razu (przy tworzeniu klasy), a zawarte w nim przypisania niepoprzedzone nazwą żadnego obiektu odnoszą się do atrybutów klasy.

Kod
class nic:
   tralalala = 3  # atrybut klasy Nic
 
print nic.tralala  # -> 3

[@Edit 2009-12: drobne poprawki uczytelniające]
Zapisane
« Odpowiedz #7 : 02:03 16/07/09 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


W interaktywnym pythonie, wychodzi na to, że __init__() nie musi mieć żadnego argumentu. Jest jednak ALE, jeśli __init__() nie będzie miało argumentów, nie dodamy nowej instancji do tej klasy.

To czy używamy trybu interaktywnego czy uruchamiamy program z pliku nie ma w tym wypadku żadnego znaczenia.

Python pozwala zdefiniować w ramach klasy nieprawidłową metodę __init__(), ale chwila prawdy przychodzi wraz z próbą stworzenia instancji tejże klasy -- jak sam zauważyłeś nie da się; wyskakuje błąd: "TypeError: __init__() takes no arguments (1 given)" -- z czego widać, że Python próbował wywołać __init__() z nowym obiektem instancji jako pierwszym argumentem, ale jakoże zdefiniowano __init__() jako funkcję bezargumentową, musiało to spowodować wyjątek TypeError.

PS. W moim tekście, w listingu wprowadzającym metodę __init__() dodałem dla lepszej jasności komentarz ("self -- nowo utworzony obiekt instancji").
Zapisane
« Odpowiedz #8 : 02:20 16/07/09 »
Traper Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 34


Właśnie, rozumiem, tylko jeszcze mała niepewność:

jak już zrobimy nieprawidłowo:

Kod
class blablabla:
  def __init__():
     dana = 1
     liczba = 2

W jaki sposób, można się dostać do tych dwóch zmiennych. Istnieją, ale jak je wykorzystać. Nie bardzo wiem, tym bardziej, że metoda __init__ nic nie zwraca.
Zapisane

^^
« Odpowiedz #9 : 02:44 16/07/09 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


Rzecz właśnie w tym, że nie istnieją...

Po pierwsze nie zaistnieją, dopóki nie zostanie wywołana metoda -- (co w przypadku __init__() następuje z chwilą stworzenia instancji, np. b = blablabla(); jednakże w tym wypadku, przy próbie przekazania argumentu, wystąpi błąd, o którym była wyżej mowa -- więc w ogóle nie zaistnieją).

Po drugie -- jak już zaistnieją, to z chwilą zakończenia wykonywania metody zostaną zapomniane (nie będzie więcej do nich dostępu). Kolejne wywołanie metody stworzy kolejne (ale nowe, a nie te same) zmienne -- i tak samo zostaną one zapomniane. Taka natura zmiennych lokalnych.

Dlatego właśnie potrzebujesz obiektu instancji (przekazywanego do metody jako pierwszy argument, zwyczajowo nazywany self), do którego możesz dodawać atrybuty, np. self.dana czy self.liczba...
Zapisane
« Odpowiedz #10 : 02:48 16/07/09 »
LQC Offline
Python God

Zobacz profil
*****

Reputacja: 226
Płeć: Mężczyzna
Wiadomości: 1000


Minimalna działająca wersja tego kodu to:

Kod
class blablabla:
  def __init__(jakis_argument):
     dana = 1
     liczba = 2

W takiej postaci nie da się dostać do tych zmiennych, bo po końcu metody __init__ nie będzie już do nich żadnych odwołań. Można kombinować i zrobić coś takiego:

Kod
class A(object):
   def __init__(self, arg):
       zmienna_lokalna = {'slownik': 42}
       arg.append(zmienna_lokalna)
# i dalej
L = []
a = A(L)
print L
Zapisane

Dołącz do projektu Wolnelektury.pl na github (open-source, pro publico bono)
« Odpowiedz #11 : 02:52 16/07/09 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425



Cytuj
Można kombinować i zrobić coś takiego:

Można, ale rozumiem, że podajesz to jako teoretyczną możliwość. W praktyce w 99% przypadków odradzałbym, bo takie techniki czynią kod koszmarnie podatnym na błędy.
Zapisane
« Odpowiedz #12 : 03:04 16/07/09 »
Traper Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 34


Tak sądzę że, chodzi tylko o teorię. Lubię wiedzieć co jak zadziała w każdej sytuacji, nawet takiej jaka się nie zdarzy. Dzięki za odpowiedzi Panowie.
Zapisane

^^
« Odpowiedz #13 : 21:09 03/10/10 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


[Update: uzupełniłem pierwszy punkt o przykład z fakturami + dodałem drobiazgi w punktach 2. i 3.]

[Update of update Uśmiech -- jeszcze drobne poprawki]
Zapisane
« Odpowiedz #14 : 15:17 09/10/11 »
zuo Offline
Professional Python User

Zobacz profil
***

Reputacja: 129
Wiadomości: 425


[Update 2011-10-09] Pisząc tekst używałem określenia obiekt instancji jako równoznacznego z instancja oraz określenia obiekt klasy jako równoznacznego z klasa. Jednakże przekonawszy się, że może to być mylące (patrz wątek: https://pl.python.org/forum/index.php?topic=2441.0), przerobiłem w tekście wszystkie określenia obiekt instancji/klasy na instancja/klasa (odpowiednio). Przy okazji zmieniłem nazwy niektórych zmiennych na bardziej opisowe i poprawiłem parę innych drobiazgów.
Zapisane
Strony: [1] 2   Do góry
Drukuj
Skocz do:  

© 2007 - 2019 Polish Python Coders Group
Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines | Theme by PixelSlot