Re: Easy questions from a python beginner

Discussion in 'Python' started by wheres pythonmonks, Jul 22, 2010.

  1. Okay -- so I promised that I would try the namespace mangling
    approach, and here's what I have come up with:

    Approach #1: Pass in the variables to be swapped as strings. (boring)

    >>> import sys
    >>> def swap(n1,n2):

    .... try:
    .... raise RuntimeException()
    .... except:
    .... e,b,t = sys.exc_info()
    .... ldict = t.tb_frame.f_back.f_locals
    .... t = ldict[n1];
    .... ldict[n1] = ldict[n2]
    .... ldict[n2] = t
    ....
    >>> x = 'A'
    >>> y = 'B'
    >>> id(x)

    47946650437696
    >>> id(y)

    47946649710192
    >>> swap('x','y')
    >>> print id(x)

    47946649710192
    >>> print id(y)

    47946650437696
    >>> print x,y

    B A

    Approach #2: Allow the user to pass in arbitrary objects, takes the
    id, infer what the variable in by hashing all possible objects, and
    then apply the swap operation above.

    >>> def swap2(o1,o2):

    .... try:
    .... raise RuntimeException()
    .... except:
    .... e,b,t = sys.exc_info()
    .... ldict = t.tb_frame.f_back.f_locals
    .... iddict = dict( (id(v), k ) for k,v in ldict.items() )
    .... # print id(o1), id(o2)
    .... n1 = iddict[id(o1)]
    .... n2 = iddict[id(o2)]
    .... t = ldict[n1];
    .... ldict[n1] = ldict[n2]
    .... ldict[n2] = t
    ....
    >>> print x,y

    B A
    >>> swap2(x,y)
    >>> print x,y

    A B
    >>>


    Now, I want to make the above codes more "Pythonic" -- is there a way to:

    1. Get the function's arguments from the perspective of the caller?

    def f(x):
    print "caller's view of x = %s" % callersview(x)

    Then, f(1+2+3) would yield:
    caller's view of x = 1 + 2 + 3

    2. Is there a better way to loopup by id? I'm not very familiar with
    sys.exc_info, but creating the id->name hash each time seems like
    overkill.

    3. Is there a reference on all the special variables, like __foo__?

    4. Is there any work on deparsing (like Perl's deparse) lambda
    functions to inline algebra and get a performance gain?

    Thanks again for your input,

    W

    ( from Perl-hacker to Python Programmer )

    On Sun, Jul 11, 2010 at 2:37 PM, Stephen Hansen
    <me+list/> wrote:
    > On 7/11/10 10:48 AM, wheres pythonmonks wrote:
    >> I'm an old Perl-hacker, and am trying to Dive in Python.  I have some
    >> easy issues (Python 2.6)
    >> which probably can be answered in two seconds:
    >>
    >> 1.  Why is it that I cannot use print in booleans??  e.g.:
    >>>>> True and print "It is true!"

    >
    > Because print is a statement. Statements have to start lines. If you
    > want to do this, use a function-- in Python 2.6 either via "from
    > __future__ import print_function" or writing your own, even if its just
    > a very thing wrapper around the print statement.
    >
    >> 2.  How can I write a function, "def swap(x,y):..." so that "x = 3; y
    >> = 7; swap(x,y);" given x=7,y=3??
    >> (I want to use Perl's Ref "\" operator, or C's &).
    >> (And if I cannot do this [other than creating an Int class], is this
    >> behavior limited to strings,
    >>  tuples, and numbers)

    >
    > You can't do that*. Its not limited to any certain type of objects. You
    > can't manipulate calling scopes: if you really want to do that sort of
    > explicit namespace mangling, use dictionaries (or objects, really) as
    > the namespace to mangle and pass them around.
    >
    >> 3.  Why might one want to store "strings" as "objects" in numpy
    >> arrays?  (Maybe they wouldn't)?

    >
    > I don't use numpy. No idea.
    >
    >> 4.  Is there a way for me to make some function-definitions explicitly
    >> module-local?

    >
    > In what sense? If you prepend them with an underscore, the function
    > won't be imported with "from x import *". You can also explicitly
    > control what is imported in that way with a module-level __all__ attribute.
    >
    > Now that won't stop someone from doing "import x" and
    > "x._your_private_function" but Python doesn't believe in enforicng
    > restrictions.
    >
    >> (Actually related to Q3 below: Is there a way to create an anonymous scope?)

    >
    > No. You can create a limited anonymous function with lambda, but note it
    > takes only an expression-- no statements in it.
    >
    >> 5. Is there a way for me to introduce a indention-scoped variables in python?
    >> See for example: http://evanjones.ca/python-pitfall-scope.html

    >
    > No. Python only has three scopes historically; local, global, and
    > builtin. Then post-2.2(ish, I forget) limited nested scoping -- but only
    > with nested functions, and you can't (until Python 3) re-bind variables
    > in outer scopes (though you can modify them if they are mutable objects).
    >
    > Python's scoping is very basic (we generally think this is a good thing;
    > others are never happy with it) and is not fully lexical scoped.
    >
    >> 6.  Is there a Python Checker that enforces Strunk and White and is
    >> bad English grammar anti-python?  (Only half joking)
    >> http://www.python.org/dev/peps/pep-0008/

    >
    > Check out pylint and/or pychecker, which do various style-based
    > checking. If you're asking for something else, I can't pierce your
    > sarcasm to figure out what.
    >
    > --
    >
    >   Stephen Hansen
    >   ... Also: Ixokai
    >   ... Mail: me+list/python (AT) ixokai (DOT) io
    >   ... Blog: http://meh.ixokai.io/
    >
    > * Yes, I know its actually possible, to manipulate outer/calling scopes
    > with frame hacking. This is dangerous / bad / an implementation detail
    > that one should not rely on or use, generally speaking. If you need to
    > do this you're writing Java or Perl or C in Python, instead of writing
    > Python in Python, so are probably doing all kinds of things that are
    > slow / bad / dangerous / just not taking advantage of Python's strengths.
    >
    >
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >
    >
    wheres pythonmonks, Jul 22, 2010
    #1
    1. Advertising

  2. wheres pythonmonks

    Carl Banks Guest

    On Jul 22, 3:34 pm, wheres pythonmonks <>
    wrote:
    > Okay -- so I promised that I would try the namespace mangling
    > approach, and here's what I have come up with:
    >
    > Approach #1:  Pass in the variables to be swapped as strings.  (boring)
    >
    > >>> import sys
    > >>> def swap(n1,n2):

    >
    > ...  try:
    > ...   raise RuntimeException()
    > ...  except:
    > ...   e,b,t = sys.exc_info()
    > ...  ldict = t.tb_frame.f_back.f_locals
    > ...  t = ldict[n1];
    > ...  ldict[n1] = ldict[n2]
    > ...  ldict[n2] = t
    > ...>>> x = 'A'
    > >>> y = 'B'
    > >>> id(x)

    > 47946650437696
    > >>> id(y)

    > 47946649710192
    > >>> swap('x','y')
    > >>> print id(x)

    > 47946649710192
    > >>> print id(y)

    > 47946650437696
    > >>> print x,y

    >
    > B A


    Have you tried calling this swap inside a function? I bet you
    haven't.

    def test():
    x = "A"
    y = "B"
    swap("x","y")
    print x,y


    > Approach #2:  Allow the user to pass in arbitrary objects, takes the
    > id, infer what the variable in by hashing all possible objects, and
    > then apply the swap operation above.
    >
    > >>> def swap2(o1,o2):

    >
    > ...  try:
    > ...   raise RuntimeException()
    > ...  except:
    > ...   e,b,t = sys.exc_info()
    > ...  ldict = t.tb_frame.f_back.f_locals
    > ...  iddict = dict( (id(v), k ) for k,v in ldict.items() )
    > ...  # print id(o1), id(o2)
    > ...  n1 = iddict[id(o1)]
    > ...  n2 = iddict[id(o2)]
    > ...  t = ldict[n1];
    > ...  ldict[n1] = ldict[n2]
    > ...  ldict[n2] = t
    > ...
    >
    > >>> print x,y

    > B A
    > >>> swap2(x,y)
    > >>> print x,y

    > A B


    Same question.


    > Now, I want to make the above codes more "Pythonic"


    It's simply not possible (let alone Pythonic), in general, to rebind
    variables in the namespace of the caller.

    You were able to do it for a very limited circumstance, when the
    calling namespace was module-level. It doesn't work when the calling
    namespace is a function. This is true in Python 2 and 3.

    IMO, even if it could work, the very act of rebinding variables in
    another namespace is unPythonic. About the only time I've resorted to
    it is some metaprogramming tasks, and even then I give the functions
    that do it very explicit names, and I still feel dirty.


    > -- is there a way to:
    >
    > 1.  Get the function's arguments from the perspective of the caller?
    >
    > def f(x):
    >   print "caller's view of x = %s" % callersview(x)
    >
    > Then, f(1+2+3) would yield:
    > caller's view of x = 1 + 2 + 3


    Nope, other than inspecting the caller's frame.

    > 2.  Is there a better way to loopup by id?  I'm not very familiar with
    > sys.exc_info, but creating the id->name hash each time seems like
    > overkill.


    Looking up by id is a bad idea in general. Objects associated with an
    id can be destroyed, and id be reused. So if you're storing an id, by
    the time you get to it it could be a different object, or an object
    that no longer exists.


    > 3.  Is there a reference on all the special variables, like __foo__?


    Python Language Reference


    > 4.  Is there any work on deparsing (like Perl's deparse) lambda
    > functions to inline algebra and get a performance gain?


    psyco (q.g.) might help, not sure if it'll help much for lambdas,
    though.

    > Thanks again for your input,
    >
    > W
    >
    > ( from Perl-hacker to Python Programmer )


    No offense, but you seem like you're still tying to be a hacker. If
    that's what you want, fine, but generally speaking (and particularly
    for Python), you are going to have a better experience if you do it
    the language's way.

    And just to throw this out there, based on your questions I think it's
    possible that Ruby would fit your style better. (It lets you play
    fast and loose with namespaces and code blocks and such.)


    Carl Banks
    Carl Banks, Jul 23, 2010
    #2
    1. Advertising

  3. Thanks for pointing out that swap (and my swap2) don't work everywhere
    -- is there a way to get it to work inside functions?

    "No offense, but you seem like you're still tying to be a hacker. If
    that's what you want, fine, but generally speaking (and particularly
    for Python), you are going to have a better experience if you do it
    the language's way."

    None taken, but I always think that it is the language's job to
    express my thoughts... I don't like to think that my thoughts are
    somehow constrained by the language.

    The truth is that I don't intend to use these approaches in anything
    serious. However, I've been known to do some metaprogramming from
    time to time.

    In a recent application, I pass in a list of callables (lambdas) to be
    evaluated repeatedly.
    Clearly, a superior solution is to pass a single lambda that returns a
    list. [Less function call dispatches]
    However, it might be more efficient to avoid the function call
    overhead completely and pass-in a string which is substituted into a
    string code block, compiled, and executed.

    W





    On Thu, Jul 22, 2010 at 8:12 PM, Carl Banks <> wrote:
    > On Jul 22, 3:34 pm, wheres pythonmonks <>
    > wrote:
    >> Okay -- so I promised that I would try the namespace mangling
    >> approach, and here's what I have come up with:
    >>
    >> Approach #1:  Pass in the variables to be swapped as strings.  (boring)
    >>
    >> >>> import sys
    >> >>> def swap(n1,n2):

    >>
    >> ...  try:
    >> ...   raise RuntimeException()
    >> ...  except:
    >> ...   e,b,t = sys.exc_info()
    >> ...  ldict = t.tb_frame.f_back.f_locals
    >> ...  t = ldict[n1];
    >> ...  ldict[n1] = ldict[n2]
    >> ...  ldict[n2] = t
    >> ...>>> x = 'A'
    >> >>> y = 'B'
    >> >>> id(x)

    >> 47946650437696
    >> >>> id(y)

    >> 47946649710192
    >> >>> swap('x','y')
    >> >>> print id(x)

    >> 47946649710192
    >> >>> print id(y)

    >> 47946650437696
    >> >>> print x,y

    >>
    >> B A

    >
    > Have you tried calling this swap inside a function?  I bet you
    > haven't.
    >
    > def test():
    >    x = "A"
    >    y = "B"
    >    swap("x","y")
    >    print x,y
    >
    >
    >> Approach #2:  Allow the user to pass in arbitrary objects, takes the
    >> id, infer what the variable in by hashing all possible objects, and
    >> then apply the swap operation above.
    >>
    >> >>> def swap2(o1,o2):

    >>
    >> ...  try:
    >> ...   raise RuntimeException()
    >> ...  except:
    >> ...   e,b,t = sys.exc_info()
    >> ...  ldict = t.tb_frame.f_back.f_locals
    >> ...  iddict = dict( (id(v), k ) for k,v in ldict.items() )
    >> ...  # print id(o1), id(o2)
    >> ...  n1 = iddict[id(o1)]
    >> ...  n2 = iddict[id(o2)]
    >> ...  t = ldict[n1];
    >> ...  ldict[n1] = ldict[n2]
    >> ...  ldict[n2] = t
    >> ...
    >>
    >> >>> print x,y

    >> B A
    >> >>> swap2(x,y)
    >> >>> print x,y

    >> A B

    >
    > Same question.
    >
    >
    >> Now, I want to make the above codes more "Pythonic"

    >
    > It's simply not possible (let alone Pythonic), in general, to rebind
    > variables in the namespace of the caller.
    >
    > You were able to do it for a very limited circumstance, when the
    > calling namespace was module-level.  It doesn't work when the calling
    > namespace is a function.  This is true in Python 2 and 3.
    >
    > IMO, even if it could work, the very act of rebinding variables in
    > another namespace is unPythonic.  About the only time I've resorted to
    > it is some metaprogramming tasks, and even then I give the functions
    > that do it very explicit names, and I still feel dirty.
    >
    >
    >> -- is there a way to:
    >>
    >> 1.  Get the function's arguments from the perspective of the caller?
    >>
    >> def f(x):
    >>   print "caller's view of x = %s" % callersview(x)
    >>
    >> Then, f(1+2+3) would yield:
    >> caller's view of x = 1 + 2 + 3

    >
    > Nope, other than inspecting the caller's frame.
    >
    >> 2.  Is there a better way to loopup by id?  I'm not very familiar with
    >> sys.exc_info, but creating the id->name hash each time seems like
    >> overkill.

    >
    > Looking up by id is a bad idea in general.  Objects associated with an
    > id can be destroyed, and id be reused.  So if you're storing an id, by
    > the time you get to it it could be a different object, or an object
    > that no longer exists.
    >
    >
    >> 3.  Is there a reference on all the special variables, like __foo__?

    >
    > Python Language Reference
    >
    >
    >> 4.  Is there any work on deparsing (like Perl's deparse) lambda
    >> functions to inline algebra and get a performance gain?

    >
    > psyco (q.g.) might help, not sure if it'll help much for lambdas,
    > though.
    >
    >> Thanks again for your input,
    >>
    >> W
    >>
    >> ( from Perl-hacker to Python Programmer )

    >
    > No offense, but you seem like you're still tying to be a hacker.  If
    > that's what you want, fine, but generally speaking (and particularly
    > for Python), you are going to have a better experience if you do it
    > the language's way.
    >
    > And just to throw this out there, based on your questions I think it's
    > possible that Ruby would fit your style better.  (It lets you play
    > fast and loose with namespaces and code blocks and such.)
    >
    >
    > Carl Banks
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >
    wheres pythonmonks, Jul 23, 2010
    #3
  4. On Thu, 22 Jul 2010 18:34:11 -0400, wheres pythonmonks wrote:

    > Okay -- so I promised that I would try the namespace mangling approach,
    > and here's what I have come up with:
    >
    > Approach #1: Pass in the variables to be swapped as strings. (boring)


    Boring and slow and stupid. It makes an interesting trick to prove it can
    (almost) be done, but for production use? No way. There is nothing that
    *needs* call-by-reference that can't be done just as effectively using a
    slightly different approach.

    This approach also has the fatal flaw that not all objects have names, or
    have only one name. In Python, objects are often anonymous, and the
    standard Python idiom for swapping works fine for them:

    a = [1, 2, 3, "d", 5]
    b = ["a", "b", "c", 4, "e"]
    a[3], b[3] = b[3], a[3]

    I expect your hack to choke and die if you try swapping anonymous objects.


    [snip successful test of swapping using named globals]

    As Carl already pointed out, this doesn't work outside of the global
    scope.

    This demonstrates an interesting lesson re testing. It's not enough to
    test these hacks with names in the global scope. You also need to test
    them with names in a local and nested scope, and in classes.


    [...]
    > Now, I want to make the above codes more "Pythonic"


    The way to make them more Pythonic is to avoid them like the plague.

    One of the differences in philosophy between Perl and Python is that
    Python doesn't approve of doing things just because you can. There is
    very little interest in or respect given to hacking Python. We're
    programmers, not hackers, and we look for the most simple way to do
    things, not the gnarliest or trickiest or least obvious way.

    (Any yet, as a general rule, neither does Python particular get in your
    way. We have a saying: we're all adults here, if you want to shoot
    yourself in the foot, go right ahead.)

    Occasionally, *very* occasionally, that makes it hard to do something
    that would be simple in another language. But much rarer than you might
    think, and a lot of popular programming idioms are work-arounds that are
    simply not needed in Python. E.g. call-by-reference itself was a work-
    around to prevent unnecessary copying of large data structures like
    arrays in languages like Algol and Pascal (or so I understand). When Java
    guys come here and start asking how to implement design patterns in
    Python, 9 times out of 10 the answer is "you don't need it" rather than
    "you can't do it".

    It's not quite true that we consider "hack" to be a pejorative, we're
    certainly true of the positive uses of the word. But as a general rule
    the Python community looks rather askance at anything that might be
    described as a hack. We're far more likely to describe something as a
    dirty hack than a cool, nifty or amazing hack.

    It's not true, as some folks say, that there is "only one way to do it"
    in Python. But the Python ideal is for there to be "one obvious way to do
    it". If there's an obvious way, why would you look for an obscure, tricky
    hack? You better have a good reason for not using the obvious way,
    because writing the code is the *smallest* part of the job. You need to
    test it, and debug it, and maintain it, and they're all much, much harder.


    > is there a way to:
    >
    > 1. Get the function's arguments from the perspective of the caller?


    I don't understand the question.

    If the caller passes arg = [1,2,3], then both the caller and the called
    function agree that the argument is the list [1,2,3]. Both caller and
    callee see the same list. It would be a pretty strange programming
    language where the called function saw something different from what the
    caller passed...



    > 2. Is there a better way to loopup by id? I'm not very familiar with
    > sys.exc_info, but creating the id->name hash each time seems like
    > overkill.


    No.


    > 3. Is there a reference on all the special variables, like __foo__?


    If you're talking about "magic methods" and special attributes, like
    obj.__len__, then you should read this:

    http://docs.python.org/reference/datamodel.html

    This may also be helpful:

    http://www.ironpythoninaction.com/magic-methods.html

    If you're talking about special globals like __name__, I don't think
    there are any others. __name__ is (confusingly) documented here:

    http://docs.python.org/library/__main__.html



    > 4. Is there any work on deparsing (like Perl's deparse) lambda
    > functions to inline algebra and get a performance gain?


    No. How would you do that? If I have something like this:


    def my_func(arg):
    return some_class(1, 2, 3, callback=lambda x: arg.method(x))

    how would you inline that? *Where* would you inline that?

    Perhaps you're thinking that lambdas are commonly used like this:

    def my_func(args):
    f = lambda a, b, c: 3*a + 4*b -2*c
    results = []
    for x in args:
    results.append(f(2, x, 3))
    results.append(f(x, x**2, x**3)
    return results

    then, yes, that lambda could be inlined. But that's a rare and uncommon
    use for lambdas, and some would say unpythonic.

    Even if you could inline it, CPython isn't big on micro-optimizations.
    It's generally considered that the extra complexity and risk of bugs
    isn't worth the tiny performance gain. Simplicity itself is a virtue, and
    many optimizations tend to be anything but simple, if not dirty hacks.



    --
    Steven
    Steven D'Aprano, Jul 23, 2010
    #4
  5. On 7/22/10 7:47 PM, wheres pythonmonks wrote:
    > Thanks for pointing out that swap (and my swap2) don't work everywhere
    > -- is there a way to get it to work inside functions?
    >
    > "No offense, but you seem like you're still tying to be a hacker. If
    > that's what you want, fine, but generally speaking (and particularly
    > for Python), you are going to have a better experience if you do it
    > the language's way."
    >
    > None taken, but I always think that it is the language's job to
    > express my thoughts... I don't like to think that my thoughts are
    > somehow constrained by the language.


    The thing is, every language is adept at expressing different kinds of
    abstractions. They have different goals and ways of encouraging certain
    types of solutions while discouraging (and many times simply not even
    trying to offer support for) others: you're going up against those
    'discouraged' very, very hard-- and you're going to hit a wall :) The
    Python language does constrain your expressiveness in these sorts of
    areas, and there's no way around it.

    If that doesn't suit you-- you're free to use another language which
    works better to how your brain works. Ruby actually might be a very good
    suggestion. I don't mean this as a 'Deal with it or f- off, loser'
    statement. :) I mean that Python uses a very simple model in how it
    handles namespaces, calling and similar -- a lot of what seems
    completely natural to express in other languages is either slow,
    convoluted, complicated or flatly impossible here. On purpose.

    But, for those things that aren't expressed easily in Python, there's
    almost always a *different way* to express the actual need and
    intention-- in a way that is elegant and direct, in Python. You can't do
    it the other way "Pythonic", because "Pythonic" is to *not* do it that
    way. To not do things like try to treat variables as if they had
    box-like-behavior.

    > The truth is that I don't intend to use these approaches in anything
    > serious. However, I've been known to do some metaprogramming from
    > time to time.


    Depending on how you define "metaprogramming", Python is pretty
    notoriously ill-suited towards the task (more, its basically considered
    a feature it doesn't let you go there) -- or, it allows you to do vast
    amounts of stuff with its few dark magic hooks. I've never had a
    satisfying definition of metaprogramming that more then 50% of any group
    agree with, so I'm not sure which you're looking for. :)

    Python allows you to easily override nearly all operations and
    interactions between objects, construct classes, instances and such at
    runtime and modify them at any time. If metaprogramming is this to you,
    basically runtime tweaking and modification of classes types objects and
    the like, Python's good to go.

    But! What it doesn't let you do is get clever with syntax and write a
    sort of "simplified" or domain specific language to achieve certain
    sorts of repetitive tasks quickly. You always end up writing normal
    Python that looks like all other Python. You just might have a few more
    __methods__ and learn some dark magic like metaclasses and descriptors
    and decorators. (Not that -all- uses of such are dark magic, but when
    you start combining those your code can start to resemble a magic spell
    doing unholy things-- like my library with classes that have
    argument-based method overloading, so x.test("hi") and x.test("hi", 2)
    call two totally different functions. Not that I'll ever admit to having
    written the beast, nor that I actually did more then use it for pure
    proof of concept, and neither shall I willingly ever show anyone the
    monstrosity).

    > In a recent application, I pass in a list of callables (lambdas) to be
    > evaluated repeatedly.
    > Clearly, a superior solution is to pass a single lambda that returns a
    > list. [Less function call dispatches]


    > However, it might be more efficient to avoid the function call
    > overhead completely and pass-in a string which is substituted into a
    > string code block, compiled, and executed.


    This is the kind of "metaprogramming" where Python says nyet, that first
    kind I mentioned about being Notoriously Ill Suited. You can do things
    like compile code dynamically, generate up bytecode even, but it'll
    never be more efficient.

    Use a generator instead. :)

    --

    Stephen Hansen
    ... Also: Ixokai
    ... Mail: me+list/python (AT) ixokai (DOT) io
    ... Blog: http://meh.ixokai.io/


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v2.0.10 (Darwin)

    iQEcBAEBAgAGBQJMSRksAAoJEKcbwptVWx/l/oUH/1kFYM7aVI8pPE84LkjEedUZ
    8li91bCLJ7ZRhOQDlFb2Z3vMddmm6rbP6xD2EUacMzYGtUXC05LSM6SEOZU410XI
    osgDac4LvSRz5PjrLIy853ozViS2UMHYHL2td3E9yhFlzLcMPNLeAgsW4l9l4WEB
    /DYsJ0x/kdWbnxjBqgrbPByWQEyren2fRjbClVVYqbwZmyE2d+V2FQC83vOzCmHS
    8YeGdA8jmYDrWpiuFb2N5yirPEGrIh4dFiDNGoW8p8JusLpKJUebIdz+SvDsLgRz
    Iimr57pAEyF7KqlsfQxVmSeXxEE4ilapCq0fn34QEpUYTPHj2ekFY0xwwqFxVS4=
    =FyAb
    -----END PGP SIGNATURE-----
    Stephen Hansen, Jul 23, 2010
    #5
  6. wheres pythonmonks

    Carl Banks Guest

    On Jul 22, 7:47 pm, wheres pythonmonks <>
    wrote:
    > Thanks for pointing out that swap (and my swap2) don't work everywhere
    > -- is there a way to get it to work inside functions?


    Impossible without hacking the interpreter.


    > "No offense, but you seem like you're still tying to be a hacker.  If
    > that's what you want, fine, but generally speaking (and particularly
    > for Python), you are going to have a better experience if you do it
    > the language's way."
    >
    > None taken, but I always think that it is the language's job to
    > express my thoughts...


    I don't. In fact whenever I investigate new languages I make an
    effort to accommodate its thinking, I find I learn a lot more than I
    would by it into my preconceived thinking. YMMV.


    > I don't like to think that my thoughts are
    > somehow constrained by the language.


    And yet your previous thoughts seem oddly constrained by Perl....


    If you really want a language that can accommodate any thought you
    could possibly have, you should check out Lisp.

    (defmacro swap (a b)
    '(let ((t1 ,a)
    (t2 ,b))
    (setq ,b t1)
    (setq ,a t2)))

    hygiene-left-as-an-exercise-ly yr's,


    Carl Banks
    Carl Banks, Jul 23, 2010
    #6
  7. On Thu, 22 Jul 2010 22:47:11 -0400, wheres pythonmonks wrote:

    > Thanks for pointing out that swap (and my swap2) don't work everywhere
    > -- is there a way to get it to work inside functions?


    Not in CPython. In IronPython or Jython, maybe, I don't know enough about
    them. But even if you got it to work, it would be an implementation-
    dependent trick.

    [...]
    > I always think that it is the language's job to express
    > my thoughts...


    Ha, no, it's the language's job to execute algorithms. If it did so in a
    way that is similar to the way people think, that would be scary. Have
    you *seen* the way most people think???

    *wink*


    > I don't like to think that my thoughts are somehow
    > constrained by the language.



    Whether you "like" to think that way, or not, thoughts are influenced and
    constrained by language. While I don't accept the strong form of the
    Sapir-Whorf hypothesis (that some thoughts are *impossible* due to lack
    of language to express them, a position which has been discredited), a
    weaker form is almost certainly correct. Language influences thought.

    Turing Award winner and APL creator Kenneth E. Iverson gave a lecture
    about this theme, "Notation as a tool of thought", and argued that more
    powerful notations aided thinking about computer algorithms.

    Paul Graham also discusses similar ideas, such as the "blub paradox".
    Graham argues that the typical programmer is "satisfied with whatever
    language they happen to use, because it dictates the way they think about
    programs". We see this all the time, with people trying to write Java in
    Python, Perl in Python, and Ruby in Python.

    And Yukihiro Matsumoto has said that one of his inspirations for creating
    Ruby was the science fiction novel Babel-17, which in turn is based on
    the Sapir-Whorf Hypothesis.



    > The truth is that I don't intend to use these approaches in anything
    > serious. However, I've been known to do some metaprogramming from time
    > to time.
    >
    > In a recent application, I pass in a list of callables (lambdas) to be
    > evaluated repeatedly.


    Are you aware that lambdas are just functions? The only differences
    between a "lambda" and a function created with def is that lambda is
    syntactically limited to a single expression, and that functions created
    with lambda are anonymous (they don't have a name, or at least, not a
    meaningful name).


    > Clearly, a superior solution is to pass a single lambda that returns a
    > list.


    I don't see why you say this is a superior solution, mostly because you
    haven't explained what the problem is.


    > [Less function call dispatches]


    How? You have to generate the list at some point. Whether you do it like
    this:

    functions = (sin, cos, tan)
    data = (2.3, 4.5, 1.2)
    result = [f(x) for f, x in zip(functions, data)]

    or like this:

    result = (lambda x, y, z: return (sin(x), cos(y), tan(z))
    )(2.3, 4.5, 1.2)

    you still end up with the same number of function calls (four). Any
    execution time will almost certainly be dominated by the work done inside
    the lambda (sin, cos and tan) rather than the infrastructure. And unless
    you have profiled your code, you would be surprised as to where the
    bottlenecks are. Your intuitions from Perl will not guide you well in
    Python -- it's a different language, and the bottlenecks are different.


    > However, it might be more
    > efficient to avoid the function call overhead completely and pass-in a
    > string which is substituted into a string code block, compiled, and
    > executed.


    See, that's *exactly* what I mean about intuitions. No no no no!!! Using
    exec or eval in Python code is almost certainly a *pessimation*, not an
    optimization! I expect this will be an order of magnitude slower to
    parse, compile and execute a string than it is to execute a function.
    Using exec or friends to avoid the overhead of function calls is like
    pushing your car to work to avoid the overhead of having to get in and
    out of the car.

    But of course, don't take my word for it. Write your code and profile it,
    see where the bottlenecks are. I might be wrong.



    --
    Steven
    Steven D'Aprano, Jul 23, 2010
    #7
  8. On Thu, 22 Jul 2010 21:23:05 -0700, Stephen Hansen wrote:

    > On 7/22/10 7:47 PM, wheres pythonmonks wrote:

    [...]
    >> The truth is that I don't intend to use these approaches in anything
    >> serious. However, I've been known to do some metaprogramming from time
    >> to time.

    >
    > Depending on how you define "metaprogramming", Python is pretty
    > notoriously ill-suited towards the task (more, its basically considered
    > a feature it doesn't let you go there) -- or, it allows you to do vast
    > amounts of stuff with its few dark magic hooks. I've never had a
    > satisfying definition of metaprogramming that more then 50% of any group
    > agree with, so I'm not sure which you're looking for. :)


    I disagree strongly at your characterisation that Python is notorious for
    being ill-suited towards metaprogramming. I'd say the complete opposite
    -- what is considered dark and scary metaprogramming tasks in other
    languages is considered too ordinary to even mention in Python.

    If you have a class that defines a single member (or attribute in Python
    terminology) "spam", and you want to add a second "ham" to a specific
    instance, such a thing is either deep, dark metaprogramming in some
    languages, if not outright impossible. In Python it is not even
    noteworthy:

    instance.ham = "something" # *yawns*

    Recently there was a thread started by some Java or C++ refugee who was
    distressed about attribute access in Python, because it made
    metaprogramming frighteningly easy:

    http://mail.python.org/pipermail/python-list/2010-June/1248029.html

    My response at the time was: Python makes metaprogramming *easy*:

    http://mail.python.org/pipermail/python-list/2010-June/1248053.html

    I can't imagine how he would have reacted if we had showed him how easy
    it is to monkey-patch built-in functions...

    [...]
    > But! What it doesn't let you do is get clever with syntax and write a
    > sort of "simplified" or domain specific language to achieve certain
    > sorts of repetitive tasks quickly. You always end up writing normal
    > Python that looks like all other Python.


    Exactly... 90% of the time that you think you want a DSL, Python beat you
    to it.

    It is true that other languages (like Lisp, or Forth) allow you to write
    your own syntax. That's incredibly powerful, but it also has serious
    costs. If you can define your own syntax, that means every piece of code
    you look at is potentially a different language.


    --
    Steven
    Steven D'Aprano, Jul 23, 2010
    #8
  9. Funny... just spent some time with timeit:

    I wonder why I am passing in strings if the callback overhead is so light....

    More funny: it looks like inline (not passed in) lambdas can cause
    python to be more efficient!
    >>> import random
    >>> d = [ (['A','B'][random.randint(0,1)],x,random.gauss(0,1)) for x in xrange(0,1000000) ]
    >>> def A1(): j = [ lambda t: (t[2]*t[1],t[2]**2+5) for t in d ]


    >>> def A2(): j = [ (t[2]*t[1],t[2]**2+5) for t in d ]


    >>> def A3(l): j = [ l(t) for t in d]


    >>> import timeit
    >>> timeit.timeit('A1()','from __main__ import A1,d',number=10);

    2.2185971572472454
    >>> timeit.timeit('A2()','from __main__ import A2,d',number=10);

    7.2615454749912942
    >>> timeit.timeit('A3(lambda t: (t[2]*t[1],t[2]**2+5))','from __main__ import A3,d',number=10);

    9.4334241349350947

    So: in-line lambda possible speed improvement. in-line tuple is slow,
    passed-in callback, slowest yet?

    Is this possibly right?

    Hopefully someone can spot the bug?

    W





    On Fri, Jul 23, 2010 at 4:10 AM, Steven D'Aprano
    <> wrote:
    > On Thu, 22 Jul 2010 22:47:11 -0400, wheres pythonmonks wrote:
    >
    >> Thanks for pointing out that swap (and my swap2) don't work everywhere
    >> -- is there a way to get it to work inside functions?

    >
    > Not in CPython. In IronPython or Jython, maybe, I don't know enough about
    > them. But even if you got it to work, it would be an implementation-
    > dependent trick.
    >
    > [...]
    >> I always think that it is the language's job to express
    >> my thoughts...

    >
    > Ha, no, it's the language's job to execute algorithms. If it did so in a
    > way that is similar to the way people think, that would be scary. Have
    > you *seen* the way most people think???
    >
    > *wink*
    >
    >
    >> I don't like to think that my thoughts are somehow
    >> constrained by the language.

    >
    >
    > Whether you "like" to think that way, or not, thoughts are influenced and
    > constrained by language. While I don't accept the strong form of the
    > Sapir-Whorf hypothesis (that some thoughts are *impossible* due to lack
    > of language to express them, a position which has been discredited), a
    > weaker form is almost certainly correct. Language influences thought.
    >
    > Turing Award winner and APL creator Kenneth E. Iverson gave a lecture
    > about this theme, "Notation as a tool of thought", and argued that more
    > powerful notations aided thinking about computer algorithms.
    >
    > Paul Graham also discusses similar ideas, such as the "blub paradox".
    > Graham argues that the typical programmer is "satisfied with whatever
    > language they happen to use, because it dictates the way they think about
    > programs". We see this all the time, with people trying to write Java in
    > Python, Perl in Python, and Ruby in Python.
    >
    > And Yukihiro Matsumoto has said that one of his inspirations for creating
    > Ruby was the science fiction novel Babel-17, which in turn is based on
    > the Sapir-Whorf Hypothesis.
    >
    >
    >
    >> The truth is that I don't intend to use these approaches in anything
    >> serious.  However, I've been known to do some metaprogramming from time
    >> to time.
    >>
    >> In a recent application, I pass in a list of callables (lambdas) to be
    >> evaluated repeatedly.

    >
    > Are you aware that lambdas are just functions? The only differences
    > between a "lambda" and a function created with def is that lambda is
    > syntactically limited to a single expression, and that functions created
    > with lambda are anonymous (they don't have a name, or at least, not a
    > meaningful name).
    >
    >
    >> Clearly, a superior solution is to pass a single lambda that returns a
    >> list.

    >
    > I don't see why you say this is a superior solution, mostly because you
    > haven't explained what the problem is.
    >
    >
    >> [Less function call dispatches]

    >
    > How? You have to generate the list at some point. Whether you do it like
    > this:
    >
    > functions = (sin, cos, tan)
    > data = (2.3, 4.5, 1.2)
    > result = [f(x) for f, x in zip(functions, data)]
    >
    > or like this:
    >
    > result = (lambda x, y, z: return (sin(x), cos(y), tan(z))
    >    )(2.3, 4.5, 1.2)
    >
    > you still end up with the same number of function calls (four). Any
    > execution time will almost certainly be dominated by the work done inside
    > the lambda (sin, cos and tan) rather than the infrastructure. And unless
    > you have profiled your code, you would be surprised as to where the
    > bottlenecks are. Your intuitions from Perl will not guide you well in
    > Python -- it's a different language, and the bottlenecks are different.
    >
    >
    >> However, it might be more
    >> efficient to avoid the function call overhead completely and pass-in a
    >> string which is substituted into a string code block, compiled, and
    >> executed.

    >
    > See, that's *exactly* what I mean about intuitions. No no no no!!! Using
    > exec or eval in Python code is almost certainly a *pessimation*, not an
    > optimization! I expect this will be an order of magnitude slower to
    > parse, compile and execute a string than it is to execute a function.
    > Using exec or friends to avoid the overhead of function calls is like
    > pushing your car to work to avoid the overhead of having to get in and
    > out of the car.
    >
    > But of course, don't take my word for it. Write your code and profile it,
    > see where the bottlenecks are. I might be wrong.
    >
    >
    >
    > --
    > Steven
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >
    wheres pythonmonks, Jul 23, 2010
    #9
  10. wheres pythonmonks

    Peter Otten Guest

    wheres pythonmonks wrote:

    > Funny... just spent some time with timeit:
    >
    > I wonder why I am passing in strings if the callback overhead is so
    > light...
    >
    > More funny: it looks like inline (not passed in) lambdas can cause
    > python to be more efficient!
    >>>> import random
    >>>> d = [ (['A','B'][random.randint(0,1)],x,random.gauss(0,1)) for x in
    >>>> xrange(0,1000000) ] def A1(): j = [ lambda t: (t[2]*t[1],t[2]**2+5) for
    >>>> t in d ]

    >
    >>>> def A2(): j = [ (t[2]*t[1],t[2]**2+5) for t in d ]

    >
    >>>> def A3(l): j = [ l(t) for t in d]

    >
    >>>> import timeit
    >>>> timeit.timeit('A1()','from __main__ import A1,d',number=10);

    > 2.2185971572472454
    >>>> timeit.timeit('A2()','from __main__ import A2,d',number=10);

    > 7.2615454749912942
    >>>> timeit.timeit('A3(lambda t: (t[2]*t[1],t[2]**2+5))','from __main__
    >>>> import A3,d',number=10);

    > 9.4334241349350947
    >
    > So: in-line lambda possible speed improvement. in-line tuple is slow,
    > passed-in callback, slowest yet?
    >
    > Is this possibly right?
    >
    > Hopefully someone can spot the bug?


    A1() makes a lot of lambdas but doesn't invoke them. Once that is fixed A1()
    is indeed slower than A2():

    >>> from timeit import timeit
    >>> import random
    >>> d = [(random.choice("AB"), x, random.gauss(0, 1)) for x in

    xrange(10**6)]
    >>> def A1(d=d): return [(lambda t: (t[2]*t[1],t[2]**2+5))(t) for t in d]

    ....
    >>> def A2(d=d): return [(t[2]*t[1], t[2]**2+5) for t in d]

    ....
    >>> assert A1() == A2()
    >>> timeit("A1()", "from __main__ import A1", number=10)

    14.275790929794312
    >>> timeit("A2()", "from __main__ import A2", number=10)

    10.31659197807312

    Peter
    Peter Otten, Jul 23, 2010
    #10
  11. wheres pythonmonks

    Dave Angel Guest

    Duncan Booth wrote:
    > <snip>
    > Consider languages where you can easily write a swap function (or any other
    > function that updates its arguments). e.g. consider C or C#.
    >
    > For C your function must take pointers to the variables, so when you call
    > swap you have to make this explicit by taking the address of each variable:
    >
    > foo(&x, &y);
    >
    > For C# the function takes references to the variables. Again you have to
    > also make this explicit at the point of call by prefixing the argument with
    > 'ref':
    >
    > foo(ref x, ref y);
    >
    > Python is really no different: if you want a function to rebind its
    > arguments you have to make that explicit at the point of call. The only
    > difference is that in Python you make the rebinding explicit by assigning
    > to the names:
    >
    > x, y = foo(x, y)
    >
    >
    >

    I don't disagree with the overall point, but C has references (or at
    least C++ does, I don't think I've written any pure C code since 1992).
    If the function is declared to take references, the caller doesn't do a
    thing differently.

    void foo(int &a, int &b);

    is called by foo(x, y), and the function may indeed swap the arguments.

    If I recall correctly, pascal is the same way. The called function
    declares byref, and the caller doesn't do anything differently.

    DaveA
    Dave Angel, Jul 23, 2010
    #11
  12. On 7/23/10 2:05 AM, Steven D'Aprano wrote:
    > On Thu, 22 Jul 2010 21:23:05 -0700, Stephen Hansen wrote:
    >
    >> On 7/22/10 7:47 PM, wheres pythonmonks wrote:

    > [...]
    >>> The truth is that I don't intend to use these approaches in anything
    >>> serious. However, I've been known to do some metaprogramming from time
    >>> to time.

    >>
    >> Depending on how you define "metaprogramming", Python is pretty
    >> notoriously ill-suited towards the task (more, its basically considered
    >> a feature it doesn't let you go there) -- or, it allows you to do vast
    >> amounts of stuff with its few dark magic hooks. I've never had a
    >> satisfying definition of metaprogramming that more then 50% of any group
    >> agree with, so I'm not sure which you're looking for. :)

    >
    > I disagree strongly at your characterisation that Python is notorious for
    > being ill-suited towards metaprogramming. I'd say the complete opposite
    > -- what is considered dark and scary metaprogramming tasks in other
    > languages is considered too ordinary to even mention in Python.


    I rather think you missed my point entirely.

    'Depending on how you define "metaprogramming"'

    The 'Depending' was the most important part of that sentence. You go on
    to talk about runtime modification of classes and the like. That, Python
    lets you do quite readily, and then go on to do crazy amounts of without
    any significant effort.

    That's one definition of metaprogramming. That one Python does well.

    The other involves things like macros, or things where you basically
    write a new sub-language in the language itself to achieve some commonly
    desired task more efficiently (or just more succinctly). That's another
    definition of metaprogramming: where its not so much structures
    (classes, etc) which are modified at runtime (which Python lets you do
    readily), but the syntax or semantics of the language itself. That
    Python isn't game for.

    > [...]
    >> But! What it doesn't let you do is get clever with syntax and write a
    >> sort of "simplified" or domain specific language to achieve certain
    >> sorts of repetitive tasks quickly. You always end up writing normal
    >> Python that looks like all other Python.

    >
    > Exactly... 90% of the time that you think you want a DSL, Python beat you
    > to it.


    Yet, that is a branch of what is considered metaprogramming that the OP
    seems to be asking for, that we do not offer any sort of real support
    for. I was making this distinction.

    --

    Stephen Hansen
    ... Also: Ixokai
    ... Mail: me+list/python (AT) ixokai (DOT) io
    ... Blog: http://meh.ixokai.io/


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v2.0.10 (Darwin)

    iQEcBAEBAgAGBQJMScG9AAoJEKcbwptVWx/lAyMH/2K68t/FbQaBbnvBs7wS8hQE
    8+bbKar8VGcVAh+ORxTc5s6lWVsLAEEdiOoZezMo7D54erQg5vOjE1nDko8/fK1S
    nNKniExKZhMe3MYZUY3X/lZmOGHBvnz7wDBmcJvLiWwpauk3z6GsLWGD/E0flB/t
    v37bzKj2PHgbfMOP97TCGtq72QMWWE8E7Kf7QM3qOB4TDofJde0H9pkd+fZrxmMn
    yHAh78X1fCGakyrGTXlC6CrXd4rTFcYklWsovp2n2emZ8dkx4rlERkWPfL1mXdph
    jGQFDVFS/2z9W36ktD2gWwyhxJY1KbeDkonSZB0p5A2I+96Dk3od3oHgMljwxRc=
    =uj9J
    -----END PGP SIGNATURE-----
    Stephen Hansen, Jul 23, 2010
    #12
  13. wheres pythonmonks

    Terry Reedy Guest

    On 7/23/2010 4:10 AM, Steven D'Aprano wrote:

    > Using exec or friends to avoid the overhead of function calls is like
    > pushing your car to work to avoid the overhead of having to get in and
    > out of the car.


    And, of course, exec *is* a function call (explicitly in 3.x, but
    somewhere also in the innards of 2.x).

    Thanks for the laugh of the day.

    --
    Terry Jan Reedy
    Terry Reedy, Jul 23, 2010
    #13
  14. On Fri, 23 Jul 2010 09:22:16 -0700, Stephen Hansen wrote:

    > On 7/23/10 2:05 AM, Steven D'Aprano wrote:
    >> On Thu, 22 Jul 2010 21:23:05 -0700, Stephen Hansen wrote:
    >>
    >>> On 7/22/10 7:47 PM, wheres pythonmonks wrote:

    >> [...]
    >>>> The truth is that I don't intend to use these approaches in anything
    >>>> serious. However, I've been known to do some metaprogramming from
    >>>> time to time.
    >>>
    >>> Depending on how you define "metaprogramming", Python is pretty
    >>> notoriously ill-suited towards the task (more, its basically
    >>> considered a feature it doesn't let you go there) -- or, it allows you
    >>> to do vast amounts of stuff with its few dark magic hooks. I've never
    >>> had a satisfying definition of metaprogramming that more then 50% of
    >>> any group agree with, so I'm not sure which you're looking for. :)

    >>
    >> I disagree strongly at your characterisation that Python is notorious
    >> for being ill-suited towards metaprogramming. I'd say the complete
    >> opposite -- what is considered dark and scary metaprogramming tasks in
    >> other languages is considered too ordinary to even mention in Python.

    >
    > I rather think you missed my point entirely.
    >
    > 'Depending on how you define "metaprogramming"'
    >
    > The 'Depending' was the most important part of that sentence.


    Well, I suppose some folks might like to define words any way they like,
    so that "cat" means a reptile with no legs and "lunch time" means the
    thing you do in the shower, but I prefer to stick with common
    definitions. And the common definition of metaprogramming is that it is
    "programming about programming" -- programming where the data you are
    processing is itself programming code and data structures.

    http://en.wikipedia.org/wiki/Metaprogramming

    I did not miss your proviso, nor did I miss the fact that there are some
    metaprogramming techniques that Python is not very good at, such as
    runtime modification of syntax. I wrote:

    "It is true that other languages (like Lisp, or Forth) allow you to write
    your own syntax. That's incredibly powerful, but it also has serious
    costs. If you can define your own syntax, that means every piece of code
    you look at is potentially a different language."

    But what makes you think that the OP is trying to do that? There's
    nothing in his comments to indicate that to me. Perhaps I missed
    something.



    > You go on
    > to talk about runtime modification of classes and the like. That, Python
    > lets you do quite readily, and then go on to do crazy amounts of without
    > any significant effort.
    >
    > That's one definition of metaprogramming. That one Python does well.


    No, it's not a *definition* of metaprogramming. It is an aspect of
    metaprogramming, in the same way that roasting food is not a definition
    of cooking, it is one out of many cooking techniques.


    > The other involves things like macros, or things where you basically
    > write a new sub-language in the language itself to achieve some commonly
    > desired task more efficiently (or just more succinctly). That's another
    > definition of metaprogramming: where its not so much structures
    > (classes, etc) which are modified at runtime (which Python lets you do
    > readily), but the syntax or semantics of the language itself. That
    > Python isn't game for.


    You can't modify Python's syntax at runtime, but you can create DSLs in
    Python quite readily provided you accept the limitation of Python's
    syntax. There was even a tutorial at PyCon about it:

    http://us.pycon.org/2010/tutorials/jensen_languages/

    Although he doesn't use the term "DSL" anywhere in his essay, Guido's
    essay on creating graphs in Python essentially describes a DSL for graphs:

    http://www.python.org/doc/essays/graphs/

    In the Python Cookbook, Paul Dubois also gives an "application-specific-
    language" for graphs in a section called "Using Python Itself as a Little
    Language". Yes, it's limited to Python syntax, but it's still a DSL.

    And of course there are applications like Cheetah:

    http://www.cheetahtemplate.org/

    Python doesn't go all the way like Forth or Lisp, but there aren't very
    many metaprogramming techniques you can't do it in.



    --
    Steven
    Steven D'Aprano, Jul 24, 2010
    #14
  15. In article <4c495b50$0$28634$>,
    Steven D'Aprano <> wrote:
    >On Thu, 22 Jul 2010 21:23:05 -0700, Stephen Hansen wrote:
    >
    >> On 7/22/10 7:47 PM, wheres pythonmonks wrote:

    >[...]
    >>> The truth is that I don't intend to use these approaches in anything
    >>> serious. However, I've been known to do some metaprogramming from time
    >>> to time.

    >>
    >> Depending on how you define "metaprogramming", Python is pretty
    >> notoriously ill-suited towards the task (more, its basically considered
    >> a feature it doesn't let you go there) -- or, it allows you to do vast
    >> amounts of stuff with its few dark magic hooks. I've never had a
    >> satisfying definition of metaprogramming that more then 50% of any group
    >> agree with, so I'm not sure which you're looking for. :)

    >
    >I disagree strongly at your characterisation that Python is notorious for
    >being ill-suited towards metaprogramming. I'd say the complete opposite
    >-- what is considered dark and scary metaprogramming tasks in other
    >languages is considered too ordinary to even mention in Python.
    >
    >If you have a class that defines a single member (or attribute in Python
    >terminology) "spam", and you want to add a second "ham" to a specific
    >instance, such a thing is either deep, dark metaprogramming in some
    >languages, if not outright impossible. In Python it is not even
    >noteworthy:
    >
    >instance.ham = "something" # *yawns*
    >
    >Recently there was a thread started by some Java or C++ refugee who was
    >distressed about attribute access in Python, because it made
    >metaprogramming frighteningly easy:
    >
    >http://mail.python.org/pipermail/python-list/2010-June/1248029.html
    >
    >My response at the time was: Python makes metaprogramming *easy*:
    >
    >http://mail.python.org/pipermail/python-list/2010-June/1248053.html
    >
    >I can't imagine how he would have reacted if we had showed him how easy
    >it is to monkey-patch built-in functions...
    >
    >[...]
    >> But! What it doesn't let you do is get clever with syntax and write a
    >> sort of "simplified" or domain specific language to achieve certain
    >> sorts of repetitive tasks quickly. You always end up writing normal
    >> Python that looks like all other Python.

    >
    >Exactly... 90% of the time that you think you want a DSL, Python beat you
    >to it.
    >
    >It is true that other languages (like Lisp, or Forth) allow you to write
    >your own syntax. That's incredibly powerful, but it also has serious
    >costs. If you can define your own syntax, that means every piece of code
    >you look at is potentially a different language.


    The answer is, of course, discipline.
    I'm a Forth programmer and I morf Forth into an assembler.
    Now some sources become assembler sources and one should be
    very adamant about it. I've written a Perl interpreter for
    those sources, and a Python interpreter would be even easier.

    If I'm doing Python, I don't miss macro possibilities, but
    sometimes my code gets repetitive.
    If I ever get bored by repetition, there is m4.

    m4 < aap.pym > aap.py
    python aap.py

    (See my site below for Forth assemblers, and non-trivial m4 usage.)

    >--
    >Steven


    Groetjes Albert

    --
    --
    Albert van der Horst, UTRECHT,THE NETHERLANDS
    Economic growth -- being exponential -- ultimately falters.
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
    Albert van der Horst, Aug 6, 2010
    #15
    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. Hazzard
    Replies:
    2
    Views:
    614
    Hazzard
    Apr 6, 2004
  2. Todd_Calhoun
    Replies:
    3
    Views:
    346
    Todd_Calhoun
    Mar 25, 2005
  3. Bruno Desthuilliers
    Replies:
    5
    Views:
    364
    Bruno Desthuilliers
    Aug 29, 2007
  4. wheres pythonmonks

    Easy questions from a python beginner

    wheres pythonmonks, Jul 11, 2010, in forum: Python
    Replies:
    40
    Views:
    859
  5. danielj

    Another Easy Beginner Question

    danielj, Jun 18, 2007, in forum: Ruby
    Replies:
    15
    Views:
    178
    Drew Olson
    Jun 18, 2007
Loading...

Share This Page