views:

178

answers:

3

I am using Python for automating a complex procedure that has few options. I want to have the following structure in python. - One "flow-class" containing the flow - One helper class that contains a lot of "black boxes" (functions that do not often get changed).

99% of the time, I modify things in the flow-class so I only want code there that is often modified so I do not have to scroll around a lot to find the code I want to modify. This class also contains global variables (configuration settings) that often get changed. The helper class contains global variables that not often get changed.

In the flow-class I have a global variable that I want the user to be forced to input at every run. The line looks like this. print ("Would you like to see debug output (enter = no)? ") debug = getUserInput()

The getUserInput() function should be located in the helper class as it is never modified. The getUserInput needs a global variable from the flow class, which indicates whether the user input should be consistent with Linux command line or Eclipse (running on Windows).

My question is: How can I structure this in the best way? Currently it looks like the following: The flow-class:

import helper_class

isLinux = 1

debug = getUserInput()

The helper-class:

import os, flow_class

def getUserInput():
    userInput = input ()
    if (flow_class.isLinux == 1):
        userInput = userInput[:-1]
    return userInput

This currently gives me the following error due to the cross importing:

Traceback (most recent call last):
  File "flow_class.py", line 1, in <module>
    import helper_class
  File "helper_class.py", line 1, in <module>
    import os, flow_class
  File "flow_class.py", line 5, in <module>
    debug = getUserInput()
NameError: name 'getUserInput' is not defined

I know that I could obviously solve this by always passing isLinux as a parameter to getUserInput, but this complicates the usage of this method and makes it less intuitive.

+1  A: 

I know that I could obviously solve this by always passing isLinux as a parameter to getUserInput, but this complicates the usage of this method and makes it less intuitive.

Actually using global variables complicates the usage of this program waaaay more than a simple parameter.

try something like:

debug = getUserInput(isLinux=True)

Here's some other suggestions

  • You mention there are lots of parameters that you'll change often. Should these be hard coded? Try using a configuration file, or passing a dict() from 'flow' as a parameter. That way you have a central place to change common variables without having to dive in!
  • your 'flow/helper' class sounds like a Controller/Model paradigm. This is good. But your model shouldn't have to import your controller.

These aren't suggestions specific to 'pythonic style' these are general programming practices. If you're concerned about program design try reading The Pragmatic Programmer, they have great tips for workflow and design. There's also Code Complete which Roberto suggested.

Jweede
Parameters are nice as long as there are less than five of them per method, if there are more then something else is needed."parameters are meant to change often, but not to be hard coded. Try using a configuration file." I do not see how using a configuration file changes the general design problem.Thanks a lot for the links to the "Controller/Model" article I will look into it.
David
If you really have lots of parameters, either they are pertinent to one area (thus can be grouped in a messenger object) either you have a function that is doing too much.
Roberto Liffredo
+1  A: 

I would like to question you on your last sentence.

Usually, as also outlined in CC2, usage of global variables helps in writing code, but not in reading it.
And code is read many more times than it is written; in your case, I understand you modify the same script over and over again.

The problem you are facing now is just a consequence of the generic design decision to use global variables.
Explicit parameter passing would make it much clearer, and easier to maintain.

As said in the the Zen of Python, explicit is better than implicit.

Roberto Liffredo
*Random Haiku*Just type `import this`Ah, the Zen of Python. It's concise clarity.
Jweede
+2  A: 

you need to do helper_class.getUserIinput() in your flow_class. It's not about cross-importing. Once it's fixed you'll get AttributeError that is indeed related to cross-importing.

At this stage you'll need to implement logic of getting getUserInput defined before importing flow_class.

And to comment on your last statement: your assumption is not correct. Code would be much clearer if you use explicit local values.

SilentGhost
Thanks. I have updated my code and get the appropriate error message related to cross-importing.Implementing logic to get a function defined at the right place seems like an indication of poor design.
David
it isn't .
SilentGhost
What could such logic look like? Do you mean if statements?
David
if you call `flow_class` from command-line for example you could put an `import` statement within if-statement related to command-line execution. It works.
SilentGhost