How to "generalize" a function?

Discussion in 'Python' started by =?iso-8859-1?q?Thomas_K=F6llmann?=, Apr 24, 2005.

  1. Hi, everybody!

    I'm teaching myself Python, and I have no experience in programming
    apart from some years of shell scripting. So, please bear with me.

    These two funktions are part of an administrative script I've set
    myself as a first lesson, and, as you will see, they're practically the same,
    except for one variable. So I'd like to weld them together -- but I
    can't find out how to.

    def writeIP(ip):
    """ IP schreiben """
    regex = re.compile('(.*)address(.*)')
    confFile = open(networkConf, 'r')
    conf = confFile.readlines()
    confFile.close
    for line in conf:
    if regex.search(line):
    addressLine = line
    addressLineNum = conf.index(addressLine)
    address = string.split(addressLine, ' ')
    address[1] = ip + "\n"
    conf[addressLineNum] = string.join(address)
    confFile = open(networkConf, 'w')
    confFile.writelines(conf)
    confFile.close

    def writeMask(mask):
    """ netmask schreiben """
    regex = re.compile('(.*)netmask(.*)')
    confFile = open(networkConf, 'r')
    conf = confFile.readlines()
    confFile.close
    for line in conf:
    if regex.search(line):
    netmaskLine = line
    netmaskLineNum = conf.index(netmaskLine)
    netmask = string.split(netmaskLine, ' ')
    netmask[1] = mask + "\n"
    conf[netmaskLineNum] = string.join(netmask)
    confFile = open(networkConf, 'w')
    confFile.writelines(conf)
    confFile.close

    I feel it should be possible to use something like

    def writeFile(ip,keyword):
    ...

    but how would I construct expressions like

    netmaskLineNum = conf.index(netmaskLine)

    in that case (netmask being the keyword here)?


    I fear this is a really silly question and I guess I've missing a very
    basic concept here. But I can't figure it out alone. Any advice much
    appreciated!

    Mit schönem Gruß
    - Thomas


    --
    On the day that she left
    He died but it did not show
    - Neil Young, The Loner
    /* PGP key auf Wunsch per e-mail || PGP key sent on request */
     
    =?iso-8859-1?q?Thomas_K=F6llmann?=, Apr 24, 2005
    #1
    1. Advertising

  2. =?iso-8859-1?q?Thomas_K=F6llmann?=

    Dan Sommers Guest

    On Sun, 24 Apr 2005 23:40:22 +0200,
    Thomas Köllmann <> wrote:

    > Hi, everybody!
    > I'm teaching myself Python, and I have no experience in programming
    > apart from some years of shell scripting. So, please bear with me.


    > These two funktions are part of an administrative script I've set
    > myself as a first lesson, and, as you will see, they're practically
    > the same, except for one variable. So I'd like to weld them together
    > -- but I can't find out how to.


    [ two very similar functions snipped ]


    > I feel it should be possible to use something like


    > def writeFile(ip,keyword):
    > ...


    Absolutely.

    > but how would I construct expressions like


    > netmaskLineNum = conf.index(netmaskLine)


    > in that case (netmask being the keyword here)?


    netmaskLineNum and addressLineNum are just names. They may mean
    something to you and to people who read your program, but they mean
    nothing to Python. So just use generic names:

    for line in conf:
    if regex.search( line )
    theLine = line
    theLineNum = conf.index( theLine )

    etc.

    HTH,
    Dan

    --
    Dan Sommers
    <http://www.tombstonezero.net/dan/>
    μ₀ × ε₀ × c² = 1
     
    Dan Sommers, Apr 25, 2005
    #2
    1. Advertising

  3. Thomas Köllmann <> writes:

    > confFile.close


    You want ``confFile.close()`` -- the above won't do anything [1].

    'as


    Footnotes:
    [1] Best practice would be something like this (don't worry to much about it
    -- it just ensures the file is properly closed, even if something goes
    wrong):

    confFile = None
    try:
    confFile = open(networkConf, 'w')
    confFile.writelines(conf)
    finally:
    if confFile: confFile.close()
     
    Alexander Schmolck, Apr 25, 2005
    #3
  4. Thomas Köllmann wrote:
    > Hi, everybody!
    >
    > I'm teaching myself Python, and I have no experience in programming
    > apart from some years of shell scripting. So, please bear with me.
    >
    > These two funktions are part of an administrative script I've set
    > myself as a first lesson, and, as you will see, they're practically the same,
    > except for one variable. So I'd like to weld them together -- but I
    > can't find out how to.
    >
    > def writeIP(ip):
    > """ IP schreiben """
    > regex = re.compile('(.*)address(.*)')


    This is the only difference between the functions, isn't it?
    So, instead of hardwiring 'address' or 'netmask' into the regexp template, you
    should insert it based on an argument passed to the function. String
    interpolation works well here: e.g.,
    >>> '(.*)%s(.*)' % 'netmask'

    '(.*)netmask(.*)'
    >>>


    > confFile = open(networkConf, 'r')
    > conf = confFile.readlines()
    > confFile.close


    Note, here you presumably mean confFile.close() i.e., you must supply the parens
    to call the function.


    [snip]
    >
    > I feel it should be possible to use something like
    >
    > def writeFile(ip,keyword):
    > ...
    >


    Indeed. Use keyword as the argument to the string interpolation
    >>> regex = re.compile('(.*)%s(.*)' % keyword)


    > but how would I construct expressions like
    >
    > netmaskLineNum = conf.index(netmaskLine)
    >


    I think these should work unchanged. But it would be easier to read if you
    changed these names to be neutral to the application e.g., instead of
    netmaskLine, foundLine

    HTH

    Michael
     
    Michael Spencer, Apr 25, 2005
    #4
  5. Alexander Schmolck wrote:
    > [1] Best practice would be something like this (don't worry to much about it
    > -- it just ensures the file is properly closed, even if something goes
    > wrong):
    >
    > confFile = None
    > try:
    > confFile = open(networkConf, 'w')
    > confFile.writelines(conf)
    > finally:
    > if confFile: confFile.close()
    >


    A clearer equivalent is:
    confFile = open(networkConf, 'w')
    try:
    confFile.writelines(conf)
    finally:
    confFile.close()


    You did not say whether you are looking to replace all, the first,
    or the last occurrence of your search target. Assuming you really
    mean all lines and the first occurrence on those lines:

    def replaces(source, search, replacement):
    '''Replace first of search on lines with replacement'''
    pat = re.compile(search)
    for line in source:
    yield re.sub(pat, replacement, line, 1)

    And your application might go like:

    input = open(networkConf, 'r')
    part1 = replaces(input, 'address', 'ip')
    part2 = replaces(part1, 'netmask', 'mask')
    result = list(part2)
    input.close()
    output = open(networkConf, 'w')
    try:
    output.writelines(result)
    finally:
    output.close()


    --Scott David Daniels
     
    Scott David Daniels, Apr 25, 2005
    #5
  6. =?iso-8859-1?q?Thomas_K=F6llmann?=

    jfj Guest

    Thomas Köllmann wrote:

    > Hi, everybody!
    >
    > I'm teaching myself Python, and I have no experience in programming
    > apart from some years of shell scripting. So, please bear with me.
    >
    > These two funktions are part of an administrative script I've set
    > myself as a first lesson, and, as you will see, they're practically the same,
    > except for one variable. So I'd like to weld them together -- but I
    > can't find out how to.


    Pass the variable as an argument probably.
    But because generally you wouldn't want to recompile the regexp (this
    should be done once), you could say:

    # untested
    def makewriter (regexp_string):
    def writeFunc(ip, regex=re.compile(regexp_string)):
    confFile = open(networkConf, 'r')
    conf = confFile.readlines()
    confFile.close
    for line in conf:
    if regex.search(line):
    addressLine = line
    addressLineNum = conf.index(addressLine)
    address = string.split(addressLine, ' ')
    address[1] = ip + "\n"
    conf[addressLineNum] = string.join(address)
    confFile = open(networkConf, 'w')
    confFile.writelines(conf)
    confFile.close
    return writeFunc

    writeIP=makewriter('(.*)address(.*)')
    writeMask=makewriter('(.*)netmask(.*)')

    This is rather advanced python programming though, but it shows
    cool dynamic function creation features and it's never early to
    get into it;)

    jfj
     
    jfj, Apr 25, 2005
    #6
  7. Michael Spencer <> writes:

    > Thomas Köllmann wrote:
    >> regex = re.compile('(.*)address(.*)')

    >
    > This is the only difference between the functions, isn't it?
    > So, instead of hardwiring 'address' or 'netmask' into the regexp
    > template, you should insert it based on an argument passed to the
    > function. String interpolation works well here: e.g.,
    > >>> '(.*)%s(.*)' % 'netmask'

    > '(.*)netmask(.*)'
    > >>>


    Thanks, I somehow missed this (presumably very basic) feature.

    >>> confFile = open(networkConf, 'r')

    >> conf = confFile.readlines()
    >> confFile.close

    >
    > Note, here you presumably mean confFile.close() i.e., you must supply
    > the parens to call the function.


    Yes, thanks -- to Alexander as well, who also pointed me to that!

    Mit schönem Gruß
    - Thomas


    --
    /* PGP key auf Wunsch per e-mail || PGP key sent on request */
     
    =?iso-8859-1?q?Thomas_K=F6llmann?=, Apr 28, 2005
    #7
  8. Dan Sommers <> writes:

    > On Sun, 24 Apr 2005 23:40:22 +0200,
    > Thomas Köllmann <> wrote:
    >
    > netmaskLineNum and addressLineNum are just names. They may mean
    > something to you and to people who read your program, but they mean
    > nothing to Python. So just use generic names:


    Thanks. I still get easily confused when trying to "abstract" such
    things, but I guess I'll get it some fine day. I appreciate you took
    the time to point that out to me -- you must have found it _extremely_
    obvious. :)

    Mit schönem Gruß
    - Thomas


    --
    I filled and lit my pipe and sat there smoking. Nobody came in, nobody
    called, nothing happened, nobody cared whether I died or went to El Paso.
    - Raymond Chandler, The High Window
    /* PGP key auf Wunsch per e-mail || PGP key sent on request */
     
    =?iso-8859-1?q?Thomas_K=F6llmann?=, Apr 28, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. James Vanns
    Replies:
    7
    Views:
    7,171
    Evan Carew
    Jan 21, 2004
  2. Nash
    Replies:
    7
    Views:
    359
  3. Nash
    Replies:
    6
    Views:
    377
  4. John

    function to generalize

    John, Oct 9, 2003, in forum: Javascript
    Replies:
    1
    Views:
    108
    Richard Cornford
    Oct 9, 2003
  5. rajsena
    Replies:
    3
    Views:
    248
    Arndt Jonasson
    Nov 10, 2004
Loading...

Share This Page