470,849 Members | 686 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,849 developers. It's quick & easy.

pondering about the essence of types in python

let's start with a question:

==========
class z(object): .... def __init__(self):
.... self.blah=5
.... class x(object): .... def __init__(self):
.... z.__init__(self)
.... y=x() Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __init__
TypeError: unbound method __init__() must be called with z instance as
first argument (got x instance instead)
==========

and the question is -- WHY?

what is a type? generally speaking, if everything were an object, the
type only defines the MRO (method resolution order) for that object.
x.y first looks at the instance, then the class, then the parent
classes, etc. (this was changed a little in python2.3 to something more
complicated, but it's basically the same).

you can see the mro like this:
========== class x(object): pass
class y(x): pass
class z(y): pass
a=z()
print a.__class__.mro()

[<class '__main__.z'>, <class '__main__.y'>, <class '__main__.x'>,
<type 'object'>]
==========

after all, if we stay out of builtin types, all python objects are
dicts, which support chian-lookup according to the mro. and a method is
just a function that takes the instance as a first argument. so why is
all this type hassle necessary?

if we've taken it that far already, then let's really go over the edge.
I WANT TO DERIVE FROM INSTANCES. not only types.

why? i'm the developer of rpyc (http://rpyc.sf.net), and i got a
request from someone to add support for deriving from remote types. the
concrete example he gave was quite silly, but after i thought about it
a little, i said why not try?

a little intro about rpyc: it gives you proxies (instances) to remote
objects, which can be instances, functions, or classes. and that user
wanted to do something like this:

class my_frame(conn.modules.wx.Frame):
...

so the client was actually creates the graphics on the server. not very
usable, but why not? all it means is, when he does "my_frame.xyz",
python should add the remote type to the mro chain. not too bizar.

but __mro__ is a readonly attribute, and deriving from instances is
impossible (conn.modules.wx.Frame is a PROXY to the class)...

and again -- WHY? these all look like INTENTIONAL limitations. someone
went around and added type checks (which are NOT pythonic) into the
cPython implementation. argh. why do that?

so i thought -- let's be nasty. i created a function that creates a
class that wraps an instance. very ugly. small children and peope with
heart problems should close their eyes.

============
def derive_from(obj):
class cls(object):
def __getattr(self, name):
return getattr(obj, name)
return cls

class my_frame(derive_from(conn.modules.wx.Frame)):
....
============

the actual implementation is quite more complex, but that shows the
concept.
so now i'm experimenting with that little shit. but then i came to the
problem that methods check the type of the first argument... ARGH. dont
check types. DONT. the whole point of duck-typing is you DONT CHECK THE
TYPES. you just work with objects, and instead of TypeError you'd get
AttribiuteError, which is much better. AAARRRRRRGGGHH.

python is EVIL at the low level. the high-level is just fine, but when
you try to go under the hood... you better go with an exorcist.

-tomer

Mar 25 '06 #1
6 1382
gangesmaster wrote:
let's start with a question:

==========
class z(object):
... def __init__(self):
... self.blah=5
...
class x(object):
... def __init__(self):
... z.__init__(self)
...
y=x()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __init__
TypeError: unbound method __init__() must be called with z instance as
first argument (got x instance instead)
==========

and the question is -- WHY?

what is a type? generally speaking, if everything were an object, the
type only defines the MRO (method resolution order) for that object.
x.y first looks at the instance, then the class, then the parent
classes, etc. (this was changed a little in python2.3 to something more
complicated, but it's basically the same).

you can see the mro like this:
==========
class x(object): pass
class y(x): pass
class z(y): pass
a=z()
print a.__class__.mro()


[<class '__main__.z'>, <class '__main__.y'>, <class '__main__.x'>,
<type 'object'>]
==========

after all, if we stay out of builtin types, all python objects are
dicts, which support chian-lookup according to the mro. and a method is
just a function that takes the instance as a first argument. so why is
all this type hassle necessary?

if we've taken it that far already, then let's really go over the edge.
I WANT TO DERIVE FROM INSTANCES. not only types.

why? i'm the developer of rpyc (http://rpyc.sf.net), and i got a
request from someone to add support for deriving from remote types. the
concrete example he gave was quite silly, but after i thought about it
a little, i said why not try?

a little intro about rpyc: it gives you proxies (instances) to remote
objects, which can be instances, functions, or classes. and that user
wanted to do something like this:

class my_frame(conn.modules.wx.Frame):
...

so the client was actually creates the graphics on the server. not very
usable, but why not? all it means is, when he does "my_frame.xyz",
python should add the remote type to the mro chain. not too bizar.

but __mro__ is a readonly attribute, and deriving from instances is
impossible (conn.modules.wx.Frame is a PROXY to the class)...

and again -- WHY? these all look like INTENTIONAL limitations. someone
went around and added type checks (which are NOT pythonic) into the
cPython implementation. argh. why do that?

so i thought -- let's be nasty. i created a function that creates a
class that wraps an instance. very ugly. small children and peope with
heart problems should close their eyes.

============
def derive_from(obj):
class cls(object):
def __getattr(self, name):
return getattr(obj, name)
return cls

class my_frame(derive_from(conn.modules.wx.Frame)):
....
============

the actual implementation is quite more complex, but that shows the
concept.
so now i'm experimenting with that little shit. but then i came to the
problem that methods check the type of the first argument... ARGH. dont
check types. DONT. the whole point of duck-typing is you DONT CHECK THE
TYPES. you just work with objects, and instead of TypeError you'd get
AttribiuteError, which is much better. AAARRRRRRGGGHH.

python is EVIL at the low level. the high-level is just fine, but when
you try to go under the hood... you better go with an exorcist.

Take a look at languages like Self. Self was actually the first
prototype-based OO language. You could consider Javascript to be a
prototype-based language as well.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd www.holdenweb.com
Love me, love my blog holdenweb.blogspot.com

Mar 25 '06 #2
i was taking about python...

Mar 26 '06 #3
gangesmaster wrote:
but __mro__ is a readonly attribute, and deriving from instances is
impossible (conn.modules.wx.Frame is a PROXY to the class)...


Maybe I'm misunderstanding, but why is an instance a proxy to a class?
Why don't you make a class a proxy to the class?

STeVe
Mar 26 '06 #4
i dont think it's possible, to create proxy classes, but even if i did,
calling remote methods with a `self` that is not an instance of the
remote class would blow up.
-tomer

Mar 26 '06 #5
gangesmaster on comp.lang.python said:
TypeError: unbound method __init__() must be called with z instance as
first argument (got x instance instead)
==========

and the question is -- WHY?
I think the answer would be: because it's an instance method. Its
'contract' it's to be bound to an object of a certain class. Would you like
a different behaviour, you could decorate whatever method you need. I.e.,
turn your example into:

class z(object):
@staticmethod
def __init__(self):
self.blah=5

class x(object):
def __init__(self):
z.__init__(self)
y = x()
And this will work as you wish. You could have used classmethod as well
with a properly tuned init, of course.
but __mro__ is a readonly attribute, and deriving from instances is
impossible (conn.modules.wx.Frame is a PROXY to the class)... and again -- WHY? these all look like INTENTIONAL limitations. someone
went around and added type checks (which are NOT pythonic) into the
cPython implementation. argh. why do that?
I really think this happens because Python was designed to be
casualerror-safe. This approach would probably lead to many programming
errors.

By the way, Python was designed to *discourage* such behaviours, not to
prevent them. By the way, I didn't grasp what you would really like to do.
You're saying you want to derive from instances, but then I see in your
sample code you're creating a *class* derived from an object (I would
expect you would like to derive an instance from an instance, and to
'twist' such new instance methods to your needs, which I think can be done
as well). What's the difference between that and the use of __class__ ?

class z(object):
@staticmethod
def __init__(self):
self.blah=5

@staticmethod
def met_stat(self):
pass

@classmethod
def met_cls(self):
pass

def met_inst(self):
pass

class x(object):
def __init__(self):
z.__init__(self)
y = x()
class q(y.__class__):
pass
r = q()
This work OK to me. Unless you want to do something like making y instance
attributes become q class attributes, or you would like to set y instance
attributes on all q instances, which could require a bit more of code but
surely can be done. This would mix up a bit the class vs instance
behaviour, though, e.g. changing a derived class instance attribute which
is inherited from a parent instance would lead to a global attribute
change, or would 'spawn' a new instance attribute for that particular
instance?
def derive_from(obj):
class cls(object):
def __getattr(self, name):
return getattr(obj, name)
return cls
This seems to work for deriving read-only data from instances (no way to
write back data).
check types. DONT. the whole point of duck-typing is you DONT CHECK THE
TYPES. you just work with objects, and instead of TypeError you'd get
AttribiuteError, which is much better. AAARRRRRRGGGHH.


You don't HAVE TO check types if you don't want. Just use @staticmethod
everywhere in your classes. I mean, a METHOD is supposed to be
class-related, and it's often useful to have it as such, (unexpected errors
and behaviours might rise everywhere if not so), but you're never forced to
use that.
--
Alan Franzoni <al***************@gmail.com>
-
Togli .xyz dalla mia email per contattarmi.
Rremove .xyz from my address in order to contact me.
-
GPG Key Fingerprint:
5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
Mar 26 '06 #6
gangesmaster wrote:
i dont think it's possible, to create proxy classes, but even if i did,
calling remote methods with a `self` that is not an instance of the
remote class would blow up.


I don't understand you here. Why can't you just do something like:
class RemoteClass(object): .... def __init__(self, name):
.... self.name = name
.... def __repr__(self):
.... return '%s(name=%s)' % (type(self).__name__, self.name)
.... rc = RemoteClass('foo')
rc RemoteClass(name=foo) class ProxyClass(object): .... def __init__(self, name):
.... self.remote = RemoteClass(name)
.... def __repr__(self):
.... return repr(self.remote)
.... pc = ProxyClass('foo')
pc

RemoteClass(name=foo)

Note that when I call methods on the remote class, I don't pass them an
instance of the proxy class -- I pass them an instance of the
appropriate, RemoteClass type. Of course my code is simplified because
I'm not actually doing something remote, but assuming things get, say,
pickled and unpickled appropriately, I'm not sure I understand why the
above won't work.

Could you give some more details?

STeVe
Mar 26 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

17 posts views Thread by Gordon Airport | last post: by
8 posts views Thread by Jacek Generowicz | last post: by
24 posts views Thread by Matt Feinstein | last post: by
reply views Thread by Pete Shinners | last post: by
2 posts views Thread by j_mckitrick | last post: by
reply views Thread by Brett C. | last post: by
15 posts views Thread by pranab_bajpai | last post: by
7 posts views Thread by Maximus Decimus | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.