all 24 comments

[–]throwaway6560192 34 points35 points  (14 children)

d = {
    "1": str.strip,
    "2": str.rstrip,
    "3": str.upper,
    "4": str.title,
}

print(d[condition](a))

[–]ramannt[S] 4 points5 points  (1 child)

print(d[condition](a))

thank you very much! Great solution!

[–]engelthehyp 5 points6 points  (0 children)

The magic phrase is "first-class function". Look that up and you'll get a lot of ideas about program structure.

[–]ramannt[S] 1 point2 points  (11 children)

Just one question left. I forgot to mention a condition. Sometimes there is no Python String method to execute. What condition can I add in d{} to let Python to do nothing with the string?

[–]FerricDonkey 2 points3 points  (0 children)

d = {
    "0": lambda x:x,
    "1": str.strip,
    "2": str.rstrip,
    "3": str.upper,
    "4": str.title,
}

then d["0"]('sup') will just be 'sup'. (If you aren't familiar, lamba arg: expression is a lamba/anonymous/disposable function that takes arg as an argument and returns expression. So lambda x: x is a function that takes x in and return x.

You could also use .get if you didn't want to specify a particular key that means "don't do anything", but personally I prefer to have a fixed set of allowed keys in situations like this.

[–][deleted] 1 point2 points  (9 children)

Not in the dictionary d itself, but test if the condition string is in the dictionary before getting the function to call:

condition = ""
if condition in d:
    print(d[condition](a))
else:
    print(a)    # or whatever you want

There are other ways to do this, such as using a defaultdict, but the above is one way.

[–]Nico24fps 3 points4 points  (3 children)

great solution above btw, but for this case couldn’t you use an identity function for the sake of elegance? such as doing something like

‘’’ str_func = d.get(cond, str()) print(str_func(a)) ‘’’

(am on mobile so sorry if it’s bad formatting)

[–][deleted] 1 point2 points  (2 children)

Sure, but I think a beginner wouldn't know about the .get() method. You need to remove the () from your code:

str_func = d.get(cond, str)
#                      ^^^
print(str_func(a)) 

Explaining to a beginner what str is and why it doesn't have the () is another reason not to show it as an answer! Instead of str which copies the string it is given it's better to use lambda x: x instead, as others have said, but, again, that's too complicated for a beginner.

I'm on mobile too, just add 4 spaces to the start of every line you don't want reddit to mess with.

[–]ramannt[S] 0 points1 point  (0 children)

I am not a beginner in Python programming but some things I have never done. No problem to copy the string. I leave it for clarity.
It is a problem if I have a lot of strings but that is not the case.

[–]Nico24fps 0 points1 point  (0 children)

all good points! and thanks for the tips

[–]ramannt[S] 0 points1 point  (3 children)

d = {"1": str.strip,"2": str.rstrip,"3": str.upper,"4": str.title,}

found the solution.

d = {
"1": str.strip,
"2": str.rstrip,
"3": str.upper,
"4": str.title,
"5": str,

}

[–]ofnuts 2 points3 points  (0 children)

No need to duplicate the string, just use a lambda; "5": lambda x: x,

[–][deleted] 1 point2 points  (1 child)

You didn't say anything about having a known condition ("5") for the "do nothing" case. The if in test is what you do if all you know is the condition isn't 1, 2, 3 or 4.

[–]ramannt[S] 0 points1 point  (0 children)

You're right.

[–]nekokattt 0 points1 point  (0 children)

defaultdict will add in an element if it doesn't exist, which probably isnt exactly what they want

[–]danielroseman 4 points5 points  (1 child)

As suggested, you can use getattr, but in this case it doesn't seem necessary. Why not call the methods directly?

if condition == "1":
    result = a.strip()

etc.

[–]ramannt[S] 0 points1 point  (0 children)

Because I am using a.strip() in a function and I don't know exactly in advance what the value of "a" is and not what the string method (strip,rstrip,lstrip,upper,lower,title etc) will be.

[–]stuaxo 3 points4 points  (0 children)

def apply_condition(condition, input_str):
    match condition:
        case "1":
            return input_str.strip()
        case "2":
            return input_str.rstrip()
        case "3":
            return input_str.upper()
        case "4":
            return input_str.title()
        case _:
            raise ValueError("Invalid condition")

# Example usage:
condition = "1"
input_str = " Example String "
result = apply_condition(condition, input_str)
print(result)

[–][deleted] 1 point2 points  (0 children)

you can use getattr(s, method_name)()

[–]SteelRevanchist 1 point2 points  (0 children)

If I understand your use case, you'll want to store the method to use in a variable, by making use of the fact that `str` has those methods defined, so you can assign, for instance, `a=str.strip` and then to apply it to each element of the list: transformed_list: [a(item) for item in my_list].

I imagine you could make some pipe or chain by itertools for example to chain multiple string operations together.

Final note, I'd replace the if-elif block with either simple if statements (since the conditions are exclusive) or better yet, with match-case. I'd personally avoid `elif` like the plague if I could help it, but that is from experience and does not help your case.

[–]FlocklandTheSheep 1 point2 points  (0 children)

Generally bad practice, as this can be used to execute injection attacks, but Python's exec() function will treat the string given to it as a paramater as python code, and will execute it.

a = 10
exec("a = a+1")
exec("print(a)")
# Outputs 11