Does Python have something like anonymous inner classes of Java?

Question:

In Java you can define a new class inline using anonymous inner classes. This is useful when you need to rewrite only a single method of the class.

Suppose that you want create a subclass of OptionParser that overrides only a single method (for example exit()). In Java you can write something like this:

new OptionParser () {

    public void exit() {
        // body of the method
    }
};

This piece of code creates a anonymous class that extends OptionParser and override only the exit() method.

There is a similar idiom in Python? Which idiom is used in these circumstances?

Asked By: Andrea Francia

||

Answers:

Java uses anonymous classes mostly to imitate closures or simply code blocks. Since in Python you can easily pass around methods there’s no need for a construct as clunky as anonymous inner classes:

def printStuff():
   print "hello"

def doit(what):
   what()

doit(printStuff) 

Edit: I’m aware that this is not what is needed in this special case. I just described the most common python solution to the problem most commonly by anonymous inner classes in Java.

Answered By: Joachim Sauer

In python you have anonymous functions, declared using lambda statement. I do not like them very much – they are not so readable, and have limited functionality.

However, what you are talking about may be implemented in python with a completely different approach:

class a(object):
  def meth_a(self):
    print "a"

def meth_b(obj):
  print "b"

b = a()
b.__class__.meth_a = meth_b
Answered By: rob

Python probably has better ways to solve your problem. If you could provide more specific details of what you want to do it would help.

For example, if you need to change the method being called in a specific point in code, you can do this by passing the function as a parameter (functions are first class objects in python, you can pass them to functions, etc). You can also create anonymous lambda functions (but they’re restricted to a single expression).

Also, since python is very dynamic, you can change methods of an object after it’s been created object.method1 = alternative_impl1, although it’s actually a bit more complicated, see gnud’s answer

Answered By: hasen

You can accomplish this in three ways:

  1. Proper subclass (of course)
  2. a custom method that you invoke with the object as an argument
  3. (what you probably want) — adding a new method to an object (or replacing an existing one).

Example of option 3 (edited to remove use of “new” module — It’s deprecated, I did not know ):

import types
class someclass(object):
    val = "Value"
    def some_method(self):
        print self.val

def some_method_upper(self):
    print self.val.upper()

obj = someclass()
obj.some_method()

obj.some_method = types.MethodType(some_method_upper, obj)
obj.some_method()
Answered By: gnud

Well, classes are first class objects, so you can create them in methods if you want. e.g.

from optparse import OptionParser
def make_custom_op(i):
  class MyOP(OptionParser):
    def exit(self):
      print 'custom exit called', i
  return MyOP

custom_op_class = make_custom_op(3)
custom_op = custom_op_class()

custom_op.exit()          # prints 'custom exit called 3'
dir(custom_op)            # shows all the regular attributes of an OptionParser

But, really, why not just define the class at the normal level? If you need to customise it, put the customisation in as arguments to __init__.

(edit: fixed typing errors in code)

Answered By: John Fouhy

Python doesn’t support this directly (anonymous classes) but because of its terse syntax it isn’t really necessary:

class MyOptionParser(OptionParser):
    def exit(self, status=0, msg=None):
        # body of method

p = MyOptionParser()

The only downside is you add MyOptionParser to your namespace, but as John Fouhy pointed out, you can hide that inside a function if you are going to do it multiple times.

Answered By: davidavr

You can use the type(name, bases, dict) builtin function to create classes on the fly. For example:

op = type("MyOptionParser", (OptionParser,object), {"foo": lambda self: "foo" })
op().foo()

Since OptionParser isn’t a new-style class, you have to explicitly include object in the list of base classes.

Answered By: Joe Hildebrand

You can always hide class by variables:

 class var(...):
     pass
 var = var()

instead of

 var = new ...() {};
Answered By: Maciej Piechotka

This is what you would do in Python 3.7

#!/usr/bin/env python3
class ExmapleClass:
    def exit(self):
        print('this should NOT print since we are going to override')

ExmapleClass= type('', (ExmapleClass,), {'exit': lambda self: print('you should see this printed only')})()
ExmapleClass.exit()
Answered By: grepit

I do this in python3 usually with inner classes

class SomeSerializer():
    class __Paginator(Paginator):
        page_size = 10

    # defining it for e.g. Rest:
    pagination_class = __Paginator

    # you could also be accessing it to e.g. create an instance via method:
    def get_paginator(self):
        return self.__Paginator()

as i used double underscore, this mixes the idea of “mangling” with inner classes, from outside you can still access the inner class with SomeSerializer._SomeSerializer__Paginator, and also subclasses, but SomeSerializer.__Paginator will not work, which might or might not be your whish if you want it a bit more “anonymous”.

However I suggest to use “private” notation with a single underscore, if you do not need the mangling.

In my case, all I need is a fast subclass to set some class attributes, followed up by assigning it to the class attribute of my RestSerializer class, so the double underscore would denote to “not use it at all further” and might change to no underscores, if I start reusing it elsewhere.

Answered By: g4borg

Being perverse, you could use the throwaway name _ for the derived class name:

class _(OptionParser):

    def exit(self):
        pass  # your override impl
Answered By: otterrisk

Here is a more fancy way of doing Maciej’s method.
I defined the following decorator:

def newinstance(*args, **kwargs):
    def decorator(cls):
        return cls(*args, **kwargs)
    return decorator

The following codes are roughly equivalent (also works with args!)

// java

MyClass obj = new MyClass(arg) {
    public void method() {
        // body of the method
    }
};
# python

@newinstance(arg)
class obj(MyClass):
    def method(self):
        pass # body of the method

You can use this code from within a class/method/function if you want to define an "inner" class instance.

Answered By: User9123
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.