#1
  1. Reinvent the Circle
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2004
    Location
    Jonesville, MI
    Posts
    218
    Rep Power
    16

    Arrow New to Python from Perl: Is there an equivalent to perl's CODEREF reference types?


    I need to find out if there is an equivalent to perl's reference data type. Specifically, I want to know if python can do something like this simple perl code:
    Code:
    $coderef = sub {...};
    Thanks!
    -Yanno

    "If it will have to be done more than once, don't do it. Make something that does it for you."

    "If you want to get out of the box, you must not think outside the box, you must think about the box. In fact, think about destroying the box."
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Posts
    624
    Rep Power
    35
    "You can create a reference to an anonymous subroutine by using sub without a subroutine name:

    $coderef = sub { print "Boink!\n" }; # Now &$coderef prints "Boink!"
    "

    Python uses reference to data structures by default, but the closest thing it has to anonymous subroutines is using lambda:

    Code:
    >>> f = lambda x: x+1
    >>> f(1)
    2
    These are limited to single lines of code though, and can't contain certain things. It's probably easier to just make a function, because functions are first class and can be treated as objects anyway...:

    Code:
    >>> def f(x):
    >>>     print x+1
    >>>
    >>> f
    <function f at 0x012C69B0>
    >>> f(1)
    2
  4. #3
  5. Reinvent the Circle
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2004
    Location
    Jonesville, MI
    Posts
    218
    Rep Power
    16
    Thanks for starters.

    I assume I can have a dictionary structure with values being functions? Also, can you nest dictionaries like you can nest hashes in perl?

    One of the ways I use perl referencing is that I might declare an anonymous subroutine as private, but pass a reference to it to some other place in the code. In that way the subroutine isn't lost when it goes out of scope, but I can redefine the variable that holds the reference so that it references a different subroutine, and I could even remove all references and let it be picked up by the garbage collector.
    One way I use this is so that I can dynamically create a list of subroutines to run (by reference).
    So, is there a way that a function can be held in similar fashion so as to hold a list or dictionary of functions?
    -Yanno

    "If it will have to be done more than once, don't do it. Make something that does it for you."

    "If you want to get out of the box, you must not think outside the box, you must think about the box. In fact, think about destroying the box."
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Posts
    624
    Rep Power
    35
    I don't really know much Perl, so I'm quite happy for anyone else who does to correct me, but I think I can answer these so I will try:

    Originally Posted by yanno
    I assume I can have a dictionary structure with values being functions?
    Yes, just by putting the functions (or anonymous functions) in the dictionary:
    Code:
    >>> def increment(x):
    ... 	return x+1
    ... 
    >>> d = {'add':increment, 'minus':lambda x: x-1}
    >>>
    >>> d['add']
    <function increment at 0x012C69B0>
    >>> d['add'](3)
    4
    >>> d['minus'](5)
    4
    >>> test = d['add']
    >>> test
    <function increment at 0x012C69B0>
    >>> test(1)
    2
    Also, can you nest dictionaries like you can nest hashes in perl?
    I don't know if it works like it does in Perl, but you can nest dictionaries:

    Code:
    >>> left = {'a': 1}
    >>> both = {'L':left, 'R':{'b':2}}
    >>> 
    >>> both['L']
    {'a': 1}
    >>> both['L']['a']
    1
    >>> both['L']['b']
    Traceback (most recent call last):
      File "<interactive input>", line 1, in ?
    KeyError: 'b'
    >>> both['R']['b']
    2
    >>>
    One of the ways I use perl referencing is that I might declare an anonymous subroutine as private, but pass a reference to it to some other place in the code. In that way the subroutine isn't lost when it goes out of scope, but I can redefine the variable that holds the reference so that it references a different subroutine, and I could even remove all references and let it be picked up by the garbage collector.
    One way I use this is so that I can dynamically create a list of subroutines to run (by reference).
    So, is there a way that a function can be held in similar fashion so as to hold a list or dictionary of functions?
    I'm not sure on the details. You can't declare a function as private in Python, but you can easily pass a reference to it to some other code:

    Code:
    >>> def runfunction(f, x):
    ... 	return f(x)
    ... 
    >>> def inc(n):
    ... 	return n+1
    ... 
    >>> runfunction(inc, 3)
    4
    I don't know my way around Python scoping and garbage collection enough to answer the next part - I think that if you have a reference to an object it will not be collected, but that's all I can really say.

    The last bit - you can dynamically add functions to a list or dictionary, and rebind variables to reference other functions in much the same way they are used above.

    Code:
    >>> test = lambda s: s+" adding to the end of a string"
    >>> test("-")
    '- adding to the end of a string'
    >>> test = lambda s: s.replace(" ", "")
    >>> test("removing spaces from a string")
    'removingspacesfromastring'
    >>>

IMN logo majestic logo threadwatch logo seochat tools logo