2008-12-10 113 views
32

在Java中,您可以使用匿名内部类来内联定义一个新类。当您只需要重写该类的单个方法时,这非常有用。Python有类似Java的匿名内部类吗?

假设您要创建一个仅覆盖单个方法的OptionParser的子类(例如exit())。在Java中,你可以写这样的事情:

new OptionParser() { 

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

这段代码创建一个扩展OptionParser并覆盖只有exit()方法的匿名类。

Python中有一个类似的习语吗?在这些情况下使用哪一个习语?

回答

31

您可以使用内建函数type(name, bases, dict)来即时创建类。例如:

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

由于OptionParser是不是一个新的风格类,你必须明确地包括在基类的列表object

16

Java使用匿名类主要是模仿闭包或简单的代码块。由于在Python中,你可以轻松地绕过方法有没有必要为笨重的匿名内部类的构建:

def printStuff(): 
    print "hello" 

def doit(what): 
    what() 

doit(printStuff) 

编辑:我知道,这不是什么需要这种特殊情况。我刚刚描述了Java中匿名内部类最常见的python解决方案。

+3

-1我要继承optparse.OptionParser()不在身边方法引用传递。 – 2008-12-10 23:47:22

+0

在这种情况下,编写一个真正的子类有什么问题?我只是说明匿名内部类的最常见的用法。 – 2008-12-10 23:53:22

+2

+1:匿名内部类是Java减轻复杂语法的一种方式。 Python已经有了简单的语法,并且不需要匿名类来减轻负载。 – 2008-12-11 12:32:43

2

在Python中你有匿名函数,使用lambda语句声明。我不太喜欢它们 - 它们不太可读,并且功能有限。

但是,你说怎么样可以在Python中实现了完全不同的方法:

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

def meth_b(obj): 
    print "b" 

b = a() 
b.__class__.meth_a = meth_b 
5

Python中可能有更好的方法来解决你的问题。如果你能提供你想要做的更具体的细节,这将有所帮助。例如,如果您需要更改在代码中特定点调用的方法,可以通过将该函数作为参数传递来实现此目的(函数是python中的第一个类对象,可以将它们传递给函数,等等)。您还可以创建匿名lambda函数(但它们仅限于一个表达式)。

而且,由于蟒蛇是非常动态的,你可以改变一个对象的方法,它已经创造了object.method1 = alternative_impl1之后,虽然它实际上是更复杂一点,看到gnud's answer

11

您可以通过三种方式来完成它:

  1. 正确的子类
  2. 一个自定义的方法,你有对象调用作为参数
  3. (你可能想要的东西)(当然) - 添加新的方法,以一个对象(邻替换现有的)。选3的

例(编辑删除使用的“新”的模块 - 这是过时了,我不知道):

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() 
10

嗯,类是第一类对象,所以你可以创建他们在方法,如果你想。例如

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 

但是,真的,为什么不直接在正常水平上定义类呢?如果您需要对其进行自定义,请将自定义设置为参数__init__

(编辑:固定输入代码中的错误)

6

Python不支持这种直接(匿名类),但由于其简洁的语法它是不是真的有必要:

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

p = MyOptionParser() 

唯一缺点是你添加MyOptionParser到你的命名空间,但正如John Fouhy指出的那样,如果你要多次执行,你可以隐藏它。

0

您可以随时变量隐藏类:的

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

代替

var = new ...() {}; 
-5
#!/usr/bin/env python 
import os;os.system("""ruby << 'GOZER' 
anonymous_class = Class.new do 
    def hi(name) 
    puts "Hello: #{name}." 
    end 

    def too_late(message) 
    exit 1 
    end 
end 

anonymous_ghoul = anonymous_class.new 
anonymous_ghoul.hi("Egon Spengler") 
anonymous_ghoul.too_late <<-quote 

There's something very import I forgot to tell you. 

Don't cross the streams. 

It would be bad. 

quote 
GOZER""")