Correct type for a simple "bag of attributes" namespace object

Ian Kelly ian.g.kelly at gmail.com
Mon Aug 4 02:41:32 EDT 2014


On Sun, Aug 3, 2014 at 11:41 PM, Marko Rauhamaa <marko at pacujo.net> wrote:
> Steven D'Aprano <steve+comp.lang.python at pearwood.info>:
> And I'm talking about a third kind: object-based. It is in active
> (albeit limited) use in scheme: <URL: http://irreal.org/blog/?p=40>. I'm
> currently using the principle in a project of mine.
>
> In Java, you use anonymous classes for the same thing. In Python, you
> can think of the principle as one-time classes. So instead of writing:

In my experience, 99% of the time when anonymous classes are used,
they only contain one method. That's because they're not really being
used to implement some interface abstractly; they mostly exist to
provide a means of specifying a callback function in a language where
functions aren't first-class.

>
>     class A:
>         def __init__(self, x, y, z):
>             self.x = x
>             self.d = y * y + z * z
>
>         def f(self):
>             return self.x - self.d
>
> you write:
>
>     def A(x, y, z):
>         d = y * y + z * z
>
>         class Anonymous:
>             def f(self):
>                 return x - d
>
>         return Anonymous()

And it's the same thing here.  This isn't an interface.  It's a
function, so just return a function and be done with it. And in the
rare event that you actually mean to implement more than one method,
then you have enough functionality localized that it's probably
worthwhile to just name it and make it an actual class.

> Now, if you always did this, you would notice that classes are
> unnecessary clutter and would call for syntax like this:
>
>     def A(x, y, z):
>         d = y * y + z * z
>         return object:
>             def f():
>                 return x - d

The presence of "object" here feels totally unnecessary to me.  If the
point is to avoid having a class, then why create a class?  In this
case you could easily just return a function. To take a more complex
case, say the Scheme make-queue constructor that you linked to, you
could still just return a function; the same could be implemented in
Python 3 as:


def make_queue():
  front = []
  back = []
  def queue_command(command, data=None):
    def exchange():
      nonlocal front, back
      front = back; front.reverse()
      back = []
    if command == 'push':
      back.append(data)
    elif command == 'pop':
      if not front: exchange()
      return front.pop()
    elif command == 'peek':
      if not front: exchange()
      return front[-1]
    elif command == 'show':
      return str(list(reversed(front)) + back)
    else:
      raise ValueError('Illegal command to queue object ' + command)
  queue_command.push = lambda data: queue_command('push', data)
  queue_command.pop = lambda: queue_command('pop')
  queue_command.peek = lambda: queue_command('peek')
  return queue_command


>>> queue = make_queue()
>>> queue.push(1)
>>> queue.push(2)
>>> queue.pop()
1
>>> queue.push(3)
>>> queue.push(4)
>>> queue.pop()
2
>>> queue.peek()
3
>>> queue.pop()
3
>>> queue.pop()
4



More information about the Python-list mailing list