Re: [Tutor] functions first?

2015-01-27 Thread Alex Kleider

On 2015-01-27 16:10, Steven D'Aprano wrote:

On Tue, Jan 27, 2015 at 08:39:17AM -0800, Alex Kleider wrote:


I use the docopt module to collect command line options and then
configparser to read a file.
Some of the values (such as a port number, for example) must then be
adjusted.  An example is
a port number which I want to convert from "5022" to ":5022" if it's a
non standard port or
to "" if it is the standard "22" so it can then be used as a string
format parameter.
Perhaps I should be doing this in the same place as I set up the 
string

rather than where
I populate the 'config' and 'PARAMS' dictionaries?



I see the basic problem as this:

- you have config settings (command line options, config files)
  which by their nature are always strings
- furthermore they are strings in a format designed for human use
  rather than machine use
- by the time your function uses them, they need to be converted
  from human-format to machine-format.

That last step might involve a type conversion like int(s), trimming
whitespace, or more complex operations.

The most obvious way to do them is to apply the operation after reading
the config value but before storing it in the params dict. If that
works, I wouldn't add complexity where it isn't needed.

If it doesn't work for you, I think you need to explain what the 
problem

is before we can suggest a better design.


Again, thank you very much.
I'll do as you suggest above and see if I can make it work.
Alex
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-27 Thread Steven D'Aprano
On Tue, Jan 27, 2015 at 08:39:17AM -0800, Alex Kleider wrote:

> I use the docopt module to collect command line options and then 
> configparser to read a file.
> Some of the values (such as a port number, for example) must then be 
> adjusted.  An example is
> a port number which I want to convert from "5022" to ":5022" if it's a 
> non standard port or
> to "" if it is the standard "22" so it can then be used as a string 
> format parameter.
> Perhaps I should be doing this in the same place as I set up the string 
> rather than where
> I populate the 'config' and 'PARAMS' dictionaries?


I see the basic problem as this:

- you have config settings (command line options, config files) 
  which by their nature are always strings
- furthermore they are strings in a format designed for human use
  rather than machine use
- by the time your function uses them, they need to be converted
  from human-format to machine-format.

That last step might involve a type conversion like int(s), trimming 
whitespace, or more complex operations.

The most obvious way to do them is to apply the operation after reading 
the config value but before storing it in the params dict. If that 
works, I wouldn't add complexity where it isn't needed.

If it doesn't work for you, I think you need to explain what the problem 
is before we can suggest a better design.


-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-27 Thread Alex Kleider

On 2015-01-27 00:15, Alan Gauld wrote:

On 27/01/15 02:04, Alex Kleider wrote:

Please correct me if I am wrong, but I've assumed that it is proper to
define all functions before embarking on the main body of a program.


No, you can do it either way round. Top-Down or Bottom-Up as they are 
known.


Usually its a muxture of both.

But most folks like to have a running program at all times. So you
might write the function headers with dummy bodies then write the main
code that calls the functions. Then go back and fill in the functions


I've just realized where the confusion arises.
As Steve guessed, I was talking about the order in which they appear in 
the file,
not the order in which they were written.  Only when this light went on 
did I
realize why I had inadvertently precipitated a discussion of top down vs 
bottom up

design.
Sorry about the confusion.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-27 Thread Alex Kleider

On 2015-01-26 22:30, Ben Finney wrote:

Alex Kleider  writes:


Please correct me if I am wrong, but I've assumed that it is proper to
define all functions before embarking on the main body of a program.


I would say rather that as much code as possible should be in small
well-defined functions, with the “main body” a tiny and trivial call to
a function.

That way, all the code is easily tested by unit testing tools.


I find myself breaking this rule because I want to set the default
values of some named function parameters based on a configuration file
which I have to first read, hence the need to break the rule.


Module-level constants are fine, and they obviously need to be bound
before the definition of the function which uses them for parameter
defaults.

But if they're not constants – as implied by your statement you read
them from a configuration file – then they should not be in the 
function

definition, because reading the configuration file should itself be
encapsulated in a well-tested function.


Thanks for your well reasoned advice.
You are of course correct in that if they are read from a configuration
file then they are not constants but in a sense they are, at least for
the life of the current program run.  I'm probably going to go with the
way Steve recommended which is to use global dictionaries to contain
the command line arguments (which docopt already does) and configuration
values (which are also placed into a dictionary by configparser) and 
then

use those dictionaries within functions that need them
rather than setting default named parameters for the functions.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-27 Thread Alex Kleider

On 2015-01-27 03:18, Steven D'Aprano wrote:

On Mon, Jan 26, 2015 at 06:04:10PM -0800, Alex Kleider wrote:

Please correct me if I am wrong, but I've assumed that it is proper to
define all functions before embarking on the main body of a program.
I find myself breaking this rule because I want to set the default
values of some named function parameters based on a configuration file
which I have to first read, hence the need to break the rule.
..so my question is "is this acceptable" or "is there a better way?"


I'm not really sure I understand the question correctly.

As far as *design* go, there are two competing paradigms, "top-down"
versus "bottom-up". Perhaps you are thinking about that?

In top-down, you start with the part of the application closest to the
user, say, a web browser:

def run_browser():
win = make_window()
page = get_url(whatever)
show_page(page, win)

Then you write the next level down:

   def make_window()
   ...

   def get_url(address):
   ...

   def show_page(page, win):
   ...

and so on, all the way down to the most primitive and simple parts of
the application:

   def add_one(n):
   return n+1


In bottom-up programming, you do the same, only in reverse. You build
the most primitive functions first, then add them together like Lego
blocks, getting more and more complicated and powerful until you end up
with a fully-functioning web browser.

Personally, I think that in any real application, you need a 
combination

of both top-down and bottom-up, but mostly top-down. (How do you know
what primitive operations you will need right at the start of the 
design

process?) Also, many of the primitive "Lego blocks" already exist for
you, in the Python standard library.

If you are talking about the order in which functions appear in the
source file, I tend to write them like this:

=== start of file ===
hash-bang line
encoding cookie
licence
doc string explaining what the module does
from __future__ imports
import standard library modules
import custom modules
metadata such as version number
other constants
global variables
custom exception types
private functions and classes
public functions and classes
main function
if __name__ == '__main__' code block to run the application
=== end of file ===


All of those are optional (especially global variables, which I try 
hard

to avoid). Sometimes I swap the order of private and public sections,
but the main function (if any) is always at the end just before the "if
__name__" section.


As far as the default values go, I *think* what you are doing is
something like this:

f = open("config")
value = int(f.readline())
f.close()

def function(x, y=value):
return x + y



Am I right?

Yes, this is indeed what I was doing (but then on reflection,
became uncertain about the wisdom of doing it this way- hence
the question.)



If so, that's not too bad, especially for small scripts, but I think a
better approach (especially for long-lasting applications like a 
server)

might be something like this:

def read_config(fname, config):
f = open(fname)
config['value'] = int(f.readline())
f.close()

PARAMS = {
# set some default-defaults that apply if the config file
# isn't available
value: 0,
}

read_config('config', PARAMS)


def func(x, y=None):
if y is None:
y = PARAMS['value']
return x + y



This gives lots of flexibility:

- you can easily save and restore the PARAMS global variable with
  just a dict copy operation;

- you can apply multiple config files;

- you can keep multiple PARAMS dicts (although as written, func only
  uses the one named specifically PARAMS);

- read_config can be isolated for testing;

- you can re-read the config file without exiting the application;

etc.


Does this help?



Yes, very much so.
Thank you again!

I use the docopt module to collect command line options and then 
configparser to read a file.
Some of the values (such as a port number, for example) must then be 
adjusted.  An example is
a port number which I want to convert from "5022" to ":5022" if it's a 
non standard port or
to "" if it is the standard "22" so it can then be used as a string 
format parameter.
Perhaps I should be doing this in the same place as I set up the string 
rather than where

I populate the 'config' and 'PARAMS' dictionaries?
Sincerely,
Alex

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-27 Thread Steven D'Aprano
On Mon, Jan 26, 2015 at 06:04:10PM -0800, Alex Kleider wrote:
> Please correct me if I am wrong, but I've assumed that it is proper to 
> define all functions before embarking on the main body of a program.
> I find myself breaking this rule because I want to set the default 
> values of some named function parameters based on a configuration file 
> which I have to first read, hence the need to break the rule.
> ..so my question is "is this acceptable" or "is there a better way?"

I'm not really sure I understand the question correctly.

As far as *design* go, there are two competing paradigms, "top-down" 
versus "bottom-up". Perhaps you are thinking about that?

In top-down, you start with the part of the application closest to the 
user, say, a web browser:

def run_browser():
win = make_window()
page = get_url(whatever)
show_page(page, win)

Then you write the next level down:

   def make_window()
   ...

   def get_url(address):
   ...

   def show_page(page, win):
   ...

and so on, all the way down to the most primitive and simple parts of 
the application:

   def add_one(n):
   return n+1


In bottom-up programming, you do the same, only in reverse. You build 
the most primitive functions first, then add them together like Lego 
blocks, getting more and more complicated and powerful until you end up 
with a fully-functioning web browser.

Personally, I think that in any real application, you need a combination 
of both top-down and bottom-up, but mostly top-down. (How do you know 
what primitive operations you will need right at the start of the design 
process?) Also, many of the primitive "Lego blocks" already exist for 
you, in the Python standard library.
   
If you are talking about the order in which functions appear in the 
source file, I tend to write them like this:

=== start of file ===
hash-bang line
encoding cookie
licence
doc string explaining what the module does
from __future__ imports
import standard library modules
import custom modules
metadata such as version number
other constants
global variables
custom exception types
private functions and classes
public functions and classes
main function
if __name__ == '__main__' code block to run the application
=== end of file ===


All of those are optional (especially global variables, which I try hard 
to avoid). Sometimes I swap the order of private and public sections, 
but the main function (if any) is always at the end just before the "if 
__name__" section.


As far as the default values go, I *think* what you are doing is 
something like this:

f = open("config")
value = int(f.readline())
f.close()

def function(x, y=value):
return x + y



Am I right?

If so, that's not too bad, especially for small scripts, but I think a 
better approach (especially for long-lasting applications like a server) 
might be something like this:

def read_config(fname, config):
f = open(fname)
config['value'] = int(f.readline())
f.close()

PARAMS = {  
# set some default-defaults that apply if the config file
# isn't available
value: 0,
}

read_config('config', PARAMS)


def func(x, y=None):
if y is None:
y = PARAMS['value']
return x + y



This gives lots of flexibility:

- you can easily save and restore the PARAMS global variable with 
  just a dict copy operation;

- you can apply multiple config files;

- you can keep multiple PARAMS dicts (although as written, func only 
  uses the one named specifically PARAMS);

- read_config can be isolated for testing;

- you can re-read the config file without exiting the application;

etc.


Does this help?


-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-27 Thread Alan Gauld

On 27/01/15 02:04, Alex Kleider wrote:

Please correct me if I am wrong, but I've assumed that it is proper to
define all functions before embarking on the main body of a program.


No, you can do it either way round. Top-Down or Bottom-Up as they are known.

Usually its a muxture of both.

But most folks like to have a running program at all times. So you might 
write the function headers with dummy bodies then write the main code 
that calls the functions. Then go back and fill in the functions one at 
a time, for example.


eg. A trivial example:

### pass 1 

def sayHello(msg):
   pass

def getGreeting(prompt):
return "hello world"

def main():
   greeting = getGreeting("What to say: ")
   sayHello(greeting)

if __name__ == "__main__": main()

### pass 2 ##

def sayHello(msg):
   print(msg)

def getGreeting(prompt):
return "hello world"

def main():
   greeting = getGreeting("What to say: ")
   sayHello(greeting)

if __name__ == "__main__": main()

### pass 3  ##

def sayHello(msg):
   print(msg)

def getGreeting(prompt):
return input(prompt)

def main():
   greeting = getGreeting("What to say: ")
   sayHello(greeting)

if __name__ == "__main__": main()

HTH
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] functions first?

2015-01-26 Thread Ben Finney
Alex Kleider  writes:

> Please correct me if I am wrong, but I've assumed that it is proper to
> define all functions before embarking on the main body of a program.

I would say rather that as much code as possible should be in small
well-defined functions, with the “main body” a tiny and trivial call to
a function.

That way, all the code is easily tested by unit testing tools.

> I find myself breaking this rule because I want to set the default
> values of some named function parameters based on a configuration file
> which I have to first read, hence the need to break the rule.

Module-level constants are fine, and they obviously need to be bound
before the definition of the function which uses them for parameter
defaults.

But if they're not constants – as implied by your statement you read
them from a configuration file – then they should not be in the function
definition, because reading the configuration file should itself be
encapsulated in a well-tested function.

-- 
 \  “It is the integrity of each individual human that is in final |
  `\examination. On personal integrity hangs humanity's fate.” |
_o__)   —Richard Buckminster Fuller, _Critical Path_, 1981 |
Ben Finney

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] functions first?

2015-01-26 Thread Alex Kleider
Please correct me if I am wrong, but I've assumed that it is proper to 
define all functions before embarking on the main body of a program.
I find myself breaking this rule because I want to set the default 
values of some named function parameters based on a configuration file 
which I have to first read, hence the need to break the rule.

..so my question is "is this acceptable" or "is there a better way?"
thks
Alex
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor