Python 是否有类似于 Java 的匿名内部类的东西?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/357997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:56:54  来源:igfitidea点击:

Does Python have something like anonymous inner classes of Java?

pythonclassanonymous-class

提问by Andrea Francia

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.

在 Java 中,您可以使用匿名内部类内联定义一个新类。当您只需要重写类的一个方法时,这很有用。

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

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

new OptionParser () {

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

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

这段代码创建了一个匿名类,该类OptionParser仅扩展和覆盖该exit()方法。

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

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

回答by Joe Hildebrand

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

您可以使用type(name, bases, dict)内置函数动态创建类。例如:

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

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

由于 OptionParser 不是新式类,因此您必须明确包含object在基类列表中。

回答by Joachim Sauer

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:

Java 主要使用匿名类来模仿闭包或简单的代码块。由于在 Python 中您可以轻松地传递方法,因此不需要像匿名内部类那样笨重的构造:

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.

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

回答by gnud

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).
  1. 适当的子类(当然)
  2. 您使用对象作为参数调用的自定义方法
  3. (您可能想要的)——向对象添加新方法(或替换现有方法)。

Example of option 3 (edited to remove use of "new" module -- It's deprecated, I did not know ):

选项 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()

回答by John Fouhy

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__.

但是,真的,为什么不只是在正常级别定义类呢?如果您需要自定义它,请将自定义作为参数放入__init__.

(edit: fixed typing errors in code)

(编辑:修复了代码中的打字错误)

回答by davidavr

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

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

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.

唯一的缺点是您将 MyOptionParser 添加到您的命名空间,但正如 John Fouhy 指出的那样,如果您要多次执行此操作,则可以将其隐藏在函数中。

回答by hasen

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.

Python 可能有更好的方法来解决您的问题。如果您可以提供有关您想要做的事情的更具体的细节,那将会有所帮助。

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 lambdafunctions (but they're restricted to a single expression).

例如,如果您需要更改在代码中特定点调用的方法,则可以通过将函数作为参数传递来实现(函数是 Python 中的第一类对象,您可以将它们传递给函数等)。您还可以创建匿名lambda函数(但它们仅限于单个表达式)。

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

另外,由于python非常动态,您可以在创建对象后更改对象的方法object.method1 = alternative_impl1,尽管它实际上有点复杂,请参阅gnud的答案

回答by rob

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.

在 python 中,你有匿名函数,使用 lambda 语句声明。我不太喜欢它们——它们不那么易读,而且功能有限。

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

但是,您所谈论的可能是在 python 中以完全不同的方法实现的:

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

def meth_b(obj):
  print "b"

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

回答by Maciej Piechotka

You can always hide class by variables:

您始终可以通过变量隐藏类:

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

instead of

代替

 var = new ...() {};

回答by grepit

This is what you would do in Python 3.7

这就是你在 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()

回答by g4borg

I do this in python3 usually with inner classes

我通常使用内部类在 python3 中执行此操作

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".

当我使用双下划线时,这将“重整”的想法与内部类混合在一起,从外部您仍然可以访问内部类SomeSerializer._SomeSerializer__Paginator和子类,但是 SomeSerializer.__Paginator 将不起作用,这可能是您的愿望,也可能不是您的愿望你希望它更“匿名”。

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.

就我而言,我只需要一个快速子类来设置一些类属性,然后将其分配给我的 RestSerializer 类的类属性,因此双下划线将表示“不再使用它”并且可能会更改为没有下划线,如果我开始在其他地方重用它。