Javascript Python中的原型编程

Javascript Python中的原型编程,javascript,python,inheritance,prototype,prototypal-inheritance,Javascript,Python,Inheritance,Prototype,Prototypal Inheritance,Javascript对其对象使用基于原型的模型。尽管如此,该语言非常灵活,并且很容易用几行代码编写函数,以取代其他类型的结构。例如,可以创建一个类函数,模拟标准类行为,包括继承或私有成员。或者可以通过编写一个curry函数来模拟函数工具,该函数将接受一个函数及其一些参数,并返回部分应用的函数 我想知道是否有可能在更为经典的语言中进行反转和模仿原型方法。特别是,我一直在思考是否可以用Python模拟原型,但是缺少对匿名函数的支持(比lambdas更通用)让我陷入困境 是否可以编写一些函数来模拟基于

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

我想知道是否有可能在更为经典的语言中进行反转和模仿原型方法。特别是,我一直在思考是否可以用Python模拟原型,但是缺少对匿名函数的支持(比lambdas更通用)让我陷入困境

是否可以编写一些函数来模拟基于类的语言(特别是Python语言)中的固有类型

编辑让我举一些例子,说明如何实现这样一个目标(但我并不是真的能够做到这一切)

首先,与Javascript对象最相似的是Python字典。所以我们可以有简单的对象,比如

foo = {
    'bar': 1,
    'foobar': 2
}
当然,我们想要添加方法,只要该方法适合lambda,这就不是问题

foo = {
    'bar': 1,
    'foobar': 2,
    'method': lambda x: x**2
}
现在我们可以打个比方

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

我想可以通过对
foo
应用
makeObject
函数来实现这一点,该函数循环遍历
foo
值,并在找到可调用的值时,修改其
\u call\u
属性,将
foo
作为其第一个参数传递

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

然后我们需要能够给
foo
一个原型,它可以作为
makeObject
函数的第二个参数传递。函数应该修改
foo.\uuu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.\uuuuuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


所以,我想我能够实现这个,除了一件事:我想不出任何方法来声明比lambdas更复杂的方法,除非事先声明它们并将它们附加到我的对象。问题在于缺少匿名函数。我在这里问这个问题是因为也许一些Python大师可以找到一些巧妙的方法来规避这个问题。

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

发件人:

类ChattyType(类型): ... 定义新定义(cls、名称、基础、dct): ... 打印“为类分配内存”,名称 ... 返回类型。\uuuuu新\uuuuuuu(cls、名称、基数、dct) ... 定义初始值(cls、名称、基数、dct): ... 打印“初始化(配置)类”,名称 ... super(chattype,cls)。\uuuuu init\uuuuuuu(名称、基、dct) ... >>>X=ChattyType('X',(),{'foo':lambda self:'foo'}) 为类X分配内存 初始化(配置)类X >>>X,X().foo() (,“foo”)
也检查一下


编辑:检查,这是最接近的结果,但它总是归结为要么使用lambda,要么只是在外部定义函数并向类对象添加指向该函数的指针。

每次读取Python对象的某些属性时,都会调用方法
\uuuu getattribute\uuuuuu
,所以您可以重载它并完全控制对对象属性的访问。然而,对于您的任务,可能会使用稍微不同的函数--
\uuuuu getattr\uuuu
。与
\uuuu getattribute\uuuu
相反,只有在属性的正常查找失败时(即在JavaScript中启动原型查找的同时)才会调用它。以下是用法:

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

还要注意这个问题,因为它有一些关于旧样式和新样式对象的注释。

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

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

>>> foo = Foo()
>>> foo.bar = 1
>>> foo.foobar = 2
然后还可以动态添加方法

>>> foo.method = lambda x: x**2
>>> foo.method(2)
4
对于比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

我知道这很旧,但我想我应该加上我的.02美元:

这里唯一的问题是添加方法。JavaScript的语法和函数文字要优雅得多,这是很难克服的。Lambda不太喜欢。所以我的解决方案是添加一个笨拙的
方法
方法来添加方法

要点中包括了博士学位,而且一切都有效

编辑:

更新了gist,不再使用
方法
实例方法。但是,我们仍然需要事先定义函数


无论如何,原型对象模型最重要的部分就是在这个要点中实现的。其他东西只是语法糖(拥有它们很好,但这并不意味着不能使用原型对象模型)。

与其他答案和互联网上的其他类似实现相比,此实现包含一个重要的增强:从原型正确继承方法。如果从原型中获得的值是绑定实例方法(为了涵盖奇怪的情况,该方法实际上也绑定到该原型),则提取该方法的底层函数,并返回一个将该函数绑定到调用对象的新方法

import types
import inspect

class Proto(object):
  def __new__(self, proto, *args, **kw):
    return super(Proto, self).__new__(self, *args, **kw)
  def __init__(self, proto, *args, **kw):
    self.proto = proto
    super(Proto, self).__init__(*args, **kw)
  def __getattr__(self, name):
    try:
      attr = getattr(self.proto, name)
      # key trick: rebind methods from the prototype to the current object
      if (inspect.ismethod(attr) and attr.__self__ is self.proto):
        attr = types.MethodType(attr.__func__, self)
      return attr
    except AttributeError:
      return super(Proto, self).__getattr__(name)
据我所知,这应该完全实现原型继承。 一个限制我
import types
import inspect

class Proto(object):
  def __new__(self, proto, *args, **kw):
    return super(Proto, self).__new__(self, *args, **kw)
  def __init__(self, proto, *args, **kw):
    self.proto = proto
    super(Proto, self).__init__(*args, **kw)
  def __getattr__(self, name):
    try:
      attr = getattr(self.proto, name)
      # key trick: rebind methods from the prototype to the current object
      if (inspect.ismethod(attr) and attr.__self__ is self.proto):
        attr = types.MethodType(attr.__func__, self)
      return attr
    except AttributeError:
      return super(Proto, self).__getattr__(name)
from prototypal import Proto

class A(Proto):
  x = "This is X"
  def getY(self):
    return self._y

class B(Proto):
  _y = "This is Y"

class C(object):
  def __getattr__(self, name):
    return "So you want "+name

class D(B,C):
  pass

a = A(None) # a has no proto
b = B(a) # a is the proto for b
print b.x
print b.getY() # this will not work in most implementations

d = D(a) # a is the proto for d
print d.x
print d.getY()
print d.z