0

我在 python 中有一个程序,其中包含一个将函数作为__init__方法参数的类。此函数存储为属性,并在类中的各个位置使用。传入的函数可以是多种多样的,传入一个键然后从一组预定义的函数中进行选择不会提供相同程度的灵活性。

现在,如果像这样的一长串问题不酷,我们深表歉意,但是......

  • 他们是在函数不是一流对象的语言中实现这一目标的标准方法吗?
  • 在这方面,块(如 smalltalk 或 Objective-C 中的块)是否算作函数?
  • 在这些语言中,块会是最好的方法吗?
  • 如果没有块怎么办?
  • 你能在运行时添加一个新方法吗?
  • 这在哪些语言中是可能的(并且容易)?
  • 或者使用执行所需操作的单个方法创建一个对象会更好吗?
  • 如果我想传递很多函数,我会创建很多单例对象吗?
  • 这会被认为是一种更面向对象的方法吗?
  • 有人会考虑在 python 中这样做吗,其中函数是一流的对象?
4

4 回答 4

1

我只是回答你的一些问题。

正如他们在 Scheme 社区中所说,“对象是穷人的闭包”(闭包是一等函数)。块通常只是闭包的语法糖。对于没有闭包的语言,存在各种解决方案。

一种常见的解决方案是使用运算符重载:C++ 有一个函数对象的概念,它定义了一个成员operator()(“运算符函数调用”)。Python 具有类似的重载机制,您可以在其中定义__call__

class Greeter(object):
    def __init__(self, who):
         self.who = who

    def __call__(self):
         print("Hello, %s!" % who)

hello = Greeter("world")
hello()

是的,您可以考虑在 Python 中使用 this 而不是将函数存储在对象中,因为函数不能被pickle

在没有运算符重载的语言中,你会看到像 Guava 的Function界面这样的东西。

于 2011-11-03T12:30:39.577 回答
1

您可以使用策略模式。基本上,您传入一个具有已知接口但行为不同的对象。这就像传递函数,但它被包裹在一个对象中。

于 2011-11-03T12:48:18.247 回答
1

我不明白您所说的“等效......使用面向对象的方法”是什么意思。在 Python 中,由于函数(如您所说)是一等对象,那么将函数作为参数传递是不是“面向对象”的呢?

在函数不是一流对象的语言中实现这一目标的标准方法?

我会说,只有在有一种标准的函数方式不能成为一流对象的情况下。

在 C++ 中,通常会创建另一个类,通常称为functorfunctionoid,它定义了 的重载operator(),允许在语法上像函数一样使用实例。但是,通常也可以使用普通的旧函数指针。指针和指向的函数都不是一流的对象,但接口足够丰富。

这与通过模板实现的“临时多态性”非常吻合;您可以编写实际上并不关心您是否传递类的实例或函数指针的函数。

callable同样,在 Python 中,您可以通过为类定义__call__方法来使对象注册为。

在这方面,块(如 smalltalk 或 Objective-C 中的块)是否算作函数?

我会说他们有。至少与 Python 中的函数一样多,而且实际上更多,因为它们并没有像 Python 的 lambda 那样被削弱。

在这些语言中,块会是最好的方法吗?

这取决于你需要什么。

你能在运行时添加一个新方法吗?这在哪些语言中是可能的(并且容易)?

对自己的编译器提供自省和运行时访问的语言。Python 符合条件。

然而,到目前为止,这个问题并没有表明需要跳过这些障碍。当然,对于新课程,某些语言比其他语言需要更多的样板。

或者使用执行所需操作的单个方法创建一个对象会更好吗?

这是相当标准的。

如果我想传递很多函数,我会创建很多单例对象吗?

你这么说好像你可能会不小心创建多个类的实例,如果你不写大量的样板来阻止自己这样做。

这会被认为是一种更面向对象的方法吗?

同样,我无法理解您对“面向对象”一词的理解。这并不意味着“创建很多对象”。

有人会考虑在 python 中这样做吗,其中函数是一流的对象?

并非不需要类可以做而函数不能做的额外事情。用鸭子打字,你到底为什么要打扰?

于 2011-11-03T13:20:41.820 回答
0

在 Smalltalk 中,您主要使用块。您还可以在运行时创建类和实例。

于 2011-11-07T22:58:41.053 回答