Closures in python

Discussion in 'Python' started by Kasper B. Graversen, Sep 18, 2003.

  1. Having played with Smalltalk for the past month, I'm getting used to
    passing code as arguments to methods... how easy is it to do this in
    python? I haven't seen any recent postings on this subject here...

    \kasper
     
    Kasper B. Graversen, Sep 18, 2003
    #1
    1. Advertising

  2. Try this.

    def f(n):
    return n*2

    def t(fnc_prm, n):
    return fnc_prm(n)

    t(f, 2)

    I hope it helps.

    Károly

    "Kasper B. Graversen" <> az alábbiakat írta a következo
    hírüzenetben: ...
    > Having played with Smalltalk for the past month, I'm getting used to
    > passing code as arguments to methods... how easy is it to do this in
    > python? I haven't seen any recent postings on this subject here...
    >
    > \kasper
     
    Ladvánszky Károly, Sep 18, 2003
    #2
    1. Advertising

  3. Kasper B. Graversen

    Syver Enstad Guest

    (Kasper B. Graversen) writes:

    > Having played with Smalltalk for the past month, I'm getting used to
    > passing code as arguments to methods... how easy is it to do this in
    > python? I haven't seen any recent postings on this subject here...


    It is fairly straightforward:

    import sys

    def funcThatTakesCallable(aCallable):
    aCallable('SomeString')

    class MyClass:
    def myFunc():
    def myCallable(arg):
    print arg
    funcThatTakesCallable(myCallable)
    funcThatTakesCallable(self.anotherCallable)
    funcThatTakesCallable(lambda arg: sys.stdout.write('%s\n' % arg))

    def anotherCallable(self, arg):
    print 'another', arg


    The major difference is that the anonymous form of a function (lambda)
    isn't allowed to contain statements, only an expression. This is
    rather crippling for Smalltalk/Ruby style coding and seems to lead to
    warts like list comprehensions instead of having simple methods in the
    collection interface that takes a block/lambda and calls this for each
    element of the collection.

    Example:

    newCollection = [each for each in collection if each != 'Sausage']

    newCollection = collection.select(lambda each: each != 'Sausage')
     
    Syver Enstad, Sep 18, 2003
    #3
  4. Kasper B. Graversen wrote:
    > Having played with Smalltalk for the past month, I'm getting used to
    > passing code as arguments to methods... how easy is it to do this in
    > python? I haven't seen any recent postings on this subject here...


    There is no direct equivalent of code blocks in Python. Use Callables
    instead. Callables are

    - functions
    def mywrite (text):
    sys.stdout.write (text)
    variable = mywrite
    variable ('printed text')

    - bound methods, a method bound to a specific object
    variable = sys.stdout.write
    variable ('printed text')

    - lambda, unnamed functions, which can contain only one expression
    variable = lambda text: sys.stdout.write (text)
    variable ('printed text')

    - classes implementing the __call__ method
    class Writer:
    def __call__ (self, text):
    sys.stdout.write (text)
    variable = Writer ()
    variable ('printed text')

    Daniel
     
    Daniel Dittmar, Sep 18, 2003
    #4
  5. 'closure' is a much-abused word.
    This is a closure over foo's x variable:

    def foo():
    x = 3
    def bar():
    x += 1
    return x
    return bar

    f = foo()
    print f() # print 4
    g = foo()
    print f() # print 5
    print g() # print 4

    ....or it would be, if it worked.

    --
    Hallvard
     
    Hallvard B Furuseth, Sep 18, 2003
    #5
  6. Try this.

    def f(n):
    return n*2

    def t(fnc_prm, n):
    return fnc_prm(n)

    t(f, 2)

    I hope it helps.

    Károly


    "Kasper B. Graversen" <> az alábbiakat írta a következo
    hírüzenetben: ...
    > Having played with Smalltalk for the past month, I'm getting used to
    > passing code as arguments to methods... how easy is it to do this in
    > python? I haven't seen any recent postings on this subject here...
    >
    > \kasper
     
    Ladvánszky Károly, Sep 18, 2003
    #6
  7. Hallvard B Furuseth <h.b.furuseth(nospam)@usit.uio(nospam).no> wrote:

    >'closure' is a much-abused word.
    >This is a closure over foo's x variable:


    How about namespaces?

    >def foo():
    > x = 3
    > def bar():
    > x += 1
    > return x
    > return bar
    >
    >f = foo()
    >print f() # print 4
    >g = foo()
    >print f() # print 5
    >print g() # print 4
    >
    >...or it would be, if it worked.


    This works:

    def foo():
    class ns:pass
    ns.x = 3
    def bar():
    ns.x += 1
    return ns.x
    return bar

    Anton
     
    Anton Vredegoor, Sep 18, 2003
    #7
  8. Kasper B. Graversen

    JCM Guest

    Hallvard B Furuseth <h.b.furuseth(nospam)@usit.uio(nospam).no> wrote:
    > 'closure' is a much-abused word.
    > This is a closure over foo's x variable:


    > def foo():
    > x = 3
    > def bar():
    > x += 1
    > return x
    > return bar


    > f = foo()
    > print f() # print 4
    > g = foo()
    > print f() # print 5
    > print g() # print 4


    > ...or it would be, if it worked.


    Python does have closures; the trouble is you can't rebind variables
    defined in arbitrary scopes--you can only rebind locals and globals.
    So you need some indirection for it to work:

    >>> def foo():

    ... x = [3]
    ... def bar():
    ... x[0] += 1
    ... return x[0]
    ... return bar
    ...
    >>> f = foo()
    >>> f()

    4
    >>> g = foo()
    >>> f()

    5
    >>> g()

    4

    This is actually one of my biggest complaints about Python. I'd like
    syntactic disambiguation between definition and assignment in order to
    have control over which scope you're assigning into.
     
    JCM, Sep 18, 2003
    #8
  9. Anton Vredegoor wrote:
    > Hallvard B Furuseth <h.b.furuseth(nospam)@usit.uio(nospam).no> wrote:
    >
    >> 'closure' is a much-abused word.
    >> This is a closure over foo's x variable:

    >
    > How about namespaces?
    > (...)


    Nice! Being a Python newbie I needed JCM's explanation to figure out
    how it worked, though. Nothing magic about classes at all...

    --
    Hallvard
     
    Hallvard B Furuseth, Sep 19, 2003
    #9
  10. JCM wrote:
    > >>> def foo():

    > ... x = [3]
    > ... def bar():
    > ... x[0] += 1
    > (...)
    >
    > This is actually one of my biggest complaints about Python. I'd like
    > syntactic disambiguation between definition and assignment in order to
    > have control over which scope you're assigning into.


    Maybe Python could be changed to let 'foo.x' inside function foo mean
    the x variable in foo?

    --
    Hallvard
     
    Hallvard B Furuseth, Sep 21, 2003
    #10
  11. nospam wrote:

    > JCM wrote:
    >> >>> def foo():

    >> ... x = [3]
    >> ... def bar():
    >> ... x[0] += 1
    >> (...)
    >>
    >> This is actually one of my biggest complaints about Python. I'd like
    >> syntactic disambiguation between definition and assignment in order to
    >> have control over which scope you're assigning into.

    >
    > Maybe Python could be changed to let 'foo.x' inside function foo mean
    > the x variable in foo?


    That would be backwards-incompatible, since foo.x already means
    something -- the attribute x of object foo (yep, functions are objects
    and can have attributes), which has no connection whatsoever with
    the local variable x inside (some of the potentially many currently
    active instances of) functions named foo.


    Alex
     
    Alex Martelli, Sep 21, 2003
    #11
  12. In article <>,
    Hallvard B Furuseth <h.b.furuseth(nospam)@usit.uio(nospam).no> wrote:

    > JCM wrote:
    > > >>> def foo():

    > > ... x = [3]
    > > ... def bar():
    > > ... x[0] += 1
    > > (...)
    > >
    > > This is actually one of my biggest complaints about Python. I'd like
    > > syntactic disambiguation between definition and assignment in order to
    > > have control over which scope you're assigning into.

    >
    > Maybe Python could be changed to let 'foo.x' inside function foo mean
    > the x variable in foo?


    But the x variable does not live on the foo function object, it lives on
    the stack frame created by the current call to foo.

    So something more indirect, like scope(foo).x, would make more sense,
    where scope() inspects the call stack looking for calls to foo and
    returns an object with appropriate __getattr__ and __setattr__ methods.
    This may be implementable now, by someone who knows more about python
    introspection than I do. I tried doing it with inspect.stack, but it
    doesn't work -- I can find the right frame and get it's f_locals
    dictionary, but this gives read-only access to the true frame's locals.

    --
    David Eppstein http://www.ics.uci.edu/~eppstein/
    Univ. of California, Irvine, School of Information & Computer Science
     
    David Eppstein, Sep 21, 2003
    #12
    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. paolo veronelli

    Closures python,scheme,ruby

    paolo veronelli, Jul 12, 2004, in forum: Python
    Replies:
    5
    Views:
    1,031
    Jacek Generowicz
    Jul 16, 2004
  2. Robert Brewer

    RE: Closures python,scheme,ruby

    Robert Brewer, Jul 16, 2004, in forum: Python
    Replies:
    2
    Views:
    293
    Sean Ross
    Jul 16, 2004
  3. Karl Kofnarson

    What are python closures realy like?

    Karl Kofnarson, Dec 1, 2006, in forum: Python
    Replies:
    16
    Views:
    480
    Roy Smith
    Dec 12, 2006
  4. treble54

    Closures / Blocks in Python

    treble54, Jul 24, 2007, in forum: Python
    Replies:
    10
    Views:
    815
    Gabriel Genellina
    Jul 26, 2007
  5. Replies:
    3
    Views:
    310
    James Stroud
    Dec 4, 2008
Loading...

Share This Page