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.
Vad blir det för fel?
'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.
Så vad är felet nu?
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.
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.
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 bortself.numerator = (numerator)
ochself.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)
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.
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
Jag ser att abs(self.denominator+1) ska vara abs(self.denominator)+1.
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?
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.