-5

Problem statement:

I am trying to read lines from my data and and output both the forward and reverse orientation by passing my list to a function. To solve what I am trying to do, I have to pipe the function-name as string. I am making a mock test below that replicates my original problem in a simple way.

my_str = 'abcdef\nijklmn\nstuv\n'
my_str = my_str.rstrip('\n').split('\n')

for lines in my_str:
    print(lines)
    line_list = list(lines)

    # I want to read both forward and reverse orientation using a function "(def orient_my_str():"
    # the reason to pass this into another function is because I have lots of data crunching to do in each orientation (not shown here).
    # but, below process typically resolves what I am trying to achieve

    line_rev = orient_my_str(line_list, orientation='reversed')
    line_fwd = orient_my_str(line_list, orientation='')

    print('list in reverse orientation :', line_rev)
    print('list in forward orientation :', line_fwd)
    print()


# I am only want to make one function not two, because if I make two functions ..
# .. I will have to copy a large amount of code below the for-loop.
# there should be a way to fix this problem (calling function using string name when required and not).
def orient_my_str(line, orientation):
    my_output = ''
    for item in eval(orientation)(line):
        my_output += item

    print(my_output)
    return my_output

# But, this only works for reverse orientation. I know the issue is with passing "eval('')(line)" but was hoping it would work.

I tried to fix my code using ideas from these links,

Use a string to call function in Python

Calling a function of a module by using its name (a string)

python function call with variable

but I cannot seem to work it out.

13
  • I think you didn't read my question carefully. To do what you are imply, I will either have to make two functions; which is not what I want - because I will have to copy a big chunk of code in my original program. I am sure sure there is way to fix this. Commented Mar 13, 2018 at 19:04
  • 1
    @everestial007 @PatrickArtner Yeah, it's a little bit hacky that's why I wrote it as comment. The thing you should understand is eval evaluates passed string. Since what you need is either reversed(line) or just line, I wrap line with parantheses hence the code. Commented Mar 13, 2018 at 19:18
  • 1
    @everestial007 Regardless of how you feel your question is being received. It is not helpful to clutter said question with complaints about downvotes, etc. If you have issue with how people are reacting to your questions, look into posting on meta. Commented Mar 13, 2018 at 19:22
  • 1
    I didn't downvote your question, but there's two things that are bad about it. First thing is that it is a so-called "XY question", instead of describing the goal, you ask how to achieve a certain (flawed!) solution. The other thing is that it violates the MCVE spirit in that the first two lines and the loop that follow could be replaced with just the loop's body. Commented Mar 13, 2018 at 20:03
  • 1
    BTW: It's also unclear why you can not pass the reversed sequence to the function like rev = orient_my_str(reversed(line_list)). Further, naming isn't your strong side either, because line_list is not a list of lines and my_str is not a string. These things matter! Commented Mar 13, 2018 at 20:11

2 Answers 2

2

Here's the approach as already suggested in the comment:

def orient_my_str(line, preprocessor):
    my_output = ''
    for item in preprocessor(line):
        my_output += item

    print(my_output)
    return my_output

As I mentioned, you can pass a function as parameter. In order to call it, you do this:

line_rev = orient_my_str(line_list, preprocessor=reversed)
line_fwd = orient_my_str(line_list, preprocessor=lambda x: x)

You could also use a default parameter for preprocessor, if you don't like passing the lambda function explicitly.

In summary, the important point is that there's no need to pass the name of a function around in order to then look up that function and call it. Just pass the function itself as parameter.

Sign up to request clarification or add additional context in comments.

2 Comments

This seems to work pretty neat. It's nice to know that we can do preprocessor=reversed on a function directly rather than string typing them. It's astonishing how lambda x: x fit in there; and how would you default it ?
preprocessor=iter would also work nicely for the forward case
2

Dont use eval, keep your methods simple. You do not need to copy anything below the for:

def orient_my_str(line, reverse = False): 
    # add any needed preprocessing here, store result as new list
    # and use it in the following line instead of the variable line
    data = reversed(line) if reverse else line 

    my_output = ''
    for item in data: # operate on line or reversed line as needed
        my_output += item

    print(my_output)
    return my_output

line_list= ["1","2","3","4"]
line_rev = orient_my_str(line_list, reverse = True)
line_fwd = orient_my_str(line_list)

print(line_rev)
print(line_fwd)

Output:

4321
1234
4321
1234

5 Comments

Thanks Patrick. Let me ask you. Did you had problem reading my question and problem? Why are people so whimsical about downvoting a simple, comprehensive question like this?
data = reversed(line) if reverse else line seems to be the problem because in my original program I have the break the line first to do my data computation. I am not just writing the line back but the manipulated line. This was just a mock test file.
@everestial007 I havent had any problems reading your questions and did not downvote until you put this big black text on top of it. This method does the same as yours without use of eval which can be considered unsafe and passing strings that then work as functionname for something that can easily be solved otherwise.If you need to preprocess your list - do so, then reverse it when ever you are finished preprocessing it and do your big for-loop over the reversed partof it.
data = reversed(line) if reverse else line just escapes the for loop. So, it's not applicable.
@everestial007 I am not sure I get your last comment. It is a ternary operator that provides line either as is or reversed by the name data to your for loop. If you need further preprocessing on line, you can do that before it - I marked it as comment in the code. Your loop operates on data which is either reversed or not - wich is exactly the same as your "eval" solution would do. I can see you are not pleased with my solution, downvote it if you really think it does not solve your problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.