javascript to python

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Fri Oct 3 14:38:11 EDT 2008


lkcl a écrit :
> On Oct 3, 10:29 am, Bruno Desthuilliers <bruno.
> 42.desthuilli... at websiteburo.invalid> wrote:
>> lkcl a écrit :> On Oct 2, 7:42 pm, Bruno Desthuilliers
>>> <bdesth.quelquech... at free.quelquepart.fr> wrote:
>>>> lkcl a écrit :
> 
>> And as far as I'm concerned, the point is
>> exactly here : it's doing "a little bit more" than the original code.
> 
>  yeah, i know.  and that "bit more" gets you a proper representation
> of the python "class" concept.

Except that in most cases - at least when it comes to browser 
scripting[1]  - this concept is just useless. IOW, that's quite a lot of 
code for something you just don't need.

[1] but ask yourself how many times you end up having only one single 
instance of a given class in a python utility script...

>  i was merely pointing out that if you want to _really_ translate the
> original code into python - _really_ strictly - it's not actually
> possible.

"really strictly", nope. But mainly because there's nothing in Python 
that behave like the 'this' javascript object (and it doesn't matter in 
the OP snippet). But you can have something quite close, using the class 
as an object (which it is anyway).

>  because python doesn't have the concept of non-prototyping
> (but... see below: i believe i may stand corrected on that)

!-)

>> Indeed. But the point is that Python - while close to a prototype-based
>> language in many aspects - is still class-based. The closer Python
>> translation of the OP's javascript snippet is probably the one I gave
>> using a 'class singleton' - that is, using the class itself as an
>> object.
> 
>  oh is _that_ how you do it.  thanks.  i always wondered how you did
> class singletons in python.

Note that this not really idiomatic Python - partly for cultural 
reasons, and mostly because use case and constraint differs (class 
singleton would surely become idiomatic if Python was used as 
browser-scripting language the way js is, because you then have to avoid 
any useless code to keep the site responsive).

Anyway, that's still IMHO the pythonic way to translate a litteral 
javascript object - I fail to see anything closer in Python (if there's 
some guru around ?)

>> python-source-to-javascript-source tool like pyjamas won't give you back
>> the original javascript snippet (which is by no mean a criticism of
>> pyjamas - it would just be way too complicated to automatize such a
>> translation).
> 
>  well... you _say_ that... but... actually, if that's the real way to
> represent class singletons, and it's an accurate representation of the
> OP's javascript, and a good example, then _yes_, pyjs should
> definitely have that added as a feature - to understand that a class
> singleton _can_ get mapped to the much more efficient javascript
> example you gave.

I'm afraid it's going to be quite complicated. You'd have to make sure 
the class only has classmethods - including inherited methods (and 
exception made of methods inherited from object). And FWIW, even such a 
class may be a base class for 'normal' python classes, so there's just 
no reliable semantic way to make sure the class is really a class 
singleton that should map to a litteral js object.

See, the problem here is that we have two high level, highly dynamic 
languages, that are quite close on quite a lot of things but are based 
on two really different object models. So quite often, the best 
translation is obvious for a programmer with a decent knowledge of both 
languages, but almost impossible for a program because there are way too 
much imply stuff (like, for the python class singleton, the fact that 
the class is not meant to be instanciated is totally implicit).

> not that many people would _want_ to do that,

Err... Do you have much experience in browser scripting ??? That's a 
*very* common js idiom.

> so it goes onto the
> "diminishing returns TODO list", but...
> 
>> Nope. You defined functions outside the object's scope, and you still
>> have to instanciate dataListener. Also, this above code just won't work
>> - unless you explicitely pass the dataListener instance to the
>> functions, ie:
>>
>> d = dataListener()
>> d.onDataAvailable(d, ...)
> 
>  yeah - i didn't realise what the python class singleton thing was.

In this case, the problem I pointed out was that Python's functions 
needs to be class instances to yield instancemethods when looked up on 
an instance or class. If you set a function as an instance attribute, 
the descriptor protocol is not invoked, and you just have a plain 
function (note that this is by design).

>> It seem you didn't read my other translation proprosal, so I repost it here:
> 
>> class dataListener(object):
>>     data = ''
> 
>  i did - i just didn't understand its significance.
> 
>  so - to get this straight: when you do class clsname(object), and you
> have the indentation and declaration of variables (e.g. data, above)
> at the same level as the functions, it means that there's only one of
> them? (i.e. a singleton)?

Nope. Whatever is declared within the class statement becomes a class 
attribute - that is, an attribute of the class object, shared by all 
instances. But that doesn't prevent you from instanciating the class and 
set an instance attribute by that name, in which case it will shadow the 
class attribute.

> so, if i do this:
> 
> d = dataListener()
> e = dataListener()
> 
> d.data = "fred"
> 
> print f.data
> 
> will return "fred"?
> 

Nope. The lookup rules for "reading" are:
- first check if the class (or it's bases, following mro) has a 
__getattribute__ method. If yes, call it, and stop here whatever the result.
- else check if there's a descriptor by that name in the class 
(including bases etc)
- if not, check if the instance has a non-descriptor attribute by that 
name in it's dict
- else check if the class (and it's bases etc) has a non-descriptor by 
that name
- else lookup if the class (etc...) have a callable __getattr__ 
attribute and if yes call it with the looked up name
- else (if nothing matched so far) raise an attribute error

When it comes to 'writing', it's much more simple:
- first check if the class (and it's bases...) have a __setattr__ 
method. If yes, call it with the name and value and stop here whatever 
happens.
- else check if the class (and it's bases etc...) have a descriptor by 
that name _with binding behaviour_ (IOW : with a __set__ method). If 
yes, call the descriptor's __set__ method with instance, name and value.
- else just set the instance's __dict__ with the name and value.

NB : I didn't mention slots, but they are rarely used. I leave it up to 
you to read the relevant doc for more detailed informations.

To make a long story short, in your above snippet, the d.data = "fred" 
statement ends up being a shortcut for d.__dict__['data'] = "fred". To 
have the class singleton working as an object, you must not instanciate 
it - just use the class object directly, ie:

class dataListener(object):
     data = ""

dataListener.data = "fred"
print dataListener.data

If you really want to prevent dataListener from being instanciated, 
you'd have to provide a __new__ method preventing instanciation, ie:

class dataListener(object):
     def __new__(cls):
         raise TypeError("class %s is a class singleton" % cls)

HTH



More information about the Python-list mailing list