[Python-Dev] more on PEP 318

foo ishnigarrab at earthlink.net
Tue Mar 30 21:34:20 EST 2004


I haven't posted on this list much (at all?) but the 318 fiasco has caught my attnetion because it's something that I've been missing in python for a while now (it's actually sparked my search for more dynamic languages like scheme, etc). So I just thought I'd throw in my two sense (sic).

First of I'm +1 on

  def a(*args) as expr: pass

I'm very +1 (+2, +3?) on keywording (where 'as' can be 'mod' or whatever). Also +10 on expressionizing the decorator, where the decorator _evaluates_ to a sequence (or iterable) of callables

Secondly, I don't see why the wrappers should be restricted to simple identifiers that must be callables. One of the things that I've always loved about python is it's "we're all adults here" attitude and the concept of enforcing some arbitrary requirement for the sake of style enforcement seems unnessesary to me. I understand that

  def a(*args) as [lambda fn: fn, module.class.clsmeth, give_me_a_wrapper(some_arg)]: pass

(which, incidently, looks much better as

  def a(*args) as [lambda fn: fn,
                   module.class.clsmeth,
                   give_me_a_wrapper(some_arg)]:
      pass

thus pointing out that the fear of ugly expressions in decorators is a bit exagerated)

can be confusing and cumbersome, limiting it from happening isn't going to prevent some caffinated hacker from doing wacky things, it merely forces them to be more clever about it, i.e.:

---- helpers.py ----

  def argument_checked(*tests):
      def outter(fn):
          def inner(*args, **kwds):
              # I swear I don't come from a functional background! ;)
              for arg, test in zip(args, tests):
                  test(arg) # raises excpetion if doesn't meet check
              fn(*args, **kwds)
      return outter

  def memoized(fn):
      # ... stuff ...

---- main.py ----

  import helpers

  # ... misc code ...

  argument_checked = argument_checked(int, iter)
  memoized = helpers.memoized

  # ... maybe pages of code ...

  def doSomething(must_be_int, must_be_iterable) as [argument_checked, memoized]:
      # ... something ...

which IMHO is
* ugly because it assigns unnessesary names and clutters the file.
* a pain to have to do every time I want to use something that's not a pure identifier as a wrapper.
* and also in violation of "There should be one-- and preferably only one --obvious way to do it." because it leads one to believe that you can only use things which are predefined out-of-the box wrappers.
* is not explicit where the wrappers are coming from or how they have been formed

Another use case would be when a certain series of wrappers are going to be used over and over again, such as:

  def myFirstFunc(*args) as [argument_checked, memoized, protected, something_else, property]:
      pass

  def mySecondFunc(*args) as [argument_checked, memoized, protected, something_else, property]:
      pass

In such a case, typing out (or c-n-p-ing) that list of wrappers is tedious, not to mention a pattern to be refactorred out:

  my_wrappers = [argument_checked, memoized, protected, something_else, property]

  def myFirstFunc(*args) as my_wrappers:
      pass

  def mySecondFunc(*args) as my_wrappers:
      pass

As for lambda's etc, I see nothing wrong with

  def myFunc(*args) [lambda fn: something(fn)
                     lambda fn: something_else(fn)
                     lambda fn: more_stuff(fn)]:
      pass

so long as it isn't abused. And even then, I don't see why I should be specifically restricted from abusing it.


Anyways, there you go, take it or leave it.

Isaac Freeman



More information about the Python-Dev mailing list