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