#πŸ”’ Can self.variable have said variable be flexible

114 messages Β· Page 1 of 1 (latest)

spiral iris
#

I don't know how exactly to be able to specify which self.variable to return without having to write an individual if statement for every single possible variable, or a separate function for every one. Does anyone have any ideas? I can provide more photos of other code parts if needed
Current example:
printing self.name -> test (which is correct)
printing f"self.{variable}" -> self.name
return exec(f"self.{variable}) -> None

lyric hemlockBOT
#

@spiral iris

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

spiral iris
#

Here are some additional pictures in case they are needed, I apologize for bad readabilty, I've never had clean code

acoustic kite
#

can you copy the code over here?

spiral iris
acoustic kite
#

would be enough

#

you can put the code into ```code here```

spiral iris
acoustic kite
#

```py
print("Hello World!")
print("Yes!")
```

print("Hello World!")
print("Yes!")
river monolith
#

!e if you want to see what variables you have in your class, you can always do this:

class MyClass:
    def __init__(self):
        self.name = "Some name"


my_class = MyClass()

print(my_class.__dict__.keys())```
lyric hemlockBOT
spiral iris
#
   def get_variable(self,variable):
        for possible_variable in list_of_variables:
            if possible_variable==variable:
               print(variable)
               return exec(f"self.{variable}")

            elif possible_variable == list_of_variables[-1] and variable!= possible_variable:
                print("Cannot find variable")```
drowsy light
#

return exec(f"self.{variable}") nooo

acoustic kite
#

yea, im working on a better solution, @spiral iris can you specify what is variable in your code and what do you want the function to do?

drowsy light
#

I think you're looking for the __getattr__ dunder that you can override

#

or

#

using @property 's

#

at the very least, you can do return getattr(self, variable) instead of exec

spiral iris
acoustic kite
#
    def get_variable(self,variable:str): # variable has to be string
        if variable in self.__dict__.keys():
            return self.__dict__[variable]
        else:
            print("cannot find variable")
drowsy light
spiral iris
final frigate
#

You don't normally make getters and setters in python

drowsy light
#

and if you need to, you make property's

acoustic kite
spiral iris
drowsy light
#

Just access the variables directly

acoustic kite
drowsy light
#

python already handles all the cannot find variable stuff

#

!e

import this
lyric hemlockBOT
# drowsy light !e ```py import this ```

:white_check_mark: Your 3.12 eval job has completed with return code 0.

001 | The Zen of Python, by Tim Peters
002 | 
003 | Beautiful is better than ugly.
004 | Explicit is better than implicit.
005 | Simple is better than complex.
006 | Complex is better than complicated.
007 | Flat is better than nested.
008 | Sparse is better than dense.
009 | Readability counts.
010 | Special cases aren't special enough to break the rules.
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/5DUJKAIEISXDCXNTGUZLFBDHFI

drowsy light
#

Simple is better than complex.

acoustic kite
spiral iris
left notch
#

and there is no such thing as private or protected attributes or such in python, everything is generally accessible

acoustic kite
drowsy light
#

also just scrap this whole thing and access variables directly

spiral iris
acoustic kite
drowsy light
#

I get it. But there's nothing wrong with saying "you shouldn't actually do it that way" imo

acoustic kite
spiral iris
#

Could I ask one more question

final frigate
#

There's no limit on questions

spiral iris
#

what exactly does dict do, since I want to understand the code so i can manipulate it

left notch
#

__dict__ holds all attributes and methods/functions of a class in a dictionary

acoustic kite
left notch
#

what language are you coming from to python, java maybe?

spiral iris
#

Scratch excluded

left notch
acoustic kite
# spiral iris I think?

So class.__dict__ creates a dictionary of all variables and functions inside of a class
So if you have self.value = "hi"
self.__dict__ will hold {"value" : "hi"}

left notch
#

python is an excellent language to pick up then

spiral iris
spiral iris
acoustic kite
spiral iris
#

I will go back to my project now, and will be rememebring all of you for the help offered
Thank you very much!

acoustic kite
#

No problem, happy to help

left notch
#

you are always welcome to come back and ask more questions πŸ™‚

spiral iris
# acoustic kite Perfect, just try to never use exec or eval in your code, it might be dangerous
    def set_variable(self,old_variable,new_variable):
        for possible_variable in list_of_variables:
            if old_variable == possible_variable:
                if old_variable == "texture":
                    try:
                        pygame.image.load(str(f"graphics/{new_variable}")).convert_alpha()
                    except FileNotFoundError:
                        self.button_surf = pygame.image.load("graphics/Default Texture.png").convert_alpha()
                    else:
                        self.texture = f"graphics/{str(new_variable)}"
                        self.button_surf = pygame.image.load(str(self.texture)).convert_alpha()

                else:
                    exec (f"self.{old_variable}={new_variable}")
                break
            elif possible_variable == list_of_variables[-1] and old_variable!= possible_variable:
                print("Not a correct variable")```

I was revewing my code to see if anything was affected by the change with get_variable, and saw I had this exec in my code. Should I remove it?
And sorry for the ping!
acoustic kite
#

oh also, one thing that might help you:
instead of elif possible_variable == list_of_variables[-1] and old_variable!= possible_variable:
at the end of the loop just do this:

for possible_variable in list_of_variables:
    ... # do something here
    break # use this is it has been done
else:
   print("Not a correct variable") # this will run if break was not executed in the for loop
spiral iris
#

I'm wondering how and if I should remove it
And thank you for the suggestion, I don't know why I didn't think of that myself

acoustic kite
#

however, I think you can remove the entire loop inside of your code

spiral iris
acoustic kite
left notch
#

there is also the getattr() and setattr() functions

spiral iris
spiral iris
acoustic kite
# spiral iris ```py def set_variable(self,old_variable,new_variable): for possible...
    def set_variable(self,old_variable,new_variable):
        if old_variable in self.__dict__: # we will check if old variable is inside of our class variables
            if old_variable == "texture": # now we check if its texture
                if os.path.exists(f"graphics/{new_variable}"): # we use "os" module to check if the file exists
                    self.texture = f"graphics/{new_variable}" # if yes we use this texture
                else:
                    self.texture = "graphics/Default Texture.png" # otherwise we use default one
                self.button_surf = pygame.image.load(self.texture).convert_alpha() # now we just load the image
            else:
                self.__dict__[old_variable] = new_variable # we will change the "self.{old_variable}" to "new_variable"
        else: # its not in our class
            print("Not a correct variable")```
final frigate
acoustic kite
left notch
#

if you are going to even test for it's existence before just trying to access it

final frigate
#

Just making texture a property and using other variables directly is what i would do

spiral iris
left notch
#

nothing is sealed away in python

acoustic kite
#

well, if you need my help please ping me I have to go for now

left notch
#

you can always access any property of a class/instance/object from outside

spiral iris
spiral iris
# left notch nothing is sealed away in python

Then allow me to rephrase
It gives me a much needed but false sense of security

I'm primarily afraid of messing my already atrocious code up even more by skipping the middleman and accessing class variables directly

spiral iris
#

Still, thanks a lot for recommending alternatives I might actually use later down the project when I become more confident in my skills

left notch
#

are you familiar with LBYL (look before you leap) and EAFP (easier to ask forgiveness than permission)?
python mostly leans towards the last one

left notch
#

the short of it is that it's often recommended to just try to access something in a try block and handle the exception if that happens, unless you think it will be a very common code path, then it might be better to first test for existence for performance reasons

spiral iris
#

That's a bit contradictory for my type of coding, I don't really work with stuff that doesn't exist unless I am at least 90% sure I can poof it into existence, hence I never really had a use for try up until this project

left notch
naive mist
left notch
naive mist
#

Then use __slots__

left notch
#

ha ha, true

spiral iris
naive mist
#

!e

class Foo:
    __slots__ = ["a", "b"]

    def __init__(self, a, b):
        self.a = a
        self.b = b

f = Foo(9, 10)
print(f.a)
f.c = "blow up, please"
lyric hemlockBOT
naive mist
left notch
naive mist
#

Often times the thing you're trying to guard against isn't really that much of a problem when you get down to it.
How often is someone trying to add an attribute that shouldn't exist onto a class instance?
If they want to, what's the harm?

spiral iris
# left notch what do you mean that you needed to learn pygame to "open a window"?

my third program was essentially an incredibly scuffed minesweeper, right after learning how to use the random module in my first program, and how to access exit code colors in my second.
I had to do the whole "gui" part of minesweeper in console, and becuse I'm no artist, the only way I could advance was learn to manipulate some form of proper window with png textures

final frigate
#
import pygame
from pathlib import Path


class Example:
    DEFAULT_TEXTURE = Path("graphics") / "Default Texture.png"
    _texture: Path
    button_surf: pygame.Surface

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

    @property
    def texture(self):
        return self._texture

    @texture.setter
    def texture(self, value):
        new_path = Path("graphics") / value
        if new_path.exists():
            self._texture = new_path
        else:
            self._texture = self.DEFAULT_TEXTURE
        self.button_surf = pygame.image.load(self.texture).convert_alpha()```
example with property
spiral iris
naive mist
#

Patience. It doesn't come naturally, or quickly.

#

Short version is that properties look like attribute access, but they act like the getter/setter pattern.
def texture(self) is the getter, returning a value.

The one decorated by @texture.setter is the setter method, taking a value arg. This is called when doing .texture = "blah".

So in the __init__, self.texture = ... is calling that setter.

left notch
final frigate
#

Don't undersell yourself, you were able to come up with that complicated setter you had yourself

naive mist
#

Agreed, you had the pattern in mind. We're demonstrating some better tools for it. πŸ™‚

spiral iris
#

You're all incredibly helpful and kind people, I thank you all with as much sincerity as I can

lyric hemlockBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.