Python中的原型编程

2024-09-25 06:24:09 发布

您现在位置:Python中文网/ 问答频道 /正文

Javascript对其对象使用基于原型的模型。然而,这种语言是非常灵活的,而且很容易用几行代码编写函数来代替其他类型的构造。例如,可以创建一个class函数,模拟标准的类行为,包括继承或私有成员。或者,可以通过编写一个curry函数来实现函数工具的功能,该函数将接受一个函数及其一些参数并返回部分应用的函数。在

我想知道是否可以做相反的事情,用更经典的语言来模仿原型方法。特别是,我一直在考虑是否可以用Python来模拟原型,但是由于缺少对匿名函数(比lambdas更通用)的支持,我陷入了困境。在

Is it possible to write some functions to mimic propotypes in class-based languages, in particular in Python?

编辑让我举一些例子来说明一个人如何去实现这样的事情(但我并不是真的能做到所有)。在

首先,最像Javascript对象的是Python字典。所以我们可以有简单的物体,比如

foo = {
    'bar': 1,
    'foobar': 2
}

当然,我们想添加方法,只要方法适合lambda,这不是问题

^{pr2}$

所以现在我们可以打个比方

foo['method'](2)
>>> 4

现在如果我们有任意函数作为方法,我们可以这样继续下去。首先,我们需要foo中的函数来访问foo本身;否则它们只是普通函数,而不是方法。在

我想可以通过将makeObject函数应用于foo来实现这一点,该函数循环遍历foo值,并且,只要找到可调用的值,就会修改其__call__属性,将foo作为第一个参数传递。在

在这个阶段,我们将拥有独立的对象,无需创建类就可以声明这些对象。在

然后我们需要能够给foo一个原型,它可以作为makeObject函数的第二个参数传递。该函数应该修改foo.__getattr__foo.__setattr__,如下所示:只要在foo中找不到属性,就应该在^{中搜索它。在

我想,除了事先声明的方法外,我不能期望任何方法都更复杂。问题是缺少匿名函数。我之所以问这个问题,是因为也许有些Python大师可以找到一些巧妙的方法来避开这个问题。在


Tags: to对象方法函数in模型语言声明
3条回答

在Python中比在JS中容易得多。在Python中,您的JS代码可以替换为:

>>> class Foo(object):
...      pass

>>> foo = Foo()
>>> foo.bar = 1
>>> foo.foobar = 2

然后还可以动态地添加方法

^{pr2}$

对于比lambdas更复杂的方法,可以将它们声明为函数,并且它们可以访问foo本身,没有问题:

>>> def mymethod(self, bar, foobar):
...     self.bar = bar
...     self.foobar = foobar
>>> foo.mymethod = mymethod
>>> foo.mymethod(1,2)
>>> foo.bar
1
>>> foo.foobar
2

或者就这件事而言:

>>> mymethod(foo, 3, 4)
>>> foo.bar
3
>>> foo.foobar
4

同样的事情。在

因此,正如您所看到的,用Python执行您的示例几乎非常简单。问题是为什么。:)我是说,这样会更好:

>>> class Foo(object):
...     def __init__(self, bar, foobar):
...         self.bar = bar
...         self.foobar = foobar
...     def method(self, x):
...         return x**2

简短的版本,是的,但是它比JS复杂一点。在

来自Metaclass programming in Python

>>> class ChattyType(type):
...     def __new__(cls, name, bases, dct):
...         print "Allocating memory for class", name
...         return type.__new__(cls, name, bases, dct)
...     def __init__(cls, name, bases, dct):
...         print "Init'ing (configuring) class", name
...         super(ChattyType, cls).__init__(name, bases, dct)
...
>>> X = ChattyType('X',(),{'foo':lambda self:'foo'})
Allocating memory for class X
Init'ing (configuring) class X
>>> X, X().foo()
(<class '__main__.X'>, 'foo')

同时检查What is a metaclass in Python。在

编辑:勾选Prototype based OO,这是最接近的方法,但它总是可以归结为要么使用lambda,要么只是在外部定义函数并将指向它的指针添加到类对象。在

每次读取Python对象的某些属性时,都会调用方法__getattribute__,这样就可以重载它并完全控制对对象属性的访问。不过,对于您的任务,可以使用一个稍微不同的函数__getattr__。与__getattribute__相反,如果对属性的正常查找失败,即在JavaScript中的原型查找开始时,它才被称为。用法如下:

...
def __getattr__(self, name):
    if hasattr(prototype, name)
        return getattr(prototype, name)
    else: 
        raise AttributeError

还要注意this问题,因为它对新旧样式的对象有一些注释。在

相关问题 更多 >