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