Python Forum
class, attribute and method - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: class, attribute and method (/thread-36506.html)



class, attribute and method - Frankduc - Feb-26-2022

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?


RE: class, attribute and method - ibreeden - Feb-26-2022

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.)


RE: class, attribute and method - deanhystad - Feb-26-2022

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.


RE: class, attribute and method - Frankduc - Feb-26-2022

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



RE: class, attribute and method - snippsat - Feb-26-2022

(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 *



RE: class, attribute and method - deanhystad - Feb-27-2022

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?


RE: class, attribute and method - Frankduc - Feb-27-2022

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.


RE: class, attribute and method - deanhystad - Feb-27-2022

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()



RE: class, attribute and method - Frankduc - Feb-27-2022

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.


RE: class, attribute and method - deanhystad - Feb-27-2022

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.