11 svar
122 visningar
Kemibiologi1999 är nöjd med hjälpen
Kemibiologi1999 43
Postad: 2 dec 2021 19:04

Använda instansmetoder inuti andra instansmetoder hos samma klass

Jag försöker skapa en klass Rational som tar in ett eller två värden när den deklareras, och därefter returnerar bråket i förenklad form.

 

Om r = Rational(20, 4)

så vill jag att följande skall vara sant:

print(r.get_num() == 5 and r.get_denom() == 1)

class Rational:

    def __init__(self,numerator, denominator = 1):
        self.numerator = numerator
        self.denominator = denominator

    def cd_numerators(self):
        list_cd_numerators = []
        for i in range(1, self.numerator):
            if self.numerator % i == 0:
                list_cd_numerators.append(i)
        return list_cd_numerators

    def cd_denominators(self):
        list_cd_denominators = []
        for i in range(1, self.denominator):
            if self.denominator % i == 0:
                list_cd_denominators = []
        return list_cd_denominators


    def highest_common_denominator(self, a, b):
        highest_common_denominator1 = 1
        for i in a:
            if i in b:
                highest_common_denominator1 = i
        return highest_common_denominator1

    def get_num(self):
        common_denominator = highest_common_denominator(cd_numerators,cd_denominators)
        numerator = self.numerator / common_denominator
        return numerator

    def get_denom(self):
        common_denominator = highest_common_denominator( cd_numerators,cd_denominators)
        denominator = self.denominator / common_denominator
        return denominator

 

 

Detta är min kod. Jag förstår inte vart jag har vandrat fel. 

Laguna Online 28419
Postad: 2 dec 2021 19:28

Vad blir det för fel?

Kemibiologi1999 43
Postad: 2 dec 2021 19:30

'NameError: name 'highest_common_denominator' is not defined.'

 

 

Löste dock detta genom att lägga till ett par self. vid olika metoder/variabler.

class Rational:

    def __init__(self, numerator, denominator=1):
        self.numerator = numerator
        self.denominator = denominator

    def cd_numerators(self):
        list_cd_numerators = []
        for i in range(1, int(self.numerator)):
            if self.numerator % i == 0:
                list_cd_numerators.append(i)
        return list_cd_numerators

    def cd_denominators(self):
        list_cd_denominators = []
        for i in range(1, int(self.denominator)):
            if self.denominator % i == 0:
                list_cd_denominators.append(i)
        return list_cd_denominators

    def highest_common_denominator(self, a, b):
        highest_common_denominator1 = 1
        for i in a:
            if i in b:
                highest_common_denominator1 = i
        return highest_common_denominator1

    def get_num(self):
        common_denominator = self.highest_common_denominator(self.cd_numerators(), self.cd_denominators())
        numerator = self.numerator / common_denominator
        self.numerator = (numerator)
        print(self.numerator)
        return int(self.numerator)

    def get_denom(self):
        common_denominator = self.highest_common_denominator(self.cd_numerators(), self.cd_denominators())
        denominator = self.denominator / common_denominator
        self.denominator == int(denominator)
        print(self.denominator)
        return self.denominator

 

Detta ger mig rätt på cirka hälften av de värden jag testar för. Jag lyckas inte med att förstå vad felet är.

Laguna Online 28419
Postad: 2 dec 2021 19:34

Så vad är felet nu?

Kemibiologi1999 43
Postad: 2 dec 2021 19:37

TypeError: unsupported operand type(s) for +: 'Rational' and 'Rational'
2.0
1
True
4.0
9
True
7.0
168
False
10.0
False
0.0
1
True
-49.0
False
49.0
False
-49.0
False

 

Jag får detta nu.

Laguna Online 28419
Postad: 2 dec 2021 19:56

Jag vet inte var alla dessa siffror kommer ifrån, men felutskriften säger att din klass inte vet hur man gör + på två instanser. Tydligen vill någon göra det.

Programmeraren 3387
Postad: 2 dec 2021 21:00 Redigerad: 2 dec 2021 21:13

Från utskriften förstår vi att vi inte ser hela programmet.

Uppgiften heter "Använda instansmetoder inuti andra instansmetoder hos samma klass".
Tittar man på koden så ser man metoder som innehåller samma kod med enda skillnaden att de opererar på olika variabler i klassen. Du bör rensa bort dubletter. T ex är cd_numerators() och cd_denominators() i princip samma metod. Gör istället en metod
cd(n)
som tar talet den ska hitta vilka delare det finns i. Sen kan anropa den med cd(numerator) och cd(denominator).
Det fixar inte felet men gör koden snyggare.

Dina get-metoder ser konstiga ut: När det förkortade värdet har beräknats så lagrar du det i variabeln. Men då kommer nästa get misslyckas eftersom du förkortat.
Om du har (2*3*5*7)/(3*5):
(2*3*5*7 förkortas till 2*7 i get_num( och lagras. Sen ropar du på get_denom men då finns det inga 3*5 kvar i täljaren som kan hittas av metoderna som hittar alla faktorer.
Dvs ta bort
self.numerator = (numerator)
och
self.denominator == int(denominator)
(som dessutom är fel ändå) och ändra print och return-raderna till:

print(numerator)
return numerator

respektive

print(denominator)
return denominator

MEN: jag gissar att du lagrar för att varje anrop ska "skala av" en faktor. Om det är så får du beräkna både nya täljaren och nya nämnaren i en metod och SEN uppdatera båda värdena (t ex göra all beräkning och uppdatering i get_num och bara returnera värdet i get_denom)

Jag tror inte du behöver ha self när du ropar på en metod från en annan (men som sagt, jag kan inte Python så kan ha fel)

CurtJ 1141
Postad: 3 dec 2021 05:39

Det ser inte så tokigt ut men jag ser några grundläggande fel

I cd_numerators, cd_denominators så skapar du en lista från 1 upp till värdet. Jag gissar att den övre gränsen ska vara med så lägg till +1 i din range.

Som @programmeraren säger ovan så skriver du över dina värden för dina instansvariabler nominator och denominator i get_num och get_denom vilket gör att anropet till get_denom blir fel så ta bort de överskrivningarna. I överskrivningen av self.numerator har du dessutom glömt en int().

Med det så borde det fungera som avsett.

Sen kan man fundera på om det är det mest effektiva sättet att lösa det här problemet men uppgiften var att testa att använda instansmetoder i andra instansmetoder och det syftet är uppfyllt.

Kemibiologi1999 43
Postad: 4 dec 2021 10:11

Jag ändrade min kod enligt det ni skrev. När man använder sig av positiva argument fungerar det finfint. När man använder sig av ett negativt tal i argumentet för denominator så returnerar dock get_denom ingenting. Jag har felsökt väldigt länge, men kan inte se att jag någonsin gör någonting som får värdet på self.denominator att ändras. Någon som kan se vad jag gör fel?

class Rational:

        def __init__(self, numerator, denominator=1):
            self.numerator = numerator
            self.denominator = denominator

        def cd_numerators(self):
            list_cd_numerators = []
            for i in range(1, abs(self.numerator+1)):
                if abs(self.numerator) % i == 0:
                    list_cd_numerators.append(i)
            return list_cd_numerators

        def cd_denominators(self):
            list_cd_denominators = []
            for i in range(1, abs(self.denominator+1)):
                if abs(self.denominator) % i == 0:
                    list_cd_denominators.append(i)
            return list_cd_denominators

        def highest_common_denominator(self, a, b):
            highest_common_denominator1 = 1
            for i in a:
                if i in b:
                    highest_common_denominator1 = i
            return highest_common_denominator1

        def get_num(self):
            common_denominator = self.highest_common_denominator(self.cd_numerators(), self.cd_denominators())
            numerator = self.numerator / common_denominator
            return numerator

        def get_denom(self):
            common_denominator = self.highest_common_denominator(self.cd_numerators(), self.cd_denominators())
            denominator = self.denominator / common_denominator
            return denominator

Laguna Online 28419
Postad: 4 dec 2021 11:57

Jag ser att abs(self.denominator+1) ska vara abs(self.denominator)+1.

Kemibiologi1999 43
Postad: 4 dec 2021 12:03

Tack så mycket! Jag lyckades lösa denna nu.

r1 = Rational(1, 4)
r3 = Rational(r1)
print(type(r3))
print(r3 == r1) 

Jag undrar bara om du förstår denna?

Jag ska "overrida" den inbyggda funktionen __eq__ så att det ovanstående skriver ut True.

 

Problemet blir ju bara att min type(r3) ger mig Rational.Rational, vilket alltså skiljer sig från r1 som har typen Rational. Är det något fel på frågan eller är detta tillåtet?

Programmeraren 3387
Postad: 4 dec 2021 15:09

Vi ser inte hela din kod men du har en constructor (__init__) som tar täljare och nämnare som argument.
Men andra raden tar en annan Rational som argument vilket verkar vara sett sätt skapa en kopia. Har du kod till den constructorn?

Båda borde dock vara av type Rational. Rational.Rational låter som att du upprepat koden i din fil. Kan du ha sparat en kopia av Rational i samma textfil för att ha kvar den uti fall ändringarna blir fel? I så fall, lägg allt sån extrakod i en fil för anteckningar och rensa Rational-filen.

"overrida" den inbyggda funktionen __eq__ betyder att du ska skapa en __eq__ som returnerar true när dess argument som är en annan Rational är likadan. Alltså när täljare och nämnare är samma. Annars ska den returnera false.

Svara Avbryt
Close