creating an object from base class
Steve Holden
steve at holdenweb.com
Sat Apr 28 11:35:44 EDT 2007
Ian Clark wrote:
> Quote iogilvy:
>> i wish to have some extended functionality added to sockets
>>
>> i can create my own socket class class mysocket(socket.socket):
>>
>> and all should be fine. Except, the sockets are created for me by the
>> accept method, listening on port. So how can i take the standard
>> socket created for me and create a 'mysocket'. I need a method that
>> will initialise any new properties i have added in my class, but how
>> can i change the class of the socket created?
>>
>
> Someone correct me if I'm wrong, but I don't believe it's possible to
> change the type of objects made from builtin classes. Though if it's a
> custom class you can, for example:
>
>>>> class Foo: pass
>>>> class Bar: pass
>>>> obj = Foo()
>>>> obj.__class__ = Bar
>
>
Yes, assuming you weren't asking a rhetorical question you will
eventually run up against
>>> class myClass1(object): pass
...
>>> class myClass2(object): pass
...
>>> mc1 = myClass1()
>>> type(mc1)
<class '__main__.myClass1'>
>>> mc1.__class__ = myClass2
>>> type(mc1)
<class '__main__.myClass2'>
>>> 2 . __class__ = myClass1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types
>>>
This doesn't qualify as error message of the year, but it clearly tells
you you aren't going to get around the prohibition. We also see
>>> o = object
>>> o.__class__ = myClass2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'object'
>>>
which gives a much better error message. Of course it'll probably only
take Alex Martelli a few minutes to find a workaround or counter-example.
> One option is to make your custom socket a wrapper around
> socket.socket and then pass through the calls you don't want to handle
> to socket.socket. The downside to this is there are quite a lot of
> methods that need to be accounted for. For example:
>
>>>> class CustomSocket:
>>>> def __init__(self, socket):
>>>> self.socket = socket
>>>> def connect(self, address):
>>>> self.socket.connect( address + '.some.tld' )
>>>> [etc]
>>>>
>>>> ...
>>>>
>>>> s = server_socket.accept()
>>>> s = CustomSocket(s)
>
This technique is formally called "delegation" if you want to Google it.
>
> Another approach you might want to look at is populating your object
> at runtime through a function. This won't give it the type you want,
> but it will give it any methods and attributes it would have gotten
> from your class with the added benefit of it still being of type
> socket.socket. Example:
>
>>>> def modify_socket( socket ):
>>>> socket.cabbages = 'Yuk'
>>>> socket.apples = 'Yum'
>>>>
>>>> def info():
>>>> print 'Cabbages? %s\nApples? %s' % (socket.cabbages, socket.apples)
>>>> obj.show_info = info
>>>>
>>>> ...
>>>>
>>>> s = server_socket.accept()
>>>> modify_socket( s )
>>>> s.show_info()
> Cabbages? Yuk
> Apples? Yum
>>>> s.apples = 'Yummie'
>>>> s.show_info()
> Cabbages? Yuk
> Apples? Yummie
>>>> type(s)
> <class 'socket._socketobject'>
>
Of course that approach sucks if sockets happen to have an organes or
apples attribute that's used in the inner workings of the class. This is
when the C++ devotees start screaming about protected and private
variables. Just ignore them :-)
[Note: these remarks are more for the OP than Ian]
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
------------------ Asciimercial ---------------------
Get Python in your .sig and on the web. Blog and lens
holdenweb.blogspot.com squidoo.com/pythonology
tag items: del.icio.us/steve.holden/python
All these services currently offer free registration!
-------------- Thank You for Reading ----------------
More information about the Python-list
mailing list