IDE nie widzi zadeklarowanego parametru "self"

0

Witam. Niedawno rozpocząłem naukę programowania i postanowiłem zacząć od Pythona, ponieważ czytałem że jest najprostszy i rzeczywiście taki jest. Po pewnych zagadnieniach przyszedł czas na obiektówkę, postanowiłem nauczyć się klas,obiektów, metod itd. Skorzystałem z kursu na yt i śledziłem poczynania gościa który pisał program, który wykorzystywał obiektówke. Zadaniem tego programu było stworzyć klasę "Zwierze" dać mu parametry: Imie, Wysokosc, Waga i Dzwiek jaki wydaje, pozniej natomiast owy obiekt mial sie przedstawic czyli pwoeidziec jak sie nazywa, ile ma wzrostu, wagi itd po stworzeniu go w sposob np

Kot = Zwierze('Puszek',10,5,'Miau')
print(Kot.NazwaTamtejFunkcjiKtoraMialaWypisywac())

wszystko fajnie, jednak zanim do tego doszedłem napotkałem u siebie błąd:

class Animal:
	__name =  ""
	__height = 0
	__weight = 0
	__sound = 0

	def __init__(self,name,height,weight,sound):
		self.__name = name
		self.__height = height
		self.__weight = weight
		self.__sound = sound

	def set_name(self, name):
        self.__name = name   # <---------- w tym miejscu IDE nie znajduje mi podanego wczesniej 'self.__name' ani samego 'name'

    def get_name(self):
        return self.__name
 

Chciałbym wiedzieć co schrzaniłem i później nie popełniać takich błędów. Z góry dziękuję bardzo za pomoc :)

2

Masz głupie IDE i tyle. Korzystaj z darmowego PyCharm Community.

Co do kodu to kilka uwag:

  1. Po co tworzyć statyczne skoro żaden obiekt z nich nie skorzysta? W init te dane są nadpisywane dla każdego egzemplarza.
  2. set_name, get_name na takich durnych przykładach się nie opłaca - bo niby czemu później masz używać animal.get_name() zamiast animal.name? Nim mądrze zaczniesz używać hermetyzacji miną wieki. W każdym razie nie wszędzie opłaca się robić akcesory/gettery.

PS, polecam zmienić kurs z którego uczysz się pythona.

4

W Pythonie wszystko jest publiczne, nie powinieneś pól klasy tworzyć w ten sposób. Python dodaje do nich nazwę klasy, tym samym u Ciebie "imię" zwierzaka wygląda dokładnie tak: "_Animal__name" i dlatego self nie widzi atrybutu "__name". Możesz to sprawdzić w konsoli pythona, po zaimportowaniu klasy, stwórz obiekt klasy Animal i wywołaj na nim funkcję:

dir(zwierzak)

W odpowiedzi dostaniesz, coś podobnego do:

['_Animal__name', '__doc__', '__init__', '__module__']

Jeżeli chcesz oznaczyć dany atrybut lub metodę, że jest prywatna, to dodawaj do niej jedno podkreślenie "_name". Python wtedy nie dodaje nazwy klasy na początku. Atrybut jest jednak publiczny. Zapytasz więc, po co takie coś? Ano dlatego, że jak ktoś będzie chciał zrobić "zwierzak.sound", to mu się to nie uda, bo u Ciebie będzie _sound, o którym Ty jako programista wiesz. Po drugie dodanie jednego podkreślenia jest informacją dla innych programistów, że dany atrybut czy też metoda są prywatne, a działanie Twojej klasy i metod pozostaje zgodne z filozofią Pythona.

Twój kod może wyglądać w ten sposób:

 
class Animal:
 
    def __init__(self,name,height,weight,sound):
        self._name = name
        self._height = height
        self._weight = weight
        self._sound = sound
 
    def set_name(self, name):
        self._name = name
 
    def get_name(self):
        return self._name

A jeszcze lepiej jak użyjesz @property:

 
class Animal(object):
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @x.setter
    def x(self, name):
        self._name = name

To jest właściwy sposób tworzenia setterów i getterów w Pythonie. Dzięki temu zamiast pisać "zwierzak.set_name('imie')", piszesz "zwierzak.name = 'imie'", a zamiast zwierzak.get_name()" zwyczajnie "zwierzak.name".

0

Korzystam z JetBrains PyCharm 5.0.3
Rozumiem. Gosc na kursie na yt zagmatwał, a że ja nie mam doświadczenia w pisaniu obiektowym nie połapałem się o co w tym chodzi.

Mam jeszcze takie pytanie. Czy jak chce pisac takie wieksze programy z wykorzystaniem obiektu to musze wykorzystywac konsole Pythona ? Nie korzystalem z tego, zwykle pisalem w środowisku i po odpaleniu wyświetlał mi się wynik pod kodem w takiej środowiskowej konsoli.

Dzieki za odpowiedzi, musze jeszcze poznac wiele rzeczy..

0

Ta "srodowiskowa konsola" to jest to samo co konsola typu "cmd" w windowsie, tylko, że wsadzili ją w IDE, żeby było wygodniej. Jak wywołasz to w cmd to dostaniesz to samo.

0

Juz nie wiem o co chodzi, zdaje sie ze zupelnie nie rozumiem programowania obiektowego

class Pies:
	def _init_(self,imie):
		self.imie = imie
	def _str_(self):
		rep = "Obiekt klasy Pies\n"
		rep += "imie: ",self.imie,"\n"
		return rep

	def Szczekaj(self):
		print("Hau!Hau! Jestem ",self.imie,"\n")

pies1 = Pies("Jamnik")

pies1.Szczekaj()
 

W zalozeniu jest zeby Wyswietlilo mi: Hau!Hau! Jestem Jamnik
a zamiast tego wyswietla:

Traceback (most recent call last):
  File "C:/Users/Neapol/Desktop/wonsz/pierwszy.py", line 13, in <module>
    pies1 = Pies("Jamnik")
TypeError: object() takes no parameters

Obiekt nie posiada parametrów? Ale przeciez podałem parametr "Jamnik" jako imie. Czego brakuje? Pomoze mi ktos? :(

0

Masz jeden (a właściwie dwa) malutki(e) błąd (błędy) na początku klasy (przy init).

0

mówisz o konstruktorze który nie jest publiczny ? niestety kiedy dam __init__ wynik jest identyczny, dziwne bo ludziom w kursach te rzeczy chodzą. trzeba do obiektowego importować jakiś moduł ??

0

Dziwne, bo w IDLE działa poprawnie.

class Pies:
    def __init__(self,imie):
        self.imie = imie
    def __str__(self):
        rep = "Obiekt klasy Pies\n"
        rep += "imie: " + self.imie + "\n"
        #wyżej mała zmiana, pierwotna wersja poprawnie nie działa.
        return rep
 
    def Szczekaj(self):
        print("Hau!Hau! Jestem ",self.imie,"\n")
 
pies1 = Pies("Jamnik")
 
pies1.Szczekaj() 
0

Zmyślasz, http://ideone.com/GBgirB
Jak uruchamiasz kod po zmianie

_init_
#na
__init__
0

nie zmyślam. czy jest problem z moim środowiskiem ? user image

2

Zmyślasz, nie zmieniłeś _init_ na __init__.

0

okej. wczesniej probowalem i nie dawalo mi wyniku jaki chcialem, kiedy dawalem 2 podkreslenia. widac coś innego wcześniej miałem źle. przepraszam za zamieszanie, to przez moje gapiostwo. dzięki za pomoc :)

2

To w takim razie następna lekcja, bo widzę, że zacząłeś stosować pojedyncze podkreślenia w nazwach funkcji. W Pythonie obecne są specjalne, wbudowane w język funkcje. Nie trzeba ich samemu pisac, po prostu są i dla wyróżnienia pisane są z dwoma podkreśleniami na początku i dwoma a z tyłu. Należą do nich właśnie __init__, __dict__, __repr__ itp. Tutaj zasada jednego podkreślenia nie jest stosowana :) Aczkolwiek deklarując własną metodę możesz jej nazwę rozpocząć jednym podkreśleniem, np:

 
def _moja_prywatna_metoda(self):
  return self.name

Tutaj zasada jest taka sama jak przy atrybutach klasy: metoda z jednym podkreśleniem jest tylko umownie prywatna.

0

Najnowszy Notepad++ ma również dobry system podpowiedzi do Pythona.

0

Dzięki dobrzy ludzie. Nie zapomnę. I przepraszam za taki spam z tak trywialnego powodu :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1