Python Forum
how to use getter as argument in function - 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: how to use getter as argument in function (/thread-26766.html)



how to use getter as argument in function - nanok66 - May-13-2020

Hi,

I am starting to become familiar with using getters and setters but I'm stumped on this example of using a getter within a function. The closest I get when I open the tkinter page is that is says "property located at 0x03B0A1F" but of course I am looking for the integer value.


from tkinter import *

class Settings:
    def __init__(self):
        self._rinse = 16


    @property
    def rinse(self):
        return self._rinse

    @rinse.setter
    def rinse(self, value):
        self._rinse = value


settingsPage = Tk()
settingsPage.geometry("1024x600")


def new_setting(getter_name, row):
    s = Settings()
    value_lbl = Label(text=s.getter_name, master=settingsPage)   #error here, with getter_name.
    value_lbl.grid(row=row, column=0)


new_setting(rinse, 1)   # error here, does not recognize "rinse"

settingsPage.mainloop()



RE: how to use getter as argument in function - Larz60+ - May-13-2020

getters and setters are Java.
They are not needed (nor wanted) with python


RE: how to use getter as argument in function - deanhystad - May-13-2020

I'm having a tough time understanding what it is you want to do.

rinse is a property of Settings, but when used by itself it means nothing. Where is rinse defined within the scope where new_setting is called?

If you really want, you could try looking up the attribute by name, but properties make this difficult.
class Settings:
    def __init__(self):
        self._rinse = 10
        self.dry = 20

    def set_dry(self, value):
        self.dry = value

    @property
    def rinse(self):
        return self._rinse
 
    @rinse.setter
    def rinse(self, value):
        self._rinse = value
 
settings = Settings()
rinse = getattr(settings, 'rinse')  # Try to get property
dry = getattr(settings, 'dry') # Try to get attribute
dry_setter = getattr(settings, 'set_dry') # Try to get function
rinse = 15
dry = 25
print(rinse, '!=', settings.rinse, dry, '!=', settings.dry)
dry_setter(dry)
print(dry, '==', settings.dry)
Output:
15 != 10 25 != 20 25 == 25
As you can see, getattr does a fine job at getting the value of the named attribute, but the resulting rinse and dry are not instance variables of settings, they are local variables that were set to the value of settings.rinse and settings.dry.

Having a setter function that you can bind to works a lot better. A function works like a function even if you are using a local variable to call the function.

I think properties work really well in C#, but the python implementation is clunky, and from what I can see, offers no benefits. A property provides no protection to your instance variables. A property usually means you'll be writing a function if you want to change the property value as the result of an event. Even with the new @property/@property.setter decorators the syntax is clunky and confusing. Which one gets the doc string?


RE: how to use getter as argument in function - nanok66 - May-13-2020

Sorry I guess I only vaguely stated my question. I was having trouble bringing my getter value through my new_setting function.

But I found my issue. Weird combining of syntax and misplaced lines, felt like I was so far away but fairly simple fix.

Thanks Larz, I do like the idea of less code! Plus it's all my standalone program so I don't have to interface with other code so I could truly write it any way that works.

And thanks again Dean, you explain thoroughly and show great examples. I think you nailed it in your second sentence, defining rinse where my new setting is called.

For anyone who finds themselves stuck in this learning curve here's my mistakes and simple solution:
from tkinter import *

class Settings:
    def __init__(self):
        self._rinse = 16


    @property
    def rinse(self):
        return self._rinse

    @rinse.setter
    def rinse(self, value):
        self._rinse = value


settingsPage = Tk()
settingsPage.geometry("1024x600")


def new_setting(getter_name, row):
    #s = Settings()     # I mistakenly thought the instance should be created here and combined with getter_name
    value_lbl = Label(text=getter_name, master=settingsPage)  # previously s.getter_name  
    value_lbl.grid(row=row, column=0)

s = Settings()       # the correct place for the instance
new_setting(s.rinse, 1)   # previously: new_setting(rinse, 1)

settingsPage.mainloop()