Klasy - wykorzystane egzemplarza jako argumentu

0

Cześć,
mam takie zadanie aby utworzyć nową klasę Privileges, a następnie utworzyć egzemplarz klasy Privileges jako atrybut w klasie Admin
Napisałem kod, który działa tylko nie rozumiem jednej rzeczy. Dlaczego program się uruchamia kiedy definiując metodę __init__ podaję wartość domyślną w postaci listy.
A jak podaje sam parametr bez wartości domyślnej. I dopiero pod spodem dodaje wartośc atrybutu self.privileges = ['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika'] To program się wysypuje ?

niedziałająca część

class Privileges():
	"""Class containing information about privileges"""
	def __init__(self, privileges):
		self.privileges = ['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika']

działająca część

class Privileges():
	"""Class containing information about privileges"""
	def __init__(self, privileges= ['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika']):
		self.privileges = privileges

cały program

class User():
	"""Class containing information about user"""
	def __init__(self, first_name, last_name, login, sex, age):
		"""Initialization of attributes"""
		self.first_name = first_name
		self.last_name = last_name
		self.login = login
		self.sex = sex
		self.age = age
		self.login_attempts = 0

	def describe_user(self):
		print(f"\nInformację o użytkowniku: {self.login}:")
		print(f"\tImię: {self.first_name.title()}")
		print(f"\tNazwisko: {self.last_name.title()}")
		print(f"\tPłeć: {self.sex}")
		print(f"\tWiek: {self.age}")

	def greet_user(self):
		print(f"Witaj! {self.first_name.title()} {self.last_name.title()}.")

	def increment_login_attempts(self):
		self.login_attempts += 1

	def reset_login_attempts(self):
		self.login_attempts = 0

	def show_login_attempts(self):
		print(f"Logowałeś się {self.login_attempts} razy!")

class Privileges():
	"""Class containing information about privileges"""
	def __init__(self, privileges=['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika']):
		self.privileges = privileges

	def show_privileges(self):
		"""Shows Admin privileges"""
		print(f"Jako Admin może: {self.privileges[0]}, {self.privileges[1]}, {self.privileges[2]}.")




class Admin(User):
	"""Class containing information about Admin"""
	def __init__(self, first_name, last_name, login, sex, age):
		"""
		Inicjalizacja atrybutów klasy nadrzędnej oraz atrybutów klasy Admin
		"""
		
		super().__init__(first_name, last_name, login, sex, age)
		self.privileges = Privileges()

	


user_0 = Admin('jan', 'kowalski', 'jkowal', 'male', 25)
user_0.describe_user()
user_0.privileges.show_privileges()
user_0.greet_user()


1

Ech. A popatrz laskawie GDZIE się wysypuje. Na:

self.privileges = Privileges()

Wołasz konstruktor klasy Privileges BEZ ARGUMENTÓW. Więc jak masz tam argument, to taki konstruktor nie istnieje i program nie zadziała. Ale jak zrobisz argument z domyślną wartością, to wtedy przekazywć go nie trzeba.

0

@Shalom: Widziałem na czym się wysypało ale nie potrafiłem tego dobrze zinterpretować niestety.

Średnio zrozumiałem Twoje wyjaśnienie, próbuję dodać jakieś argumenty ale nadal mi nie wychodzi...
Zrozumiałe jest dla mnie to, że jak jest wartość domyślna dla parametru privileges w konstruktorze __init__ to program działa w takiej postaci jak teraz bo nie musi wywoływać argumentu dla ``privileges''.

To jak powinno to wyglądać, żeby nie ustawiać wartości domyślnej, tylko wyciągać to ze zmiennej z klasy Privileges ?

1

o_O to weź moze zacznij od pisania hello worlda? Miałeś kiedyś matematykę w szkole? Jak masz funkcje f(x,y) to co chciałbyś dostać wywołując f(1)? Jak funkcja ma dwa argumenty, to musisz podać dwa argumenty zeby policzyc jej wartość! Konstruktor to funkcja jak każda inna. Twój konstruktor MA ARGUMENT więc MUSISZ PODAĆ ARGUMENT kiedy go wywołujesz. Twoje wywołanie to było self.privileges = Privileges(). Widzisz jakiś argument przekazany do funkcji Privileges()? Ja nie widzę.

0

@Shalom: A myślisz, że nie próbowałem tutaj coś wpisać... ?
starałem się wpisać self.privileges = Privileges(privileges) - żeby zaciągnęło zmienną z klasy Privileges nie działa
wpisałem nawet całą listę self.privileges = Privileges(['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika']) to znowu wyrzuca mi AttributeError: 'Admin' object has no attribute 'Privileges'
W jakiej postaci ma być ten argument, żeby nie musiało pobierać informacji z wartości domyślnej ?

0

@luckyluke88

żeby zaciągnęło zmienną z klasy Privileges

Co? o_O Zacznijmy moze od tego czym różni sie KLASA od OBIEKTU, bo to jak krzesło i krzesło elektryczne, jedno z drugim nie ma nic wspólnego. Twoja klasa privileges nie ma żadnej zmiennej. Moze co najwyżej obiekt tej klasy ma takie pole, ale to za bardzo sensu nie ma, bo przecież właśnie chcesz stworzyć taki obiekt, więc jeszcze nie masz do czego się odwołać. Żeby wyjaśnić ci idiotyzm tego stwierdzenia:

p1 = Privileges(['ala'])
p2 = Privileges(['ma'])
p3 = Privileges(['kota'])

Co w takiej sytuacji rozumiesz przez żeby zaciągnęło zmienną z klasy Privileges? Bo ja widze 3 obiekty, każdy ma inną listę o_O

wpisałem nawet całą listę self.privileges = Privileges(['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika']) to znowu wyrzuca mi AttributeError: 'Admin' object has no attribute 'Privileges'

Kłamiesz:

class User():
    """Class containing information about user"""

    def __init__(self, first_name, last_name, login, sex, age):
        """Initialization of attributes"""
        self.first_name = first_name
        self.last_name = last_name
        self.login = login
        self.sex = sex
        self.age = age
        self.login_attempts = 0

    def describe_user(self):
        print(f"\nInformację o użytkowniku: {self.login}:")
        print(f"\tImię: {self.first_name.title()}")
        print(f"\tNazwisko: {self.last_name.title()}")
        print(f"\tPłeć: {self.sex}")
        print(f"\tWiek: {self.age}")

    def greet_user(self):
        print(f"Witaj! {self.first_name.title()} {self.last_name.title()}.")

    def increment_login_attempts(self):
        self.login_attempts += 1

    def reset_login_attempts(self):
        self.login_attempts = 0

    def show_login_attempts(self):
        print(f"Logowałeś się {self.login_attempts} razy!")


class Privileges():
    """Class containing information about privileges"""

    def __init__(self, privileges):
        self.privileges = privileges

    def show_privileges(self):
        """Shows Admin privileges"""
        print(f"Jako Admin może: {self.privileges}.")


class Admin(User):
    """Class containing information about Admin"""

    def __init__(self, first_name, last_name, login, sex, age):
        """
        Inicjalizacja atrybutów klasy nadrzędnej oraz atrybutów klasy Admin
        """

        super().__init__(first_name, last_name, login, sex, age)
        self.privileges = Privileges(['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika'])


user_0 = Admin('jan', 'kowalski', 'jkowal', 'male', 25)
user_0.describe_user()
user_0.privileges.show_privileges()
user_0.greet_user()
> python38 cpanie.py

Informację o użytkowniku: jkowal:
	Imię: Jan
	Nazwisko: Kowalski
	Płeć: male
	Wiek: 25
Jako Admin może: może dodać posty, może usuwać posty, może zbanować użytkownika.
Witaj! Jan Kowalski.
0

@Shalom: Jeżeli chodzi o drugi podpunkt to nie wiem... może coś miałem namieszane w innej linijce kody i dlatego wyskoczył mi ten błąd. Teraz jak wpisałem to jeszcze raz to też mi się uruchomiło. Tylko nie w tym rzecz... Bo ja bym chciał mieć tą listę z informacją co robi Admin w klasie Privileges. I nie chodzi tutaj że gdzieś tego potrzebuję, tylko z czystej ciekawości jak to uruchomić żeby lista z atrybutami była podana w klasie Privileges. Nawet patrząc na twoją miniaturę masz pod spodem wpisanego Moderatora. I tak pomyślałem, że moderator przecież może robić te trzy czynności również usuwanie, blokowanie itd.
Więc bez sensu wpisywać listę ['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika'] w klasie Admin, skoro tworząc klasę potomną Moderator, chciałbym dziedziczyć te same wartości co Admin z Privileges

Spróbowałem trochę inaczej i z metody __init__ w Privileges usunąlem po prostu parametr privileges, żeby nie trzeba było podawać argumentu.
A poniżej utworzyłem oddzielny atrybut z przypisaną listą (mam nadzieję, że nie pomyliłem nazewnictwa elementów :p). Ostatecznie działa tak jak chciałem i nie mam tego problemu, który opisałem powyżej.

class Privileges():
	"""Class containing information about privileges"""
	def __init__(self):
		self.privileges = ['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika']
	def show_privileges(self):
		"""Shows Admin privileges"""
		
		print(f"Jako Admin może: {self.privileges[0]}, {self.privileges[1]}, {self.privileges[2]}.")




class Admin(User):
	"""Class containing information about Admin"""
	def __init__(self, first_name, last_name, login, sex, age):
		"""
		Inicjalizacja atrybutów klasy nadrzędnej oraz atrybutów klasy Admin
		"""
		
		super().__init__(first_name, last_name, login, sex, age)
		self.privileges = Privileges()

	
	


user_0 = Admin('jan', 'kowalski', 'jkowal', 'male', 25,)
user_0.describe_user()
user_0.privileges.show_privileges()
user_0.greet_user()

Także dziękuję za poświęcony czas.
Szkoda, że same odpowiedzi czasami przybierały formę jakby odpisywała bardzo sfrustrowana osoba z żalem, że musi pisać tu za karę, ale ostatecznie czegoś się nauczyłem także i tak było warto.

Na koniec odwołam się do Twojego stwierdzenia:

Co? o_O Zacznijmy moze od tego czym różni sie KLASA od OBIEKTU, bo to jak krzesło i krzesło elektryczne, jedno z drugim nie ma nic wspólnego.

Jak już logicznie o tym pomyśleć to krzesło i krzesło elektryczne mają ze sobą bardzo dużo wspólnego. Po prostu krzesło elektryczne ma dodatkową funkcję, której nie ma zwykłe krzesło ;) Poza tym można równie dobrze dostawić do niego stół, usiąść na tym krześle i zjeść obiad ;)

0

@luckyluke88 to co zrobiłeś nie ma sensu, bo po co ci ta klasa Privileges w ogóle w takim razie? o_O Skoro jedyne co w niej robisz to hardkodujesz jedna listę. A co jakbyś chciał mieć Usera który nie jest Adminem i ma inne uprawnienia? Czemu u ciebie uprawnienia ma tylko Admin?

Jak już logicznie o tym pomyśleć to krzesło i krzesło elektryczne mają ze sobą bardzo dużo wspólnego

To inna analogia: jedno z drugim ma się jak picie w Szczawnicy do szczania w piwnicy.

Klasa określa typ obiektu. Tak samo jak np. string, int czy list. Obiektów klasy możesz mieć dużo. Przyjmując analogie krzesła klasa Krzesło to jest diagram który opisuje jak wygląda krzesło i jak je zbudować, taka książeczka z ikei. Krzesło na którym siedzisz to jest obiekt klasy Krzesło.

0

@Shalom: Ok, chyba już rozumiem co masz na myśli.
Tylko to już tworzy bardziej rozbudowaną strukturę... Przykład, który wkleiłem jest zadaniem z książki dotyczącym dziedziczenia. Gdzie nauczyłem się robić klasy pochodne classa Admin oraz to o czym mówimy tutaj w głównej mierze to wykorzystanie egzemplarza jednej klasy jako atrybut innej klasy. I masz rację gdyby brać to na logikę to takie przypisani nie ma sensu.
Natomiast, żeby to miało sens. To klasa Privileges powinna mieć kilka atrybutów dla każdego rodzaju użytkownika. Czyli tak jak to jest teraz można wewnątrz tej klasy zrobić kilka atrybutów np. self.admin_privileges, self.user_privileges itd. I utworzyć metody, które wyświetlają komunikat dla każdego rodzaju użytkownika inną listę z uprawnieniami.

Albo jak było to kilka postów powyżej. Tworzą klasę Privileges i w konstruktorze deklaruje parametr privileges ale później w klasach dla różnych typów tych użytkowników muszę podać argument w postaci na przykład listy z uprawnieniami.

class User():
	"""Class containing information about user"""
	def __init__(self, first_name, last_name, login, sex, age):
		"""Initialization of attributes"""
		self.first_name = first_name
		self.last_name = last_name
		self.login = login
		self.sex = sex
		self.age = age
		self.login_attempts = 0
		self.privileges = Privileges(['może dodać posty', 'może edytować własne posty'])

	def describe_user(self):
		print(f"\nInformację o użytkowniku: {self.login}:")
		print(f"\tImię: {self.first_name.title()}")
		print(f"\tNazwisko: {self.last_name.title()}")
		print(f"\tPłeć: {self.sex}")
		print(f"\tWiek: {self.age}")

	def greet_user(self):
		print(f"Witaj! {self.first_name.title()} {self.last_name.title()}.")

	def increment_login_attempts(self):
		self.login_attempts += 1

	def reset_login_attempts(self):
		self.login_attempts = 0

	def show_login_attempts(self):
		print(f"Logowałeś się {self.login_attempts} razy!")

class Privileges():
	"""Class containing information about privileges"""
	def __init__(self, privileges):
		self.privileges = privileges
	def show_privileges(self):
		"""Shows Admin privileges"""
		
		print(f"Jako Admin może: {self.privileges}.")




class Admin(User):
	"""Class containing information about Admin"""
	def __init__(self, first_name, last_name, login, sex, age):
		"""
		Inicjalizacja atrybutów klasy nadrzędnej oraz atrybutów klasy Admin
		"""
		
		super().__init__(first_name, last_name, login, sex, age)
		self.privileges = Privileges(['może dodać posty', 'może usuwać posty', 'może zbanować użytkownika'])

	
	


user_0 = Admin('jan', 'kowalski', 'jkowal', 'male', 25,)
user_0.describe_user()
user_0.privileges.show_privileges()
user_0.greet_user()

user_1 = User('paweł', 'nowak', 'pnow', 'male', 30)
user_1.describe_user()
user_1.privileges.show_privileges()
user_1.greet_user()

Tylko w rzeczywistości takie coś też jest słabym rozwiązaniem. Bo to przypisanie poza wyświetlonym tekstem nic nie daje. Tak na prawdę każdy typ uprawnienia tworzenie postów, banowanie użytkownikó itd. Można by było zapisać jako oddzielny atrybut ? klasa ? tak, żeby przypisując je do nowego użytkownika faktycznie dawały mu jakieś dodatkowe możliwości.
Tylko to jest chyba zagadnienie nie na teraz dla mnie ;) tzn. muszę jeszcze lepiej się zorientować w tego typu zagadnieniach żeby móc napisać sensowniejszy kod.

Dzięki raz jeszcze :)

1

Tylko w rzeczywistości takie coś też jest słabym rozwiązaniem. Bo to przypisanie poza wyświetlonym tekstem nic nie daje.

Nie zgodzę się. A co jak dodamy do tej klasy privileges taką funkcje:

def has_privilege(self, name):
    return name in self.privileges

I teraz w klasie bazowej User robimy analogicznie:

def has_privilege(self, name):
    return self.privileges.has_privilege(name)

I teraz nagle mozemy zrobić taki myk:

print(user_0.has_privilege("może dodać posty"))
print(user_1.has_privilege("może zbanować użytkownika"))

Co gdybyś faktycznie coś implementował mogłoby się przydać do sprawdzania czy dany użytkownik może wykonać akcje którą próbuje wykonać...

0

Faktycznie takie rozwiązanie ma już sens, zapiszę sobie może kiedyś mi się przyda w przyszłości ;)

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