Prototype Programming in Python

Javascript uses a prototype model for its objects. However, the language is very flexible and easy to write in a few lines, which replace a different view of the structure. For example, you can create a class function that emulates the behavior of a standard class, including inheritance or private members. Or you can use flexible functional tools by writing, for example, a curry function that takes a function and some of its arguments and returns a partially applied function.

I was wondering if it is possible to do the opposite and imitate the prototype method in more classical languages. In particular, I thought a bit about whether prototypes can be simulated in Python, but the lack of support for anonymous functions (more general than lambdas) leaves me stuck.

Can I write some functions to simulate propotypes in class-based languages, in particular in Python?

EDIT Let me give an example of how such a thing could be implemented (but I really am not able to do all this).

First, what closely resembles Javascript objects is the Python dictionary. So we could have simple objects like

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

Of course, we want to add a method, and that is not a problem if the method is placed in lambda

 foo = { 'bar': 1, 'foobar': 2, 'method': lambda x: x**2 } 

So now we can call the instance

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

Now , if , we had arbitrary functions like methods, which we could continue like this. First, we need functions inside foo to have access to foo itself; otherwise, these are ordinary functions, not methods.

I assume that this can be done by applying the makeObject function to foo , which goes through the values โ€‹โ€‹of foo and, when it finds the value to be called, changes its __call__ attribute to pass foo as its first argument.

At this stage, we would have independent objects that can be declared without the need to create classes.

Then we need to provide a prototype foo , which can be passed as the second argument to the makeObject function. The function should change foo.__getattr__ and foo.__setattr__ as follows: whenever an attribute is not found in foo , it should be searched in foo.prototype .

So, I think I can implement this, expect one thing: I cannot think of how to declare methods more complex than lambdas, except that they declared them in advance and bound them to my object. The problem is the lack of anonymous functions. I asked here because maybe some Python guru might have found some clever way around this.

+8
javascript python inheritance prototype prototypal-inheritance
source share
5 answers

This is much easier in Python than in JS. Your JS code can be replaced with Python:

 >>> class Foo(object): ... pass >>> foo = Foo() >>> foo.bar = 1 >>> foo.foobar = 2 

Then you can dynamically add methods

 >>> foo.method = lambda x: x**2 >>> foo.method(2) 4 

For methods more complex than lambdas, you declare them as functions, and they will have access to foo itself, no problem:

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

Or, if it is important:

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

Same.

So, as you can see, running your Python example is almost ridiculously simple. The question is why. :) I mean, that would be better:

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

Each time you read a property of a Python object, the __getattribute__ method is __getattribute__ , so you can overload it and fully control access to the attributes of the object. However, a slightly different function may be used for your task - __getattr__ . Unlike __getattribute__ , it is called only if the normal attribute search failed, i.e. At the same time, when the prototype starts in JavaScript. Here's the use:

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

Also pay attention to this question, as it contains notes about old and new style objects.

+4
source share

A short option, yes, but it's a little more complicated than JS .

From 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') 

Also check out What is a metaclass in Python .

Edit : check out the OO prototype , which is the closest you get, but it will always come down to using a lambda or just defining a function from the outside and adding a pointer to the class object.

+1
source share

I know this is pretty old, but I would add that my $ .02:

https://gist.github.com/4142456

The only problem here is to add methods. JavaScript has a much more elegant syntax with its functional literals, and it's really hard to beat. Lambda doesn't quite cut. So I decided to add an inconvenient method method to add methods.

Doctests are essential, and it all works.

EDIT:

Updated gist to no longer use the instance method . However, we still need to predefine the function.

In any case, the most important part of the prototype object model is implemented in this context. Other things are just syntactic sugar (it would be nice to have them, but that does not mean that the prototype object model cannot be used).

+1
source share

This implementation contains one important improvement over other similar implementations in other answers and on the Internet: the correct inheritance of methods from the prototype. If the value obtained from the prototype is a bound instance method - and to cover strange corner cases the method is also actually tied to this prototype - then the function underlying the method is retrieved, and the binding of the new method that functions to the calling object is returned

 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) 

This should fully implement prototype inheritance, as I understand it. One limitation is that classes that inherit from Proto must have Proto first in their MRO, because __new__ and __init__ have a prototype as the first parameter that they discard when delegated to super . Here is a usage example:

 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 bx print b.getY() # this will not work in most implementations d = D(a) # a is the proto for d print dx print d.getY() print dz 

Here is the gist

+1
source share

Source: https://habr.com/ru/post/650814/


All Articles