Mam problem ze zrozumieniem inicjalizacji klas.
Jaki jest ich sens i skąd wiemy, co w nich zawrzeć? Czy pisanie na zajęciach wymaga innego sposobu myślenia niż tworzenie funkcji (pomyślałem, że mogę po prostu tworzyć funkcje, a następnie po prostu opakować je w klasę, aby móc ich ponownie użyć. Czy to zadziała?)
Oto przykład:
class crawler:
# Initialize the crawler with the name of database
def __init__(self,dbname):
self.con=sqlite.connect(dbname)
def __del__(self):
self.con.close()
def dbcommit(self):
self.con.commit()
Lub inny przykład kodu:
class bicluster:
def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
self.left=left
self.right=right
self.vec=vec
self.id=id
self.distance=distance
Jest tak wiele zajęć, z __init__
którymi się spotykam, próbując czytać kod innych osób, ale nie rozumiem logiki ich tworzenia.
Odpowiedzi:
W tym, co napisałeś, brakuje ci krytycznego zrozumienia: różnicy między klasą a przedmiotem.
__init__
nie inicjalizuje klasy, inicjuje wystąpienie klasy lub obiektu. Każdy pies ma kolor, ale psy jako klasa nie. Każdy pies ma cztery lub mniej łap, ale klasa psów nie. Klasa to pojęcie obiektu. Kiedy widzisz Fido i Spot, rozpoznajesz ich podobieństwo, ich psią budę. To jest klasa.Kiedy powiesz
Mówisz, że Fido to brązowy pies z 4 nogami, podczas gdy Spot jest trochę kaleką i jest przeważnie żółty.
__init__
Wywoływana jest funkcja konstruktora lub inicjator i jest automatycznie wywoływana podczas tworzenia nowej instancji klasy. W ramach tej funkcji nowo utworzony obiekt jest przypisywany do parametruself
. Notacjaself.legs
to wywoływany atrybutlegs
obiektu w zmiennejself
. Atrybuty są czymś w rodzaju zmiennych, ale opisują stan obiektu lub określone akcje (funkcje) dostępne dla obiektu.Zauważ jednak, że nie jesteś nastawiony
colour
na samą psiarnię - to abstrakcyjna koncepcja. Istnieją atrybuty, które mają sens w klasach. Na przykładpopulation_size
jest jednym z nich - nie ma sensu liczyć Fido, ponieważ Fido zawsze jest jednym. Liczenie psów ma sens. Powiedzmy, że na świecie jest 200 milionów psów. To własność klasy Dog. Fido nie ma nic wspólnego z liczbą 200 milionów, podobnie jak Spot. Nazywa się to „atrybutem klasy”, w przeciwieństwie do „atrybutów instancji”, które są równecolour
lublegs
wyższe.A teraz coś mniej psiego, a bardziej związanego z programowaniem. Jak piszę poniżej, klasa dodawania rzeczy nie ma sensu - co to za klasa? Klasy w Pythonie składają się ze zbiorów różnych danych, które zachowują się podobnie. Klasa psów składa się z Fido i Spot oraz 199999999998 innych podobnych do nich zwierząt, wszystkie sikają na latarniach. Z czego składa się klasa dodawania rzeczy? Jakimi danymi się różnią? A jakie akcje mają wspólne?
Jednak liczby… to ciekawsze tematy. Powiedz, liczby całkowite. Jest ich dużo, dużo więcej niż psy. Wiem, że Python ma już liczby całkowite, ale zagrajmy w głupków i „zaimplementujmy” je ponownie (oszukując i używając liczb całkowitych Pythona).
Tak więc liczby całkowite są klasą. Mają pewne dane (wartość) i pewne zachowania („dodaj mnie do tego innego numeru”). Pokażmy to:
Jest to trochę kruche (zakładamy, że
other
będzie to MyInteger), ale teraz zignorujemy. W prawdziwym kodzie nie; przetestowalibyśmy to, aby się upewnić, a może nawet wymusilibyśmy to („nie jesteś liczbą całkowitą? przez golly, masz 10 nanosekund, aby stać się jednością! 9 ... 8 ....”)Moglibyśmy nawet zdefiniować ułamki. Frakcje również wiedzą, jak się dodawać.
Jest jeszcze więcej ułamków niż liczb całkowitych (niezupełnie, ale komputery o tym nie wiedzą). Zróbmy dwa:
W rzeczywistości niczego tu nie deklarujesz. Atrybuty są jak nowy rodzaj zmiennych. Zmienne normalne mają tylko jedną wartość. Powiedzmy, że piszesz
colour = "grey"
. Nie możesz mieć innej zmiennej ocolour
takiej nazwie"fuchsia"
- nie w tym samym miejscu w kodzie.Tablice do pewnego stopnia to rozwiązują. Jeśli powiesz
colour = ["grey", "fuchsia"]
, że umieściłeś dwa kolory w zmiennej, ale rozróżniasz je na podstawie ich pozycji (w tym przypadku 0 lub 1).Atrybuty to zmienne powiązane z obiektem. Podobnie jak w przypadku tablic, możemy mieć wiele
colour
zmiennych dla różnych psów . Tak więcfido.colour
jest jedną zmienną, alespot.colour
jest inną. Pierwsza jest związana z obiektem w zmiennejfido
; drugi,spot
. Teraz, gdy wywołaszDog(4, "brown")
lubthree.add(five)
zawsze będzie niewidoczny parametr, który zostanie przypisany do wiszącego dodatkowego parametru na początku listy parametrów. Jest konwencjonalnie nazywanyself
i pobiera wartość obiektu przed kropką. Tak więc w Dog__init__
(konstruktor)self
będzie to, czym okaże się nowy Dog; wewnątrzMyInteger
'sadd
,self
zostanie powiązany z obiektem w zmiennejthree
. A zatem,three.value
będzie ta sama zmienna pozaadd
, jakself.value
wadd
.Jeśli powiem
the_mangy_one = fido
, zacznę odwoływać się do przedmiotu znanego podfido
jeszcze inną nazwą. Od terazfido.colour
jest dokładnie tą samą zmienną, cothe_mangy_one.colour
.Więc rzeczy wewnątrz
__init__
. Możesz myśleć o nich jako o zapisywaniu rzeczy w akcie urodzenia Psa.colour
sama w sobie jest zmienną losową, może zawierać wszystko.fido.colour
lubself.colour
jest jak pole formularza na karcie identyfikacyjnej Psa; i__init__
czy urzędnik wypełnia go po raz pierwszy.Jakieś jaśniejsze?
EDYCJA : Rozwinięcie komentarza poniżej:
Masz na myśli listę obiektów , prawda?
Przede wszystkim
fido
właściwie nie jest przedmiotem. Jest to zmienna, która aktualnie zawiera obiekt, tak jak mówiszx = 5
,x
jest zmienną zawierającą obecnie liczbę pięć. Jeśli później zmienisz zdanie, możesz to zrobićfido = Cat(4, "pleasing")
(o ile utworzyłeś klasęCat
) ifido
odtąd „zawiera” obiekt kota. Jeśli to zrobiszfido = x
, będzie zawierał liczbę pięć, a nie obiekt zwierzęcy.Klasa sama w sobie nie zna swoich instancji, chyba że specjalnie napiszesz kod, aby je śledzić. Na przykład:
Tutaj
census
jest atrybutCat
klasy na poziomie klasy.Pamiętaj, że nie dostaniesz
[fluffy, sparky]
. To tylko nazwy zmiennych. Jeśli chcesz, aby koty same miały imiona, musisz utworzyć osobny atrybut dla nazwy, a następnie zastąpić__str__
metodę zwracania tej nazwy. Celem tej metody (tj. Funkcji związanej z klasą, tak jakadd
lub__init__
) jest opisanie, jak przekształcić obiekt w łańcuch, na przykład podczas drukowania.źródło
Aby przekazać moje 5 centów na dokładne wyjaśnienie od Amadana .
Gdzie klasy są opisem „typu” w sposób abstrakcyjny. Obiekty są ich urzeczywistnieniem: żyjąca, oddychająca rzecz. W świecie zorientowanym na przedmioty istnieją podstawowe idee, które można niemal nazwać esencją wszystkiego. Oni są:
Obiekty mają jedną lub więcej cech (= Atrybuty) i zachowań (= Metody). Zachowanie zależy głównie od cech. Klasy w sposób ogólny definiują, co powinno osiągnąć zachowanie, ale dopóki klasa nie jest realizowana (tworzona) jako obiekt, pozostaje abstrakcyjną koncepcją możliwości. Pozwólcie, że zilustruję za pomocą „dziedziczenia” i „polimorfizmu”.
Niektóre cechy definiują ludzi. Ale każda narodowość jest nieco inna. Więc „typy narodowe” to ludzie z dodatkami. „Amerykanie” są typem „ludzi” i dziedziczą pewne abstrakcyjne cechy i zachowania po typie ludzkim (klasa podstawowa): to jest dziedziczenie. Tak więc wszyscy ludzie mogą się śmiać i pić, dlatego wszystkie klasy dziecięce też mogą! Dziedziczenie (2).
Ale ponieważ wszystkie są tego samego rodzaju (Type / base-class: Humans), możesz je czasami wymienić: zobacz pętlę for na końcu. Ale ujawnią indywidualną charakterystykę i to jest polimorfizm (3).
Zatem każdy człowiek ma swój ulubiony napój, ale każda narodowość skłania się ku specjalnemu rodzajowi napoju. Jeśli podklasujesz narodowość z typu Ludzi, możesz nadpisać odziedziczone zachowanie, jak pokazałem powyżej za pomocą
drink()
Metody. Ale to wciąż na poziomie klasowym i dlatego jest to uogólnienie.tworzy instancję klasy German i „zmieniłem” domyślną charakterystykę na początku. (Ale jeśli zadzwonisz do hans.drink ('Milk'), to i tak wypisze „Potrzebuję więcej piwa” - oczywisty błąd ... a może tak nazwałbym funkcję, gdybym był pracownikiem większej firmy. ;-)! )
Charakterystyka typu np. Germans (hans) jest zwykle definiowana przez konstruktora (w pythonie:)
__init__
w momencie instancji. To jest punkt, w którym definiujesz klasę, która ma stać się obiektem. Można powiedzieć, że tchnij życie w abstrakcyjną koncepcję (klasę), wypełniając ją indywidualnymi cechami i stając się przedmiotem.Ale ponieważ każdy obiekt jest instancją klasy, mają one wspólne wszystkie podstawowe typy cech i pewne zachowanie. Jest to główna zaleta koncepcji zorientowanej obiektowo.
Aby chronić cechy każdego obiektu, hermetyzujesz je - oznacza to, że próbujesz połączyć zachowanie i charakterystykę i utrudnić manipulowanie nimi z zewnątrz obiektu. To jest kapsułkowanie (1)
źródło
Służy tylko do zainicjowania zmiennych instancji.
Np. Utwórz
crawler
instancję o określonej nazwie bazy danych (z powyższego przykładu).źródło
left=None
left zostanie zainicjowane,None
jeśli podczas tworzenialeft
parametr nie jest określony.left = foo
zadziała - raz. Celem zajęć jest zrobienie czegoś sensownego dla każdego innegocrawler
. Klasy nie są funkcjami ani czymś, co można porównać do funkcji (cóż, nie dopóki nie jesteś dużo bardziej zaawansowany i nie zajmiesz się programowaniem funkcjonalnym, ale to cię teraz zmyli). Przeczytaj moją odpowiedź, czym właściwie są zajęcia - nadal nie rozumiesz.Wygląda na to, że musisz użyć
__init__
w Pythonie, jeśli chcesz poprawnie zainicjować zmienne atrybuty swoich instancji.Zobacz poniższy przykład:
Zupełnie inaczej jest w Javie, gdzie każdy atrybut jest automatycznie inicjowany z nową wartością:
tworzy wynik, którego intuicyjnie oczekujemy:
Ale jeśli zadeklarujesz
attr
jakostatic
, będzie działać jak Python:źródło
Idąc za przykładem twojego samochodu : kiedy kupujesz samochód, po prostu nie dostajesz losowego samochodu, to znaczy wybierasz kolor, markę, liczbę miejsc itp. A niektóre rzeczy są również "inicjalizowane" bez twojego wyboru na przykład liczba kół lub numer rejestracyjny.
Tak więc w
__init__
metodzie definiujesz atrybuty tworzonej instancji. Tak więc, jeśli chcemy mieć niebieski samochód Renault, dla 2 osób, zainicjowalibyśmy lub wystąpił taki przykładCar
:W ten sposób tworzymy instancję
Car
klasy. To__init__
ten, który obsługuje nasze określone atrybuty (takie jakcolor
lubbrand
) i generuje inne atrybuty, takie jakregistration_number
.__init__
metodzieźródło
Klasy to obiekty, których atrybuty (stan, charakterystyka) i metody (funkcje, pojemności) są specyficzne dla tego obiektu (jak odpowiednio biały kolor i moc muchy dla kaczki).
Tworząc instancję klasy, możesz nadać jej początkową osobowość (stan lub postać, np. Nazwę i kolor jej sukienki dla noworodka). Robisz to z
__init__
.Zasadniczo
__init__
ustawia właściwości instancji automatycznie podczas wywołaniainstance = MyClass(some_individual_traits)
.źródło
__init__
Funkcja konfigurowania wszystkie zmienne w klasie. Po utworzeniu biclusterka możesz uzyskać dostęp do członka i odzyskać wartość:Sprawdź dokumentację Pythona, aby uzyskać więcej informacji. Będziesz chciał przeczytać książkę o koncepcjach OO, aby kontynuować naukę.
źródło
W powyższym przykładzie używamy gatunku jako globalnego, ponieważ będzie on zawsze taki sam (można powiedzieć, że jest to rodzaj stałej). kiedy wywołasz
__init__
metodę, wszystkie zmienne wewnątrz__init__
zostaną zainicjowane (np .: rasa, imię).jeśli wydrukujesz powyższy przykład, dzwoniąc poniżej w ten sposób
Oznacza to, że zostanie zainicjowany tylko podczas tworzenia obiektu. więc wszystko, co chcesz zadeklarować jako stałe, staje się globalne i wszystko, czego używają zmiany
__init__
źródło