Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jun 2nd, 2006, 9:27 PM   #1
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,013
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
More Abstract Use Of Class Methods

I'm trying to achieve a simple solution to requiring to pack a value alongside an integer, so it can be easily remembered at a later time.

class keep_index:
    def __init__(self, value, index):
        self.value = str(value)
        self.index = index
        
    def __call__(self):
        return self.index
    
    def __str__(self):
        return self.value

x = keep_index(4, 1)
print x
print x()

As you can see, this works. Printing x, prints out 4. But calling it returns a value I added alongside it. However, it is a string in my example, not an integer. I have tried __int__ instead of __str__ of course. That was my first attempt, but that doesn't work.

Since I got this far by trial and error by dir()'ing some of the classes like "int" and "str", I may be missing something blatantly obvious. Sorry to be a pain.

Another problem, is if I put 'x' inside a list, and print the list, it displays the function address rather then the value of ".value". And I'd rather not change the concept behind how this is working. I believe that packing an "invisible" value alongside the original would work beautifully.
Sane is offline   Reply With Quote
Old Jun 2nd, 2006, 10:24 PM   #2
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,013
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Some progress has been made. Changing __str__ to __repr__ allowed it to appear properly inside lists. However, it's still a string and not an integer (best case scenario might even be boolean).
Sane is offline   Reply With Quote
Old Jun 3rd, 2006, 6:06 AM   #3
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
This seems an odd request - would it not be more readable to refer to the index by obj.index instead of obj()?

Regardless, if I'm understanding you right, you can get the functionality you want by subclassing the int type:
class keep_index(int):
    def __new__(cls, value, index):
        obj = int.__new__(cls, value)
        obj.index = index
        return obj
    def __call__(self):
        return self.index
The int type appears to use __new__ for setup, rather than __init__, which is why I had to override __new__ in order to get it to accept two parameters.
Arevos is offline   Reply With Quote
Old Jun 3rd, 2006, 8:57 AM   #4
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,013
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
That's excellent. Thanks. So does that work by inheriting the class "int"? I've only worked with class inheritance for wxPython and it looks like fun. Do you have any quick programming challenges you can think of that involve making inherited classes?

Your solution also solved the problem that it wasn't evaluating boolean expressions properly. I had to add more methods like __gt__, __ge__, to get it to work properly before.
Sane is offline   Reply With Quote
Old Jun 3rd, 2006, 10:20 AM   #5
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Sane
That's excellent. Thanks. So does that work by inheriting the class "int"?
Yep. You're essentially extending integer class by adding some extra functionality onto it.

Quote:
Originally Posted by Sane
I've only worked with class inheritance for wxPython and it looks like fun. Do you have any quick programming challenges you can think of that involve making inherited classes?
How about: create a new list object such that len, map and filter are methods of the class. e.g.
mylist = advanced_list(1, 2, 3, 4, 5)
print mylist.len()
print mylist.filter(lambda x : (x % 2) == 0)
print mylist.map(lambda x: x * 2)
Metaclasses, types, and the __new__ method are also some interesting topics to study. For instance, did you know that the type method can also be used to construct new classes dynamically?
Arevos is offline   Reply With Quote
Old Jun 3rd, 2006, 10:39 AM   #6
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,013
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Thanks a bunch.

class advanced_list(list):
    def __init__(cls, *args):
        setattr(cls, 'len', cls._len)
        setattr(cls, 'filter', cls._filter)
        setattr(cls, 'map', cls._map)
        
        obj = list.__init__(cls, list(args))
        return obj
    
    def _len(self):
        return len(self)

    def _filter(self, func):
        return filter(func, self)

    def _map(self, func):
        return map(func, self)


mylist = advanced_list(1, 2, 3, 4, 5)
print mylist.len()
print mylist.filter(lambda x : (x % 2) == 0)
print mylist.map(lambda x: x * 2)
Sane is offline   Reply With Quote
Old Jun 3rd, 2006, 11:02 AM   #7
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Pretty good - Although you don't have to do the "return obj" stuff. That's only for __new__, not __init__. The difference between __new__ and __init__ is subtle, but worth knowing.

Take the following object creation code (note that Foobar has to be a new-style class) :
obj = Foobar(1, 2)
The above code is equivalent to:
obj = Foobar.__new__(Foobar, 1, 2)
obj.__init__(1, 2)
In Python, the __new__ method is the constructor. It returns a new object. Interestingly, there's no limit to what object is returned; you could return anything, though typically __new__ returns a new instance of the class. The first argument of __new__ is not "self" (ie. a reference to the object), but "cls" (ie. a reference to the calling class).

The __init__ method is the initialiser. It is called after the object is constructed, and is used to give the object its initial data. The __init__ method's return value is ignored.

Returning back to your code, it can be simplified somewhat:
class advanced_list(list):
	def __init__(self, *args):
		list.__init__(self, args)

	def len(self):
		return len(self)

	def filter(self, func):
		return filter(func, self)

	def map(self, func):
		return map(func, self)
Arevos is offline   Reply With Quote
Old Jun 3rd, 2006, 11:05 AM   #8
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,013
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
I did the setattr because it's a bad habit to use function names that are reserved.
Sane is offline   Reply With Quote
Old Jun 3rd, 2006, 11:11 AM   #9
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Sane
I did the setattr because it's a bad habit to use function names that are reserved.
Doesn't that only apply to functions outside of an object?
Arevos is offline   Reply With Quote
Old Jun 3rd, 2006, 11:14 AM   #10
Cerulean
Professional Programmer
 
Cerulean's Avatar
 
Join Date: Apr 2005
Location: London, England
Posts: 459
Rep Power: 4 Cerulean is on a distinguished road
Quote:
I did the setattr because it's a bad habit to use function names that are reserved.
Where did you get that from? You're still using function names that are reserved, just going about it indirectly using setattr. Of course it's fine to use names from functions that are built in (otherwise there wouldn't be 'read' methods on all the nice file-like objects).
Cerulean is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 7:33 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC