Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
class, attribute and method
#1
Hello,

Its been a few hours i am struggling with this code. I am having a hard time understanding the use of classes and constructors.

from tkinter import *


class Temperature:
    valeur = 0

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

def conversionF(self):
    if choix.get() == 'Celcius à Fahrenheit':
        resultat = float((9 * self.valeur) / 5 + 32)
        resultat.configure(text=str(fahrenheit))

    else:
        def conversionC(self):
                resultat = float((self.valeur - 32) * 5 / 9)
                resultat.configure(text=str(celcius))


def changement(event):
    if choix.get() == 'Celcius à Fahrenheit':
        txt1.configure(text='Température en Celcius')
        txt2.configure(text='Température en Fahrenheit')
    else:
        txt2.configure(text='Température en Celcius')
        txt1.configure(text='Température en Fahrenheit')


fen1 = Tk()
fen1.title('Conversion')

txt1 = Label(fen1, text='Température en Fahrenheit')
txt1.grid(row=0, column=0, sticky=E)

entree = Entry(fen1)
entree.grid(row=0, column=1)

txt2 = Label(fen1, text='Température en Celcius')
txt2.grid(row=1, column=0, sticky=E)

resultat = Label(fen1, text='')
resultat.grid(row=1, column=1)

bouton = Button(fen1, text='Conversion', command = conversionF)
bouton.grid(row=2, column=0)

bouton = Button(fen1, text='Conversion', command = conversionC)
bouton.grid(row=2, column=0)

choix = StringVar(fen1)
choix.set('Celcius à Fahrenheit')
liste = OptionMenu(fen1, choix, 'Celcius à Fahrenheit', 'Fahrenheit à Celcius', command=changement)

liste.grid(row=2, column=1)

fen1.mainloop()
I get this error message about conversionC() missing 1 required positional argument: 'self'

What does it mean?
Reply
#2
Please give the complete error stack trace. On which line does this error occur? Is it on line 48? And if so does the error change after executing "changement"?
(I guess there is something wrong with the indentation. Presumably __init() to changement() are methods of class Temperature. If so lines 7 to 27 have to be indented by 4 spaces.)
Reply
#3
I get "conversionC" is not defined because for some reason you try to define it after an else:

After I fixed that I get
Error:
File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1883, in __call__ return self.func(*args) TypeError: conversionC() missing 1 required positional argument: 'self'
when I press the Conversion button.

You have an indentation problem. Your class should be indented like this:
class Temperature:
    # valeur = 0   <- This creates a class variable.  You don't want to do this.

    def __init__(self, valeur):
        self.valeur = valeur  # This creates an instance variable.  You want to do this.

    def conversionF(self):
Without the indentation def__init__(self, valeur) and conversionF are standalone functions, not methods of class Temperature.

You have a history of sloppy indenting. Maybe now you see that indentation s important.
Reply
#4
I really hate indenting.

If i do that

from tkinter import *


class Temperature:
   # valeur = 0


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

    
    def conversionF(self):
        if choix.get() == 'Celcius à Fahrenheit':
            resultat = float((9 * self.valeur) / 5 + 32)
            resultat.configure(text=str(fahrenheit))

        else:
            def conversionC(self):
                resultat = float((self.valeur - 32) * 5 / 9)
                resultat.configure(text=str(celcius))


def changement(event):
    if choix.get() == 'Celcius à Fahrenheit':
        txt1.configure(text='Température en Celcius')
        txt2.configure(text='Température en Fahrenheit')
    else:
        txt2.configure(text='Température en Celcius')
        txt1.configure(text='Température en Fahrenheit')


fen1 = Tk()
fen1.title('Conversion')

txt1 = Label(fen1, text='Température en Fahrenheit')
txt1.grid(row=0, column=0, sticky=E)

entree = Entry(fen1)
entree.grid(row=0, column=1)

txt2 = Label(fen1, text='Température en Celcius')
txt2.grid(row=1, column=0, sticky=E)

resultat = Label(fen1, text='')
resultat.grid(row=1, column=1)

bouton = Button(fen1, text='Conversion', command=conversionF)
bouton.grid(row=2, column=0)

bouton = Button(fen1, text='Conversion', command=conversionC)
bouton.grid(row=2, column=0)

choix = StringVar(fen1)
choix.set('Celcius à Fahrenheit')
liste = OptionMenu(fen1, choix, 'Celcius à Fahrenheit', 'Fahrenheit à Celcius', command=changement)

liste.grid(row=2, column=1)

fen1.mainloop()
If i do that it reply:

Output:
Traceback (most recent call last): File "C:\Users\faceo\PycharmProjects\pythonProject18\main.py", line 53, in <module> bouton = Button(fen1, text='Conversion', command=conversionF) NameError: name 'conversionF' is not defined Process finished with exit code 1
without the indent i get:

Output:
File "C:\Users\faceo\PycharmProjects\pythonProject18\main.py", line 14 def __init__(self, valeur): ^ IndentationError: expected an indented block Process finished with exit code 1
Reply
#5
(Feb-26-2022, 05:15 PM)Frankduc Wrote: I am having a hard time understanding the use of classes and constructors.
You should not mix in GUI before you understand the basic of using class(OOP).
Your Temperature class is messy should not have else then a new function.
Like this just two methods.
class Temperature:
    def __init__(self, temp):
        self.temp = temp

    def convert_to_fahrenheit(self):
        result = float((9 * self.temp) / 5 + 32)
        return result

    def convert_to_celsius(self):
        result = float((self.temp - 32) * 5 / 9)
        return result
Use class:
>>> temp = Temperature(50)
>>> temp.temp
50
>>> 
>>> temp.convert_to_celsius()
10.0
>>> temp.convert_to_fahrenheit()
122.0
Now can add to GUI,and is better to write GUI also with classes.
Look this Tkinter tutorial that dos this exactly task.
Also the tutorial on site in link is good,that not some common as there are many not so good(old) Tkinter tutorial out there.

As mention to you before no 👎 👀
from tkinter import *
Reply
#6
I agree with snippsat. You are not ready for GUI programming. Learn about classes and it will help you learn everything else in Python, especially GUI programming.

Do you hate punctuation? Indenting is just as much punctuation in Python as {} and ; are in C/C++. Python is not going to care that you don't like nicely formatted code that is easy to read and debug. Hey! Shouldn't you want your code to be nicely formatted and easy to read and debug?
Reply
#7
Ready or not its in Chap 10. There is no chapter on classes. Chap 9 are about GUI and it jump to GUI with classes in Chap 10. I am getting ahead with assigments. We should learn about this in 2 weeks. But i still want to know it right now. After that its over for introduction to python and will jump into another course.

I tried that approach before asking the forum. I had my 3 Def but was not able to make it work.

from tkinter import *


class Temperature:
    def __init__(self, temp):
        self.temp = temp

    def convert_to_fahrenheit(self):
        if choix.get() == 'Celcius à Fahrenheit':
            resultat = float((9 * self.temp) / 5 + 32)
            resultat.configure(text=str(fahrenheit))

    def convert_to_celsius(self):
        resultat = float((self.temp - 32) * 5 / 9)
        resultat.configure(text=str(celcius))

temp = Temperature(50)
temp.temp

temp.convert_to_celsius()
temp.convert_to_fahrenheit()

def changement(event):
    if choix.get() == 'Celcius à Fahrenheit':
        txt1.configure(text='Température en Celcius')
        txt2.configure(text='Température en Fahrenheit')
    else:
        txt2.configure(text='Température en Celcius')
        txt1.configure(text='Température en Fahrenheit')


fen1 = Tk()
fen1.title('Conversion')

txt1 = Label(fen1, text='Température en Fahrenheit')
txt1.grid(row=0, column=0, sticky=E)

entree = Entry(fen1)
entree.grid(row=0, column=1)

txt2 = Label(fen1, text='Température en Celcius')
txt2.grid(row=1, column=0, sticky=E)

resultat = Label(fen1, text='')
resultat.grid(row=1, column=1)

bouton = Button(fen1, text='Conversion', command=conversionF)
bouton.grid(row=2, column=0)

bouton = Button(fen1, text='Conversion', command=conversionC)
bouton.grid(row=2, column=0)

choix = StringVar(fen1)
choix.set('Celcius à Fahrenheit')
liste = OptionMenu(fen1, choix, 'Celcius à Fahrenheit', 'Fahrenheit à Celcius', command=changement)

liste.grid(row=2, column=1)

fen1.mainloop()
I am puzzle to what to do with the if choix.get() == 'Celcius à Fahrenheit':. With 2 function how can i choose between celcius and fahrenheit?

Do i need two buttons, one for celcius and one for fahrenheit?

As for from tkinter import * for now i am making two version of it, this one from the book and the one from snipp. If i throw that into an assigment he's gonna give me a zero.

I think its more easy with brackets, you can vizualize them. Now they look invisible.
Reply
#8
I liked brackets and semicolons better when I started programming Python. Now I think C/C++ looks hideous.

Your program is a mess. Your book probably is telling you all the wrong things starting with "from tkinter import *", not using textvariable for entries, making your main window in a main() function, or worse yet, as a bunch of function calls. I think there is more bad advice about how to use tkinter than any other Python package. Much of this is due to its age. I was using Tk back in the 90's and I can see a lot of that Tk in tkinter (TK INTERface).

This is your program written how I would write it. Some may argue against subclassing Tk for the root window, but I think it makes a very clean class.
import tkinter as tk

class Temperature(tk.Tk):
    """Temperature conversion program"""
    convert_c2f = 'Celcius à Fahrenheit'
    convert_f2c = 'Fahrenheit à Celcius'
    conversions = (convert_c2f, convert_f2c)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.title('Conversion')
 
        # Enter/display temperature in degrees F
        self.fahrenheit = tk.DoubleVar(value=0.0)
        tk.Label(self, text='Température en Fahrenheit') \
            .grid(row=0, column=0, sticky=tk.E)
        tk.Entry(self, textvariable=self.fahrenheit, width=10, justify=tk.RIGHT) \
            .grid(row=0, column=1)

        # Enter/display temperature in degrees C
        self.celcius = tk.DoubleVar(value=0.0)
        tk.Label(self, text='Température en Celcius') \
            .grid(row=1, column=0, sticky=tk.E)
        tk.Entry(self, textvariable=self.celcius, width=10, justify=tk.RIGHT) \
            .grid(row=1, column=1)

        # Select C->F F->C
        self.choix = tk.StringVar(value=self.convert_c2f)
        tk.OptionMenu(self, self.choix, *self.conversions) \
            .grid(row=2, column=1)

        # Do conversion when button pressed
        tk.Button(self, text='Convert', command=self.convert) \
            .grid(row=2, column=0)
        self.convert()

    def convert(self):
        """Perform temperature conversion"""
        if self.choix.get() == self.convert_c2f:
            self.fahrenheit.set((9 * self.celcius.get()) / 5 + 32)
        else:
            self.celcius.set((self.fahrenheit.get() - 32) * 5 / 9)

if __name__ == '__main__':
    Temperature().mainloop()
ibreeden and Frankduc like this post
Reply
#9
In the late 90's? You must be close to my age than. You guess it, its a late career change for me.
We are not quite there yet, your code works one side on my part.

The assigment is asking for one class call value.
Constructor initialize to 0
The class must have 2 other methods obviously for Celcius and Fahrenheit.
What they want is a reproduction of this first version i did for a previous chapter.

from tkinter import *


def conversion():
    if choix.get() == 'Celcius à Fahrenheit':
        celcius = float(entree.get())
        fahrenheit = (celcius * 1.8) + 32
        resultat.configure(text=str(fahrenheit))

    else:
        fahrenheit = float(entree.get())
        celcius = (fahrenheit - 32) / 1.8
        resultat.configure(text=str(celcius))


def changement(event):
    if choix.get() == 'Celcius à Fahrenheit':
        txt1.configure(text='Température en Celcius')
        txt2.configure(text='Température en Fahrenheit')
    else:
        txt2.configure(text='Température en Celcius')
        txt1.configure(text='Température en Fahrenheit')


fen1 = Tk()
fen1.title('Conversion')

txt1 = Label(fen1, text='Température en Fahrenheit')
txt1.grid(row=0, column=0, sticky=E)

entree = Entry(fen1)
entree.grid(row=0, column=1)

txt2 = Label(fen1, text='Température en Celcius')
txt2.grid(row=1, column=0, sticky=E)

resultat = Label(fen1, text='')
resultat.grid(row=1, column=1)

bouton = Button(fen1, text='Conversion', command=conversion)
bouton.grid(row=2, column=0)

choix = StringVar(fen1)
choix.set('Celcius à Fahrenheit')
liste = OptionMenu(fen1, choix, 'Celcius à Fahrenheit', 'Fahrenheit à Celcius', command=changement)

liste.grid(row=2, column=1)

fen1.mainloop()
Now that i understand that this part is need it to make it work:

temp = Temperature(50)
temp.temp
 
temp.convert_to_celsius()
temp.convert_to_fahrenheit()
I can focus on the rest. How to reuse this part
if choix.get() == 'Celcius à Fahrenheit':
is bugging me.

Thank you anyway for your help. Ill figure it out soon or later.
Reply
#10
My example converts from Celsius to Fahrenheit of Fahrenheit to Celsius based on the selection in the option menu. It has one method that is called to do the conversion. To convert from Celsius to Fahrenheit type a number in the Celsius entry, set the option to convert to Fahrenheit, press the convert button. To convert from Fahrenheit to Celsius type the number in the Fahrenheit entry, set the option to convert to Celsius, press the convert button.
Frankduc likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  class definition and problem with a method HerrAyas 2 267 Apr-01-2024, 03:34 PM
Last Post: HerrAyas
  super() and order of running method in class inheritance akbarza 7 759 Feb-04-2024, 09:35 AM
Last Post: Gribouillis
  Initiating an attribute in a class __init__: question billykid999 8 1,360 May-02-2023, 09:09 PM
Last Post: billykid999
  Using one child class method in another child class garynewport 5 1,610 Jan-11-2023, 06:07 PM
Last Post: garynewport
  [Solved] Novice question to OOP: can a method of class A access attributes of class B BigMan 1 1,324 Mar-14-2022, 11:21 PM
Last Post: deanhystad
  Subclass initialized property used in parent class method. Is it bad coding practice? saavedra29 5 1,802 Feb-07-2022, 07:29 PM
Last Post: saavedra29
  Class Method to Calculate Age Doesn't Work gdbengo 1 1,717 Oct-30-2021, 11:20 PM
Last Post: Yoriz
  anonymous method in a class Skaperen 8 3,610 May-23-2021, 11:17 PM
Last Post: Skaperen
  Python generics: How to infer generic type from class attribute? Thoufak 0 2,830 Apr-25-2021, 09:31 AM
Last Post: Thoufak
  AttributeError class object has no attribute list object scttfnch 5 3,472 Feb-24-2021, 10:03 PM
Last Post: scttfnch

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020