Re: [Tutor] Subclassing logging.Handler?
On Wed, Jul 6, 2016 at 1:01 PM, Alex Hallwrote: > Regarding this project: I've gone ahead and tried a variant of it. I > wanted to log to an HTML file, since those are much easier to look at with > a screen reader and so I could get used to the concepts involved. Here's > what I've come up with so far. I'll ask the question, then paste the code. > I'm getting an error on the self.stream.write line in _open that > "'ADTimedRotatingLogFileHandler' has no attribute stream". If I'm > subclassing TimedRotatingFileHandler, how can it not have stream? > Again, in case someone is searching for an answer later and finds this thread: you must assign it. def _open(self): self.stream = super(ADTimedRotatingLogFileHandler, self)._open() I'm now getting a different error, in close(): TypeError: must be type, not None I'm not sure what that's about, but at least I now know why I wasn't getting a stream. > > import logging > import logging.handlers as logHandlers > class ADTimedRotatingLogFileHandler(logHandlers.TimedRotatingFileHandler): > > def __init__(self, filename, when, interval, backupCount, title): > """Most parameters are for the superclass, but 'title' is the > title you want your HTML file to have.""" > super(ADTimedRotatingLogFileHandler, self).__init__(filename, > when, interval, backupCount) > self._title = title > > def _open(self): > super(ADTimedRotatingLogFileHandler, self)._open() > self.stream.write(""" > > %s > > > """ %(self._title)) > > def close(self): > self.stream.write(""" > > """) > super(ADTimedRotatingLogFileHandler, self).close() > > > On Wed, Jul 6, 2016 at 8:32 AM, Alex Hall wrote: > >> Hey list, >> Another day, another Python experiment. I'm wondering what methods I'd >> have to implement in a custom subclass of logger.Handler. >> >> Currently, the recurring jobs I have written log their events to a file >> each time they run. That's fine, but it doesn't let me keep >> easily-sorted/searched records. Even if I use a size-based log file >> handler, it'll get hard to search. I'm pondering logging to a database as >> well, so that the files will always have the most recent few runs, but the >> database will have everything. That means subclassing logger.Handler. >> >> I found the docs for this, but is emit() the only function I need to >> implement? There are things about i/o locks, formatting, and so on as well. >> How much do I need to do, and how much can I leave up to the super class? >> I'll have to call >> super(MyLogHandler, self).__init__() >> I know, but what else do I have to worry about? To be clear, I'm not >> asking about logging to a database, only what to do to make a Handler >> subclass capable of logging through whatever mechanisms I want. Thanks. >> >> -- >> Alex Hall >> Automatic Distributors, IT department >> ah...@autodist.com >> > > > > -- > Alex Hall > Automatic Distributors, IT department > ah...@autodist.com > -- Alex Hall Automatic Distributors, IT department ah...@autodist.com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing logging.Handler?
Regarding this project: I've gone ahead and tried a variant of it. I wanted to log to an HTML file, since those are much easier to look at with a screen reader and so I could get used to the concepts involved. Here's what I've come up with so far. I'll ask the question, then paste the code. I'm getting an error on the self.stream.write line in _open that "'ADTimedRotatingLogFileHandler' has no attribute stream". If I'm subclassing TimedRotatingFileHandler, how can it not have stream? import logging import logging.handlers as logHandlers class ADTimedRotatingLogFileHandler(logHandlers.TimedRotatingFileHandler): def __init__(self, filename, when, interval, backupCount, title): """Most parameters are for the superclass, but 'title' is the title you want your HTML file to have.""" super(ADTimedRotatingLogFileHandler, self).__init__(filename, when, interval, backupCount) self._title = title def _open(self): super(ADTimedRotatingLogFileHandler, self)._open() self.stream.write(""" %s """ %(self._title)) def close(self): self.stream.write(""" """) super(ADTimedRotatingLogFileHandler, self).close() On Wed, Jul 6, 2016 at 8:32 AM, Alex Hallwrote: > Hey list, > Another day, another Python experiment. I'm wondering what methods I'd > have to implement in a custom subclass of logger.Handler. > > Currently, the recurring jobs I have written log their events to a file > each time they run. That's fine, but it doesn't let me keep > easily-sorted/searched records. Even if I use a size-based log file > handler, it'll get hard to search. I'm pondering logging to a database as > well, so that the files will always have the most recent few runs, but the > database will have everything. That means subclassing logger.Handler. > > I found the docs for this, but is emit() the only function I need to > implement? There are things about i/o locks, formatting, and so on as well. > How much do I need to do, and how much can I leave up to the super class? > I'll have to call > super(MyLogHandler, self).__init__() > I know, but what else do I have to worry about? To be clear, I'm not > asking about logging to a database, only what to do to make a Handler > subclass capable of logging through whatever mechanisms I want. Thanks. > > -- > Alex Hall > Automatic Distributors, IT department > ah...@autodist.com > -- Alex Hall Automatic Distributors, IT department ah...@autodist.com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing Exceptions
On Friday 06 January 2012, Steven D'Aprano wrote: Chris Fuller wrote: class Foo(SyntaxError): ... def __init__(self, a,b,c): ... self.args = (a,b,c) ... raise Foo(1,2,3) Traceback (most recent call last): File stdin, line 1, in module __main__.Foo: None Inheriting from SyntaxError doesn't work! When I create a new exception, I generally subclass from the built-in exception it most resembles, in case there was some reason to also catch it via an ancestor. But I'm not sure if that is really all that useful an idea in practice. How do you folk do it? What do you mean, doesn't work? It looks like it works to me. You get a Foo exception, exactly as expected. The error message isn't what you expect, because you're making unwarranted assumptions about SyntaxError and how it works. In general, when you override a method, you take full responsibility to perform everything that the superclass method was supposed to do. In this case, you fail to assign to msg as well as args. It is safer to overload a message rather than override it: class Spam(SyntaxError): ... def __init__(self, *args): ... if args: ... args = (I pity the fool who made a mistake,) + args[1:] ... super(Spam, self).__init__(*args) ... raise Spam('you made a mistake', 1, 2) Traceback (most recent call last): File stdin, line 1, in module __main__.Spam: I pity the fool who made a mistake Unfortunately, there's no real consistency in what arguments exceptions are expected to take. The best thing is to read the docs, if they have any, or use introspection and trial and error to work out what they do. try: ... raise SyntaxError(you made a mistake) ... except SyntaxError, err: ... pass ... err.msg 'you made a mistake' See dir(err) for more; you can use help(SyntaxError) but unfortunately it isn't very useful. You probably shouldn't inherit from SyntaxError, since it represents syntax errors in the Python code being interpreted or compiled. Any syntax error in your own data structures should be independent of SyntaxError. In Python: Essential Reference, David Beazley recommends that the parameters of the exception be assigned to the args attribute, so it is passed all the way through the traceback. You will observe that the last element in the traceback loses this information when subclassed from SyntaxError. This isn't a problem when the whole traceback is laid out before you, but can come into play with automated tools that catch/log/manipulate exceptions. This behavior of exceptions isn't apparently mentioned in the canonical documentation, however. I had the same thought about not wanting to mix syntax errors in the data with syntax errors in the code, but that applies to any exception, really. In fact, it's better to inherit from a more derived class, because when you catch an ancestor, you'll be grabbing less greedily at the possible coding errors. Which suggests that giving a damn about built-in ancestors of user-defined exceptions is a losing proposition, now that I think about it. Cheers ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing Exceptions
On 01/07/2012 03:56 PM, Steven D'Aprano wrote: Chris Fuller wrote: You probably shouldn't inherit from SyntaxError, since it represents syntax errors in the Python code being interpreted or compiled. Any syntax error in your own data structures should be independent of SyntaxError. I'd say a syntactical error in your own data structure is a kind of ValueError. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing Exceptions
Inheriting from SyntaxError doesn't work! When I create a new exception, I generally subclass from the built-in exception it most resembles, in case there was some reason to also catch it via an ancestor. But I'm not sure if that is really all that useful an idea in practice. How do you folk do it? If somebody wanted to catch a ValueError, would they also mean to catch my error? (The same with SyntaxError and so on). Probably not. If they would, then I raise the relevant exception. It is very possible to accidentally catch the wrong thing if you put too much in a try block, and I don't like making that any easier. -- Devin On Fri, Jan 6, 2012 at 10:24 PM, Chris Fuller cfuller...@thinkingplanet.net wrote: I had an interesting experience today. Python 2.7.1 (r271:86832, Nov 28 2010, 19:31:37) [GCC 4.4.5] on linux2 Type help, copyright, credits or license for more information. class Foo(Exception): ... def __init__(self, a,b,c): ... self.args = (a,b,c) ... raise Foo(1,2,3) Traceback (most recent call last): File stdin, line 1, in module __main__.Foo: (1, 2, 3) class Foo(SyntaxError): ... def __init__(self, a,b,c): ... self.args = (a,b,c) ... raise Foo(1,2,3) Traceback (most recent call last): File stdin, line 1, in module __main__.Foo: None Inheriting from SyntaxError doesn't work! When I create a new exception, I generally subclass from the built-in exception it most resembles, in case there was some reason to also catch it via an ancestor. But I'm not sure if that is really all that useful an idea in practice. How do you folk do it? By the way, inheriting from StandardError, the direct ancestor of SyntaxError, works as expected, and its parent is Exception. Cheers ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing Exceptions
Chris Fuller wrote: class Foo(SyntaxError): ... def __init__(self, a,b,c): ... self.args = (a,b,c) ... raise Foo(1,2,3) Traceback (most recent call last): File stdin, line 1, in module __main__.Foo: None Inheriting from SyntaxError doesn't work! When I create a new exception, I generally subclass from the built-in exception it most resembles, in case there was some reason to also catch it via an ancestor. But I'm not sure if that is really all that useful an idea in practice. How do you folk do it? What do you mean, doesn't work? It looks like it works to me. You get a Foo exception, exactly as expected. The error message isn't what you expect, because you're making unwarranted assumptions about SyntaxError and how it works. In general, when you override a method, you take full responsibility to perform everything that the superclass method was supposed to do. In this case, you fail to assign to msg as well as args. It is safer to overload a message rather than override it: class Spam(SyntaxError): ... def __init__(self, *args): ... if args: ... args = (I pity the fool who made a mistake,) + args[1:] ... super(Spam, self).__init__(*args) ... raise Spam('you made a mistake', 1, 2) Traceback (most recent call last): File stdin, line 1, in module __main__.Spam: I pity the fool who made a mistake Unfortunately, there's no real consistency in what arguments exceptions are expected to take. The best thing is to read the docs, if they have any, or use introspection and trial and error to work out what they do. try: ... raise SyntaxError(you made a mistake) ... except SyntaxError, err: ... pass ... err.msg 'you made a mistake' See dir(err) for more; you can use help(SyntaxError) but unfortunately it isn't very useful. You probably shouldn't inherit from SyntaxError, since it represents syntax errors in the Python code being interpreted or compiled. Any syntax error in your own data structures should be independent of SyntaxError. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing Exceptions
Devin Jeanpierre wrote: Inheriting from SyntaxError doesn't work! When I create a new exception, I generally subclass from the built-in exception it most resembles, in case there was some reason to also catch it via an ancestor. But I'm not sure if that is really all that useful an idea in practice. How do you folk do it? If somebody wanted to catch a ValueError, would they also mean to catch my error? (The same with SyntaxError and so on). Probably not. If your error represents a value error, then yes they would. But in that case, why should I subclass ValueError instead of just using ValueError itself? Writing my own exceptions is only useful if I intend to give the caller the *choice* of either treating my exception the same or different from ValueError: that is, if my error is a more specific kind of ValueError. If it is not a specific kind of value error, then just use the generic built-in ValueError exception instead. try: x = some_function() except MyValueError: # treat my errors specially except ValueError: # any other kind of ValueError caught here vs. try: x = some_function() except ValueError: # any kind of ValueError caught here, including MyValueError The same goes for all exception types, although in practice I find that I generally only subclass ValueError. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing object
Timo Vanwynsberghe timo...@gmail.com wrote I read that it is advised to subclass object. Is it really necessary? I mean, everything works, why should I add it to my code? In older versions of Python it made a difference whether you used object or not. Using object gave you a new style class which has several extra features, without you got an old style class without the features. In Python v3 you only get new style classes and I think you can omit the object without detriment. For comparison here are Python v2.5 definitions class New(object): pass ... dir(New) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash_ _', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr_ _', '__setattr__', '__str__', '__weakref__'] class Old: pass ... dir(Old) ['__doc__', '__module__'] As you can see there is quite a lot of extra stuff in the New class. In Python 3: class New(object): pass dir(New) ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] class Old: pass dir(Old) ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] There is even more stuff but it is the same with/without the explicit 'object'. HTH, -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing object
On Sun, Jan 17, 2010 at 12:47 PM, Robert webtour...@gmail.com wrote: On Sun, Jan 17, 2010 at 11:25 AM, Alan Gauld alan.ga...@btinternet.com wrote: In older versions of Python it made a difference whether you used object or not. Using object gave you a new style class which has several extra features, without you got an old style class without the features. I have been wondering about this New-style Class subject along this line: so, *theoretically speaking*, in EXISTING, pre-P3K code, if one changes everywhere where it's coded class someClass() to class someClass(object), it should not break the programs, right ? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing object
Robert webtour...@gmail.com wrote I have been wondering about this New-style Class subject along this line: so, *theoretically speaking*, in EXISTING, pre-P3K code, if one changes everywhere where it's coded class someClass() to class someClass(object), it should not break the programs, right ? More correctly replacing old style class SomeClass: with new style class SomeClass(object): should not break anything. You cannot of course reliably go the other way! Alan G ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing list
Luis N wrote: I get an error TypeError: 'rounding' is an invalid keyword argument for this function on my list subclass. How might I subclass list without this error? This is the code: class SeriesList(list): def __new__(cls, *args, **kwargs): series_list = list.__new__(cls, *args) series_list.rounding = kwargs.get('rounding', None) return series_list def moving_average(self, function, period=10): index = 0 window = [] ma = [] for i in self.__iter__(): i = float(i) if is_not_nan(i): window.insert(0, i) if len(window) == period: ma.append(function(window)) window.pop() else: ma.append(float('nan')) return round(ma, self.rounding) --- I copied and ran the above. It gives me no errors. Of course all it is is a class definition. Is there more to the code? And please post the traceback so we have more information! -- Bob Gailer Chapel Hill NC 919-636-4239 ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing list
On Fri, Jun 19, 2009 at 12:56 AM, bob gailer bgai...@gmail.com wrote: Luis N wrote: I get an error TypeError: 'rounding' is an invalid keyword argument for this function on my list subclass. How might I subclass list without this error? This is the code: class SeriesList(list): def __new__(cls, *args, **kwargs): series_list = list.__new__(cls, *args) series_list.rounding = kwargs.get('rounding', None) return series_list def moving_average(self, function, period=10): index = 0 window = [] ma = [] for i in self.__iter__(): i = float(i) if is_not_nan(i): window.insert(0, i) if len(window) == period: ma.append(function(window)) window.pop() else: ma.append(float('nan')) return round(ma, self.rounding) --- I copied and ran the above. It gives me no errors. Of course all it is is a class definition. Is there more to the code? And please post the traceback so we have more information! -- Bob Gailer Chapel Hill NC 919-636-4239 This is the traceback. I want to let SeriesList know how to round moving average series derived from itself. In [121]: s = SeriesList(rounding=1) --- TypeError Traceback (most recent call last) /Users/Luis/Documents/Programming/speculation/ipython console in module() TypeError: 'rounding' is an invalid keyword argument for this function Thank you for your help, Luis ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing list
On Thu, Jun 18, 2009 at 9:48 PM, Luis Ngloboph...@gmail.com wrote: I get an error TypeError: 'rounding' is an invalid keyword argument for this function on my list subclass. How might I subclass list without this error? This is the code: class SeriesList(list): def __new__(cls, *args, **kwargs): series_list = list.__new__(cls, *args) series_list.rounding = kwargs.get('rounding', None) return series_list This is the traceback. I want to let SeriesList know how to round moving average series derived from itself. In [121]: s = SeriesList(rounding=1) --- TypeError Traceback (most recent call last) /Users/Luis/Documents/Programming/speculation/ipython console in module() TypeError: 'rounding' is an invalid keyword argument for this function I think you need to define SeriesList.__init__(self, rounding=None). This function should assign self.round, then __new__() can be just def __new__(cls, *args, **kwargs): series_list = list.__new__(cls, *args) return series_list Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing strings
Ahh. Excellent questions. I'm playing around with subclassing the built-in string type, and realizing there's quite a bit I don't know about what's going on with the built-in types. When I create a string like so: x = 'myvalue' my understanding is that this is equivalent to: x = str('myvalue') Um. Yeah. Sort of. Python creates the 'myvalue' as a string object as it interprets it. So str('myvalue') is just saying create a string object from a string object. But I think I know what you intended to ask, see below. and that this second form is more fundamental: the first is a shorthand for the second. What is 'str()' exactly? Is it a class name? str type 'str' [edit] Here's a good thought I just thought. These are equivalent a = hello str(a) == a.__str__() True repr(a) == a.__repr__() True str(a) == str.__str__(a) True repr(a) == str.__repr__(a) It's a built-in type. That is~ it has a constructor, destructor, methods, etc. like any other object in python. When you say str('myvalue') you are passing the python string object containing 'myvalue' into the constructor the str type and creating a new string object. If so, is the string value I pass in assigned to an attribute, the way I might create a self.value = statement in the __init__ function of a class I made myself? If so, does that interior attribute have a name? I've gone poking in the python lib, but haven't found anything enlightening. Here we come to secrets of Python. It's written in C. Since str is a built-in type, the storing of the variable you ask about is a C style buffer (*not* a linked list - strings are immutable). Whenever you call str(), Python constructs a new python object and stores the string in a new C-style buffer. The same occurs for adding string together with '+', and is why .join(list_of_strs) is the preferred method (Because python can build the buffer all in one go) No it's not accessible from python. (At least I don't think so. And you never should need to) I started out wanting to subclass str so I could add metadata to objects which would otherwise behave exactly like strings. Okay. But then I started wondering where the actual value of the string was stored, since I wasn't doing it myself, and whether I'd need to be careful of __repr__ and __str__ so as not to interfere with the basic string functioning of the object. Okay. As far as I can tell the object functions normally as a string without my doing anything – where does the string value 'go', and is there any way I might inadvertently step on it by overriding the wrong attribute or method? Okay. You can overwrite string methods like __str__ and __repr__. If you look it up, the definition of these special methods (in layman's terms) is that whenever str() is called on an object (explicitly or *implicitly*) then the objects __str__ method is called which will return a string object which should give an appropriate representation. The built-in string object does the equivalent of def __str__(self): return self def __repr__(self): return '%s' % self #Notice this will give extra single quotes around string No, you will not interfere with the internal representation of the string, but you can change completely how that representation is presented to the user of the object. For an implemented simple example just say the word. HTH, Tiger12506 PS. Anyone who's interested. A significant study of C has brought me to these conclusions. immutable - implemented with static buffer mutable - implemented with linked list Anyone know a little more detail? ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing strings
Eric Abrahamsen wrote: When I create a string like so: x = 'myvalue' my understanding is that this is equivalent to: x = str('myvalue') and that this second form is more fundamental: the first is a shorthand for the second. The second does nothing that the first doesn't already do. 'myvalue' is a string: In [4]: s='myvalue' In [5]: type(s) Out[5]: type 'str' So is str('myvalue'): In [6]: t=str(s) In [7]: type(t) Out[7]: type 'str' In fact they are the *same* string - str(s) is the same as s if s is already a string: In [8]: s is t Out[8]: True What is 'str()' exactly? Is it a class name? Close; str is a type name. str() is an invocation of the type. If so, is the string value I pass in assigned to an attribute, the way I might create a self.value = statement in the __init__ function of a class I made myself? If so, does that interior attribute have a name? I've gone poking in the python lib, but haven't found anything enlightening. No, not really. At the C level, IIUC there is a structure containing a pointer to a byte array, but there is no access to this level of internals from Python. For Python, strings are fundamental types like integers and floats. The internal representation is not available. I guess you may have a background in C++ where a char array is different from an instance of the string class. Python does not have this distinction; you don't have access to a bare char array that is not wrapped in some class. I started out wanting to subclass str so I could add metadata to objects which would otherwise behave exactly like strings. But then I started wondering where the actual value of the string was stored, since I wasn't doing it myself, and whether I'd need to be careful of __repr__ and __str__ so as not to interfere with the basic string functioning of the object. As far as I can tell the object functions normally as a string without my doing anything – where does the string value 'go', and is there any way I might inadvertently step on it by overriding the wrong attribute or method? No, you can't access the actual byte array from Python and you can't damage it. You might want to take a look at BeautifulSoup, which subclasses unicode to create a page element, and path.py which subclasses string to add file path manipulation operations. http://www.crummy.com/software/BeautifulSoup/ file://localhost/Users/kent/Desktop/Downloads/Python/path-2.1/index.html The actual string object implementation is in stringobject.h .c: http://svn.python.org/view/python/trunk/Include/stringobject.h?rev=59564view=markup http://svn.python.org/view/python/trunk/Objects/stringobject.c?rev=59564view=markup Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing strings
Tiger12506 wrote: PS. Anyone who's interested. A significant study of C has brought me to these conclusions. immutable - implemented with static buffer mutable - implemented with linked list Anyone know a little more detail? Certainly not true of Python. I don't know of any standard Python data structure that is implemented with a linked list. list is implemented as an array of references, not a linked list. dict and set are hash tables. User-defined classes are implemented however you like, with a dict to hold the attributes. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing strings
Thanks both of you, that cleared a lot of things up. On Jan 9, 2008, at 11:49 AM, Kent Johnson wrote: No, you can't access the actual byte array from Python and you can't damage it. I don't know a lick of C and probably never will, but I do like to know what it is, exactly, that I don't know, and this is nice. I'll stop worrying about stepping on the actual value of the strings. On Jan 9, 2008, at 11:48 AM, Tiger12506 wrote: def __str__(self): return self def __repr__(self): return '%s' % self #Notice this will give extra single quotes around string Excellent, this was very helpful. I know about the str() vs .__str__() equivalence, but had never seen what these two functions were actually doing under the hood. What I wasn't figuring out was passing the string value of my custom string class into the constructor of the actual str type, rather than rerouting it into a data attribute of my custom class. So now I've got this, for example: class StampedString(str): def __init__(self, val): super(StampedString, self).__init__(val) import datetime self.timestamp = datetime.datetime.now() so that this: x = StampedString('This is a time-stamped string') works exactly like a string, apart from the metadata. At least, I think I've understood this correctly... Thanks again for the interesting explanations. Eric ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing vs. stand alone functions
[EMAIL PROTECTED] wrote Just so you know, my day gig is maintaining a 30 year old COBOL app and writing custom RPGLE - http://en.wikipedia.org/wiki/RPGLE - on an IBM i5. So that's where I am coming from. Thats probably one of the hardest places to learn OOP from. COBOL, more than any other language I've used forces programmers to separate data and function explicitly. It then compounds matters by encouraging the use of global variables (within modules at least). Of course COBOL is peerless in tackling exactly those problems where OOP is weakest - large volume data translation. But its a big jump from thinking in COBOL to thinking in OOP. I had to make the transition in the opposite direction and it was challenging Of course there is COBOL WITH OBJECTS now but I've no idea how that works. And with rigid discipline you can build with very small modules comprising precisely one data structure and the functions that operate on that but its not conventional COBOL practice. So I sympathise, but urge you to hang in there the penny will start to drop, especially if you try to create some projects that suit OOP - like building a few GUIs or simulations. Regards, Alan G. (2 years with MicroFocus COBOL on OS/360 for Y2K ;-) ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing vs. stand alone functions
[EMAIL PROTECTED] wrote: Let's say you want to load a dictionary. Do I create a function that accepts some argument (say a file name) and returns a dictionary, or do I subclass dict and override the __init__ and __setitem__ functions to make 'self-loading' dictionary? It seems the end result is the same. I am not understanding, what you mean by loading a dictionary or a value in python. You mean creating a custom dictionary? Then, a) obj = Dict(list_of_tuples) b) obj = mydict{} c) def fun(): # process it and store in dict. return mydict These are are various ways. Now, the question is when do you subclass? Only when you want to extend the behaviour of particular class. For e.g, you want to extend the Exception class to define your own Exception, then you will subclass it. Class MyException(Exception): def __init__(self): pass def __str__(self): return My Exception, Hurray! The same, can applied to dictionary, say you want extend the behaviour of dictionary with a get a random key-value pair. Next is, what if you want different instances of a class. Well, those are the Objects. In the class you define a property which can be variable and set those property values when you create the objects from that Class. Do you subclass WebPage for each particular page you want (because you can customize it with load functions for each piece of data) or do you just use it as is, and create separate functions outside the class that load the data and Objects. (I can send code samples if it will help). Sure, please do. I might not check the email on sat/sun. But others here are ofcourse very helpful. I hope my explaination help u a bit. Thanks, -- Senthil Your own mileage may vary. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Subclassing vs. stand alone functions
[EMAIL PROTECTED] wrote I am new to Python and trying to get my head around the OO stuff. I guess my question is - when do you go with subclassing vs. making a standalone function? OK, I'll take a slightly different approach than the other answers so far. First: procedural and OO styles of programming are diffrent ways of thinking about a problem. Any programming problem can be solved using either approach and both approaches are equally good, neither is intrinsically better than the other. Second: Some problems are more amenable to an OO aproach than a procedural and vice versa. And the majority can be done either way with very little to choose between them. I will now assume that you understand the procedural way and already know how to apply good procedural design, including modularity featuring loose coupling and tight cohesion. In addition data structure design and its relationship to your procedural design should be a concept familiar to you. ( In a perfect world you'll also be familiar with the princuiples of functional programming and the lambda calculus, but that's possibly asking too much.) That leaves the question of why and wjen should we use OOP? OOP suits programs that feature a high level of correspondence between the real world and the software modfel we are building. For example simulation software (including many games) usually involves the representation and control of a number of objects. It is a natural link to model these objects as classes and create corresponding objects in our solution. Similarly GUIs are made up of windows, widgets, etc. Again these have a fairtly clear translation into objects. When we get into problems primarily of algorithms, or of transforms to fixed data then an OOP style is not always such an obvious fit. Similarly when modelling complex state machines the applicability of OOP can be less obvious and a traditional table driven procedural style may seem better suited. In those cases the decision to use OOP is likely to be driven by the desire to create a reusable component. Something that can be utilised across multiple projects. or it may be driven by the desire to abstract away a complex process or data structure. Hiding it behind a simplere API. This can be done using traditional approaches but usually only at the cost od writing an awful lot of code or by exposing the data structure at least for initialisation purposes. Now to your examples: Let's say you want to load a dictionary. Why would anyone ever want to load a dictionary? What is the higher level goal you are trying to achieve? Is the dictionary part of the solution or the problem? If it is part of the problem a dictionary object may be appropriate. If its part of the solution, and you are already using a non OOP approach why would you want an object? Unless its for the reasons above - reuse or abstraction that is hard using procedures. But you should very rarely be making decisions at this level unless you have alrwady decided on amn overall approach and you are considering an exception to the overall style. ie Should I create a function in an OOP design or should I create a class in a procedural design. (Mixing styles is OK but will normally involve some compromises) Do I create a function that accepts some argument or do I subclass dict and override It seems the end result is the same. Quite so and the andswer will depend on what you are trying to achieve. There is no definitive right answer. I created a class called WebPage which is a stand-alone class (I get that). Sorry, I don't get it! :-). Do you mean you only have a class and never create any instances? Or do you mean you don;t subclass anything in defining it? Or do you mean you only create a single instance? It loads a web page template, and has a function to update the replacement vars with your data (updHtmlVar), and another to spit out the html to a file (wrtHtml). The data that this page holds is an html template. Does it also hold the data displayed by the html? in which case its not updating with 'your' data but with *its own* data. But it may allow you to pass some data to it. Or is it that it renders the html only when given some data? Which it doesn't store? The issue of what data a class is responsible for is key to its design. If the WebPage ownds the data then all access to that data should be via the webPage. If the WebPage accesses the data then it needs an interface to the supplying object. Do you subclass WebPage for each particular page you want Almost certainly not. You should have different instances. But you might have different *kinds* of page (Frame, CSS, Table, Dynamic, Static etc) and those could be subclasses. (because you can customize it with load functions for each piece of data) or do you just use it as is, and create separate functions outside the class that load the data and you just use updHtmlVar to
Re: [Tutor] Subclassing vs. stand alone functions
I am new to Python and trying to get my head around the OO stuff. I guess my question is - when do you go with subclassing vs. making a standalone function? OK, I'll take a slightly different approach than the other answers so far. First: procedural and OO styles of programming are diffrent ways of thinking about a problem. Any programming problem can be solved using either approach and both approaches are equally good, neither is intrinsically better than the other. Second: Some problems are more amenable to an OO aproach than a procedural and vice versa. And the majority can be done either way with very little to choose between them. I will now assume that you understand the procedural way and already know how to apply good procedural design, including modularity featuring loose coupling and tight cohesion. In addition data structure design and its relationship to your procedural design should be a concept familiar to you. ( In a perfect world you'll also be familiar with the princuiples of functional programming and the lambda calculus, but that's possibly asking too much.) Not sure about the lambda calculus, but I have been doing procedural programming for about 10 years. (I try my best for modularity and all that good stuff :) That leaves the question of why and wjen should we use OOP? OOP suits programs that feature a high level of correspondence between the real world and the software modfel we are building. For example simulation software (including many games) usually involves the representation and control of a number of objects. It is a natural link to model these objects as classes and create corresponding objects in our solution. Similarly GUIs are made up of windows, widgets, etc. Again these have a fairtly clear translation into objects. When we get into problems primarily of algorithms, or of transforms to fixed data then an OOP style is not always such an obvious fit. Similarly when modelling complex state machines the applicability of OOP can be less obvious and a traditional table driven procedural style may seem better suited. In those cases the decision to use OOP is likely to be driven by the desire to create a reusable component. Something that can be utilised across multiple projects. or it may be driven by the desire to abstract away a complex process or data structure. Hiding it behind a simplere API. This can be done using traditional approaches but usually only at the cost od writing an awful lot of code or by exposing the data structure at least for initialisation purposes. Thanks, this is just what I needed! A way to think about which to use. Now to your examples: Let's say you want to load a dictionary. Why would anyone ever want to load a dictionary? I just want to create dictionary with some data in it. The data comes from a file, let's say. I would then go on to do something with the dictionary - like use it as input to another function. (Sorry, I am thinking procedurally, or are dictionaries typically populated for you by the functions you call... maybe it's just a bad example. What is the higher level goal you are trying to achieve? Is the dictionary part of the solution or the problem? If it is part of the problem a dictionary object may be appropriate. If its part of the solution, and you are already using a non OOP approach why would you want an object? Unless its for the reasons above - reuse or abstraction that is hard using procedures. But you should very rarely be making decisions at this level unless you have alrwady decided on amn overall approach and you are considering an exception to the overall style. ie Should I create a function in an OOP design or should I create a class in a procedural design. (Mixing styles is OK but will normally involve some compromises) Do I create a function that accepts some argument or do I subclass dict and override It seems the end result is the same. Quite so and the andswer will depend on what you are trying to achieve. There is no definitive right answer. I created a class called WebPage which is a stand-alone class (I get that). Sorry, I don't get it! :-). Do you mean you only have a class and never create any instances? No. Or do you mean you don;t subclass anything in defining it? Yes. Or do you mean you only create a single instance? You could have multiple instances. It loads a web page template, and has a function to update the replacement vars with your data (updHtmlVar), and another to spit out the html to a file (wrtHtml). The data that this page holds is an html template. Does it also hold the data displayed by the html? in which case its not updating with 'your' data but with *its own* data. But it may allow you to pass some data to it. Or is it that it renders the html only when given some data? Which it doesn't store? It stores the data and the template. When it is instantiated, you just have the template and the variables. You
Re: [Tutor] Subclassing data attributes
Jan Eden wrote: Not exactly. My current setup bundles all data attributes in a single module Data containing a single class for each object. So in my main module (Show), I define: class Page(Data.Page): ... and Data contains: class Base: children = 'xyz' children_query = 'SELECT...' class Page: children = 'something' own_type = 'somethingelse' populate_query = SELECT ... index_link = p... ... So I can use self.children_query for an object of class Show.Page to get the data attribute defined in class Data.Base. But since there are many data attributes, I'd like to use things like: self.templates['index_link'] self.templates['child_link'] self.queries['populate'] or self.Templates.index_link self.Templates.child_link self.Queries.populate OK I'll try again. I still don't understand why you don't like using straight class attributes - is it to keep the size of the class namespace smaller? I'm also not sure if you want to be able to access Base.children and Page.children from a subclass of Page. If not, then you can use a hierarchical dictionary to do what you want. How about this? import UserDict class ChainDict(UserDict.DictMixin): ''' A dict that will delegate failed lookups to a parent ''' def __init__(self, parent=None): self._dict = dict() self._parent = parent # __setitem__() and __delitem__() delegate to self._dict self.__setitem__ = self._dict.__setitem__ self.__delitem__ = self._dict.__delitem__ def __getitem__(self, key): try: return self._dict[key] except KeyError: if self._parent is not None: return self._parent[key] def keys(self): keys = self._dict.keys() if self._parent is not None: keys.extend(self._parent.keys()) class Base: templates = dict() templates['children'] = 'xyz' templates['children_query'] = 'SELECT * from Base' class Page(Base): templates = ChainDict(Base.templates) templates['children'] = 'something' templates['own_type'] = 'somethingelse' templates['populate_query'] = SELECT * from Page templates['index_link'] = p... b = Base() print b.templates['children'] print b.templates['children_query'] print p = Page() print p.templates['children'] print p.templates['children_query'] print p.templates['index_link'] Kent PS Please reply on list. -- http://www.kentsjohnson.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing across multiple modules
Brian van den Broek wrote: Kent Johnson said unto the world upon 2005-03-17 20:44: The multiple inheritance from MyNode and Toolkit.NodeX is a smell. I guess you do this because you want to override methods of Toolkit.Node as well as Toolkit.NodeX, or add methods to both MyNode1 and MyNode2? I would look for another way to do this, maybe using some kind of helper class to hold some common functions? The adding methods rationale. I never instantiate Node, instead I use it for behaviour common to Node1 and Node2. Toolkit.py gives specialized methods to both Node1 and Node2. I need MyNode1 and MyNode2 (the Application.py versions) to have all the powers of the Toolkit.Node1 and Node2 classes, plus some new powers in common, and some new powers defined separately. That is the sort of thing I had understood multiple inheritance to be for -- but my understanding is about as shaky as an addict in withdrawal :-) Are you suggesting the multiple inheritance is always a smell? No. Some people would agree with that - e.g. the creators of Java - but I have seen many times where MI is useful. Usually it is to combine a primary base class with a mixin - a class that adds functionality orthogonal to that of the base class, or that modifies a carefully chosen set of base class methods. http://c2.com/cgi/wiki?MultipleInheritanceIsNotEvil http://c2.com/cgi/wiki?MixIn For example in a GUI toolkit you might have an Observable add-in that gives a class means to remember and broadcast to listeners. In the Python library there are SocketServer mixins that create a threaded server. BUT there are some clear gotchas to MI. They mostly arise when you inherit from classes that themselves have a common base class. The diamond pattern is the usual example: class A: .. class B(A): .. class C(A): .. class D(B, C): .. Now you can have all kinds of fun (i.e. subtle bugs and confusion) if A, B, C and D have methods in common and if they want to call the methods of their base classes. One of the changes is new-style classes (the addition of super() and a change to the method resolution order) was made to address some deficiencies in how old-style classes handle this situation. So, calling this a code smell is probably not the right term. It's more like a red warning light and klaxon :-) You just don't want to do this without understanding the issues. See http://www.python.org/doc/2.2.3/whatsnew/sect-rellinks.html#SECTION00033 and PEP 253 for details or google diamond multiple inheritance I'll google, but my only grasp of the meaning of helper class is what comes from intuition. For example, instead of subclassing Toolkit.Node, could you define the extra methods in another class. Then your NodeX subclasses can inherit from Toolkit.NodeX and NodeHelper. e.g. class MyNodeHelper: def doSomethingSpecial(self): # does something with a Toolkit.Node class MyNode1(Toolkit.Node1, MyNodeHelper): .. This is an example of a mixin class. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing across multiple modules
Kent Johnson said unto the world upon 2005-03-17 20:44: Brian van den Broek wrote: A schematic of what I have (with fake names for ease of example) is a base module Toolkit.py and I want to write a module Application.py which specializes the behaviour of the Toolkit.py classes. (I'm using old-style classes, but don't feel committed to that choice.) Toolkit.py defines: class Tree class Node class Node1(Node) class Node2(Node) (other Node subclasses, too, but I'm simplifying.) The Tree class contains a parser method to parse a file. It reads the file, breaking it into chunks, and for each chunk, does the following: if some_condition_on_chunk_contents: node = Node1(chunk_contents) else: node = Node2(chunk_contents) self.nodes.append(node) Application.py will define class Tree(Toolkit.Tree) class Node(Toolkit.Node) class Node1(Node, Toolkit.Node1) class Node2(Node, Toolkit.Node2) You're asking for trouble using the same name. Do something like class MyTree(Toolkit.Tree) class MyNode(Toolkit.Node) class MyNode1(MyNode, Toolkit.Node1) class MyNode2(MyNode, Toolkit.Node2) Hi all, thanks for the reply, Kent. I spent a few minutes trying to recall why I had used all the same names in the first place. Then it hit me: it was because I hadn't worked out that the issue I posted about today was there -- I'd naively thought that if I used the same names, I would seamlessly get that a method of an Application.Tree instance that was inherited from Toolkit.Tree would `point' to Application.Node, etc. Oh, well. :-) The multiple inheritance from MyNode and Toolkit.NodeX is a smell. I guess you do this because you want to override methods of Toolkit.Node as well as Toolkit.NodeX, or add methods to both MyNode1 and MyNode2? I would look for another way to do this, maybe using some kind of helper class to hold some common functions? The adding methods rationale. I never instantiate Node, instead I use it for behaviour common to Node1 and Node2. Toolkit.py gives specialized methods to both Node1 and Node2. I need MyNode1 and MyNode2 (the Application.py versions) to have all the powers of the Toolkit.Node1 and Node2 classes, plus some new powers in common, and some new powers defined separately. That is the sort of thing I had understood multiple inheritance to be for -- but my understanding is about as shaky as an addict in withdrawal :-) Are you suggesting the multiple inheritance is always a smell? I'll google, but my only grasp of the meaning of helper class is what comes from intuition. In all cases, a few methods will be added. I had no plans to override existing methods. My problem is that I want Application.Tree.parser to create Application.Node1 and Application.Node2 instances when parsing a file. From testing around with simpler cases, it seems as though unless I override Toolkit.Tree.parser in Application.Tree, the inherited Tree.parser method will create Toolkit.Node1 and Node2 objects, which isn't what I want. Toolkit.Tree.parser is my longest Tree method, and I definitely think it would be bad to just copy and paste the method def into Application.Tree so make the node = Node1(), etc. lines create an Application.Node1, etc. object. Right, you don't want to do this. The best I have come up with is to replace the Toolkit.Tree.parser lines of the form: node = Node1(chunk_contents) with lines like node = self.get_Node1(chunk_contents) and then have *both* Toolkit.Tree and Application.Tree define methods: def get_Node1(self, chunk_contents): return Node1(chunk_contents) (like lines and methods for Node2) This works in my test case, but still involves Copy and Paste of the identical methods get_Node1 (and get_Node2) in both modules. Smelly. :-P This is actually good design. It is a simple example of the Template Method pattern. Use Template Method when you have a function that defines the outline of an algorithm, but you need to specialize some part of the algorithm. You wrap the function in a class (you already have this since it is a method) and call helper methods for the parts you want to specialize. Then subclasses override the helper methods. The methods in MyTree will be different from the ones in Toolkit.Tree, they will look like def get_Node1(self, chunk_contents): return MyNode1(chunk_contents) Bing! Since I'd had the homonymously named class in the first place, I thought this approach would be a smell. (Don't repeat yourself, because then you keep saying the same thing, and repetition is redundant in that it conveys the same information more than once and is pleonastic, as well as overly verbose. ;-) ) But the smell was elsewhere :-) A couple of alternatives: You could actually pass the class constructors directly to Tree.parser(). It would look like this: def parser(self, makeNode1, makeNode2): # makeNode1 2 are callables that return nodes # ... if some_condition_on_chunk_contents: node =
Re: [Tutor] SubClassing
On Fri, 25 Feb 2005 05:54:39 -0200, Ismael Garrido [EMAIL PROTECTED] wrote: def __init__(self, this, that, new): Parent.__init__(self, this, that) #note self self.new = new If the paren's init t has a lot of possible arguments, it may be easier to do things this way: class Child(Parent): def __init__(self, new, *args, **kwargs): Parent.__init__(self, *args, **kwargs) self.new = new This way, the Child class doesn't need to know or care about what parameters get passed on to Parent; it uses the ones it needs, and passes all the rest on. Jeff Shannon ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] SubClassing
Ismael Garrido wrote: Sean Perry wrote: yep. call 'Parent.__init__(this, that)' then do 'self.new = new' def __init__(self, this, that, new): Parent.__init__(this, that) self.new = new Thanks. Though it should be: def __init__(self, this, that, new): Parent.__init__(self, this, that) #note self self.new = new been doing a bunch of C++ programming. C++ - python I always forget about self. python - c++ I always forget the semicolons (-: ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] SubClassing
Ismael Garrido wrote: Hello My code is like this: class Parent: def __init__(self, bunch, of, variables): self.bunch, self.of, self.variables = bunch, of, variables class Son(Parent): def __init__(self, bunch, of, variables, new): self.bunch, self.of, self.variables, self.new = bunch, of, variables, new What I want to know is, is there a better way to write Son class? One in which I don't have to copypaste the parent's init? yep. call 'Parent.__init__(this, that)' then do 'self.new = new' def __init__(self, this, that, new): Parent.__init__(this, that) self.new = new ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing list -- slicing doesn't preserve type
On 22 Feb 2005, [EMAIL PROTECTED] wrote: I'm trying to figure out how to subclass the list built-in. . class my_list(list): def __init__(self, sequence=None): list.__init__(self, sequence) self.spam = 1 . mine = my_list((1,2,3,4)) . mine.append(42) . mine [1, 2, 3, 4, 42] . type(mine) class '__main__.my_list' . damn = mine[1:3] . type(damn) type 'list' . damn [2, 3] . I had thought that by subsclassing list I got all list-like properties for free. Append (among others) are available for my_list instances. But slicing returns a list, rather than a my_list. I can see that this is list-like in it's way, but I'd rather have be so in mine ;-) I've read in the docs that UserList is discouraged, and in the Nutshell that the __getslice__, etc. special methods are depreciated. But the problem is here: list() defines a __getslice__ method. So, how can I get slicing to preserve the my_list type? And why does the above class get so much for free, but not slicing? It gets also slicing for free but think about what happens when you call e.g. `append'; you *mutate an existing object in place* (i.e. a destructive operation). So you change the already existing object which is an instance of Mylist. On the other hand with slicing you get a *new* object back; you never told Python that you also wanted that new object to be of type Mylist. You could do it e.g. like that: class Mylist (list): def __init__(self, seq=None): super(self.__class__, self).__init__(seq) def __getslice__(self, start, stop): return self.__class__(super(self.__class__, self).__getslice__(start, stop)) def __getitem__(self, key): if isinstance(key, slice): return self.__class__(super(self.__class__, self).__getitem__(key)) else: return super(self.__class__, self).__getitem__(key) For simple slices Python calls `list.__getslice__' for extended slices list.__getitem__ gets called. So the above handles all cases. . L = Mylist((1,2,3,4)) . L[1] . 2 . L[1:2] . [2] . type(_) . class '__main__.Mylist' . L[0:4:2] . [1, 3] . type(_) . class '__main__.Mylist' . You must also think about the other methods which return a newly allocated object. Karl -- Please do *not* send copies of replies to me. I read the list ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing list -- slicing doesn't preserve type
Brian van den Broek wrote: Hi all, I'm trying to figure out how to subclass the list built-in. . class my_list(list): def __init__(self, sequence=None): list.__init__(self, sequence) self.spam = 1 . mine = my_list((1,2,3,4)) . mine.append(42) . mine [1, 2, 3, 4, 42] . type(mine) class '__main__.my_list' . damn = mine[1:3] . type(damn) type 'list' . damn [2, 3] . I had thought that by subsclassing list I got all list-like properties for free. Append (among others) are available for my_list instances. But slicing returns a list, rather than a my_list. I can see that this is list-like in it's way, but I'd rather have be so in mine ;-) The problem is that the list methods that return a new list don't know to return an object of your class. You will have to override those methods with a new method that converts the new list to an instance of my_list. Or you can use UserList which does this for you: class my_list(list): def __init__(self, sequence=None): list.__init__(self, sequence) self.spam = 1 def __getslice__(self, i, j): return my_list(list.__getslice__(self, i, j)) print 'Subclass list:' mine = my_list((1,2,3,4)) mine.append(42) print 'mine:', mine print 'type(mine):', type(mine) print damn = mine[1:3] print 'damn', damn print 'type(damn):', type(damn) print from UserList import UserList class my_list2(UserList): def __init__(self, sequence=None): UserList.__init__(self, sequence) self.spam = 1 print 'Subclass UserList:' mine = my_list2((1,2,3,4)) mine.append(42) print 'mine:', mine print 'mine.__class__:', mine.__class__ print damn = mine[1:3] print 'damn', damn print 'damn.__class__:', damn.__class__ prints: Subclass list: mine: [1, 2, 3, 4, 42] type(mine): class '__main__.my_list' damn [2, 3] type(damn): class '__main__.my_list' Subclass UserList: mine: [1, 2, 3, 4, 42] mine.__class__: __main__.my_list2 damn [2, 3] damn.__class__: __main__.my_list2 If you decide to stick with subclassing list, UserList can still be your guide for which methods need wrappers. Look for the calls to self.__class__() in UserList.py. I've read in the docs that UserList is discouraged, and in the Nutshell that the __getslice__, etc. special methods are depreciated. So, how can I get slicing to preserve the my_list type? And why does the above class get so much for free, but not slicing? Best, and thanks to all, Brian vdB ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing list -- slicing doesn't preserve type
Karl Pflästerer said unto the world upon 2005-02-22 07:53: On 22 Feb 2005, [EMAIL PROTECTED] wrote: I'm trying to figure out how to subclass the list built-in. . class my_list(list): def __init__(self, sequence=None): list.__init__(self, sequence) self.spam = 1 SNIP my examples of behaviour: notably, slicing doesn't preserve my_list type So, how can I get slicing to preserve the my_list type? And why does the above class get so much for free, but not slicing? It gets also slicing for free but think about what happens when you call e.g. `append'; you *mutate an existing object in place* (i.e. a destructive operation). So you change the already existing object which is an instance of Mylist. On the other hand with slicing you get a *new* object back; you never told Python that you also wanted that new object to be of type Mylist. You could do it e.g. like that: class Mylist (list): def __init__(self, seq=None): super(self.__class__, self).__init__(seq) def __getslice__(self, start, stop): return self.__class__(super(self.__class__, self).__getslice__(start, stop)) def __getitem__(self, key): if isinstance(key, slice): return self.__class__(super(self.__class__, self).__getitem__(key)) else: return super(self.__class__, self).__getitem__(key) For simple slices Python calls `list.__getslice__' for extended slices list.__getitem__ gets called. So the above handles all cases. SNIP Karl's similar output, but with desired behaviour ;-) You must also think about the other methods which return a newly allocated object. Karl Thanks Karl (and Kent in another response), use of super is new to me; from a quick glance at the docs, I am glad to have been pointed at it. For the quick and dirty, I think I will go the __getslice__ way, deprecation be damned. But, learning how to do it the way you have above is high on the list of things to do. Thanks and best, Brian vdB ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subclassing list -- slicing doesn't preserve type
I'm trying to figure out how to subclass the list built-in. You could do it e.g. like that: class Mylist (list): def __init__(self, seq=None): super(self.__class__, self).__init__(seq) def __getslice__(self, start, stop): return self.__class__(super(self.__class__, self).__getslice__(start, stop)) def __getitem__(self, key): if isinstance(key, slice): return self.__class__(super(self.__class__, self).__getitem__(key)) else: return super(self.__class__, self).__getitem__(key) We might want to bring up that using inheritance here might be an inappropriate OOP construct here. It might be better to handle this sort of thing by wrapping a list in a wrapper, and work through delegation. In fact, that's essentially what UserList is. I'm not sure I agree with the documentation of: http://www.python.org/doc/lib/module-UserList.html where it says that subclassing 'list' is usually appropriate. It seems awfully messy to have to overload every method that can potentially produce a new list. And besides, all that work is being done in UserList already: ### from UserList import UserList class MyList(UserList): ... pass ... l = MyList() l.append('a') l.append('b') l.append('c') l2 = l[1:] isinstance(l2, MyList) True ### ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor