![]() |
|
|
|
#1 |
|
I have a set of classes that describe Files, Folders, etc., that I use
often in my scripts for moving files around, getting a files extension, converting paths, changing permissions, etc It's very similar to Jason Orendorff's 'Path' library, and is very useful to me. The base class 'Data.py' stores all the basic attributes of any piece of data on disk, and it is then subclassed to represent files and folders with the attributes specific to that type of object. I recently made a new class 'Disk.py' that is a subclass of 'Folder.py', to describe all of the attributes of any local or network disks attached to the computer. I subclassed it from Folder, because it really is a folder, it's just at the root of a drive. I'm realizing that these 'Disk' objects are pretty useful, and I came up with the idea to put a 'Disks' instance as a shared class variable (singleton?) within the base class ('Data') The idea being that any instance of a File, or Folder object would contain the list of Disk objects attached to the system, and could use them accordingly. Also important is that I would only need to gather the disk info once for any given running application and all the instances could use it (origianlly I was getting the disk info for each File/Folder object) After an hour of banging my head from getting "AttributeError: 'module' object has no attribute 'Disks'" errors, I finally realized that I'm trying to include an instance in the base class that is a subclass of itself. Short of making 'Disk' no longer a subclass of Folder, is there any other way to include a subclassed instance in the base class of that object? (this is very hard to put in to words) ~Sean half.italian@gmail.com |
|
|
|
|
#2 |
|
Posts: n/a
|
writes:
> Short of making 'Disk' no longer a subclass of Folder, is there any > other way to include a subclassed instance in the base class of that > object? (this is very hard to put in to words) It's a little difficult to visualise what you're describing, but IIUC your problem is of this form: ===== foo.py ===== import bar class Foo(bar.Bar): pass ===== ===== bar.py ===== import baz class Bar(baz.Baz): pass ===== ===== baz.py ===== import foo class Baz(foo.Foo): pass ===== That is, each of the classes want to inherit from the others. The usual solution in these cases is to find the common required functionality and factor that out to a separate class that is then the superclass of two of the existing classes, breaking the circle. ===== wibble.py ===== # no dependencies class Wibble(object): pass ===== ===== foo.py ===== import wibble import bar class Foo(wibble.Wibble, bar.Bar): pass ===== ===== baz.py ===== import wibble class Baz(wibble.Wibble): pass ===== Note that Baz no longer subclasses foo.Foo, and both Foo and Baz get the common functionality they share from wibble.Wibble. -- \ "Buy not what you want, but what you need; what you do not need | `\ is expensive at a penny." -- Cato, 234-149 BC, Relique | _o__) | Ben Finney Ben Finney |
|
|
|
#3 |
|
Posts: n/a
|
>
> That is, each of the classes want to inherit from the others. That's not exactly what I'm doing, but your comment still might help. I actually want to include an instance of a subclass in it's superclass like this: ===== foo.py ===== import Baz class Foo: baz = Baz.Baz() def __init__(self): pass ===== ===== bar.py ===== import Foo class Bar(Foo.Foo): pass ===== ===== baz.py ===== import Bar class Baz(Bar.Bar): pass ===== > The usual solution in these cases is to find the common required > functionality and factor that out to a separate class that is then the > superclass of two of the existing classes, breaking the circle. > > ===== wibble.py ===== > # no dependencies > > class Wibble(object): > pass > ===== > > ===== foo.py ===== > import wibble > import bar > > class Foo(wibble.Wibble, bar.Bar): > pass > ===== > > ===== baz.py ===== > import wibble > > class Baz(wibble.Wibble): > pass > ===== > > Note that Baz no longer subclasses foo.Foo, and both Foo and Baz get > the common functionality they share from wibble.Wibble. I have to think about that for a bit and see if it makes sense to factor anything out. Thanks for the idea. Would that be the best solution considering the above description? ~Sean > > -- > \ "Buy not what you want, but what you need; what you do not need | > `\ is expensive at a penny." -- Cato, 234-149 BC, Relique | > _o__) | > Ben Finney half.italian@gmail.com |
|
|
|
#4 |
|
Posts: n/a
|
<half.italian <at> gmail.com> writes:
> That's not exactly what I'm doing, but your comment still might help. > I actually want to include an instance of a subclass in it's > superclass like this: Move the initialization to another function. > > ===== foo.py ===== > # import Baz Remove the line above > > class Foo: > # baz = Baz.Baz() Remove the line above > > def __init__(self): > pass > ===== and add this below: def initFoo(): import baz Foo.baz = baz.Baz() initFoo() No changes in bar.py, baz.py Instead of initFoo, you could use a custom metaclass. Or a class decorator (if and when they become available...) The code above is an effective way of doing what you want. But I'd think about the actual need of doing such things - are you sure it's a good design? -- Gabriel Genellina Gabriel Genellina |
|
|
|
#5 |
|
Posts: n/a
|
> Remove the line above
> and add this below: > def initFoo(): > import baz > Foo.baz = baz.Baz() > initFoo() I got it to work, but I had to add a check to see if the class variable had been set.. def initBaz(): import Baz Foo.baz = Baz.Baz() class Foo: baz = None def __init__(self): if Foo.baz == None: Foo.baz = True initBaz() What exactly is being accomplished by having the init function outside of the class? If there is no check, wouldn't it just execute every time an object is instantiated anyway? > Instead of initFoo, you could use a custom metaclass. Or a class decorator (if > and when they become available...) I haven't tried either of those yet. The names scare me. like this might be a good time to explore them. > The code above is an effective way of doing what you want. But I'd think about > the actual need of doing such things - are you sure it's a good design? > I thought it was a good design, but now I'm not so sure. I'm untrained, so often I dont know the right way to do things. As I build this into the libraries, I'll keep an eye on how the code is developing and go from there. Thanks for the help! ~Sean half.italian@gmail.com |
|
|
|
#6 |
|
Posts: n/a
|
On Mar 15, 7:01 am, half.ital...@gmail.com wrote:
> > Remove the line above > > and add this below: > > def initFoo(): > > import baz > > Foo.baz = baz.Baz() > > initFoo() > > I got it to work, but I had to add a check to see if the class > variable had been set.. > > def initBaz(): > import Baz > Foo.baz = Baz.Baz() > > class Foo: > baz = None > def __init__(self): > if Foo.baz == None: > Foo.baz = True > initBaz() > > What exactly is being accomplished by having the init function outside > of the class? If there is no check, wouldn't it just execute every > time an object is instantiated anyway? > > > Instead of initFoo, you could use a custom metaclass. Or a class decorator (if > > and when they become available...) > > I haven't tried either of those yet. The names scare me. > like this might be a good time to explore them. > > > The code above is an effective way of doing what you want. But I'd think about > > the actual need of doing such things - are you sure it's a good design? > > I thought it was a good design, but now I'm not so sure. I'm > untrained, so often I dont know the right way to do things. As I > build this into the libraries, I'll keep an eye on how the code is > developing and go from there. Thanks for the help! > > ~Sean Just initialize Folder at module level - see below. -- Paul class Folder(object): def __init__(self,path): self.path = path pass def __repr__(self): return self.__class__.__name__+"("+self.path+")" class Disk(Folder): def __init__(self,driveLetter): super(Disk,self).__init__(driveLetter+":/") # hokey function to test if a drive letter points to a drive, I'm # sure there's a better way import os,string def isDisk(d): try: os.stat(d + ":/") return True except: return False # instead of calling some initFolder() method, just include this statement # at module level in the module that declares both classes Folder.allDisks = map(Disk,[d for d in string.uppercase if isDisk(d)]) # now can reference allDisks through Folder instances f = Folder("C:/temp") print f.allDisks prints: [Disk(C:/), Disk(D:/), Disk(E:/)] Paul McGuire |
|
|
|
#7 |
|
Posts: n/a
|
> Just initialize Folder at module level - see below.
> -- Paul > > class Disk(Folder): > def __init__(self,driveLetter): > super(Disk,self).__init__(driveLetter+":/") What is going on there? Is it just explicitly calling the super's init function? How is that really different from this: class Disk(Folder): def __init__(self,driveLetter): Folder.Folder.__init__(self.path) # ??? Being that Folder is the superclass? I'd like to be able to use the shared Disk objects in any class that is a subclass of Data. Will the above method still make the Disk objects available in File.py? Also, what if the classes are in different modules. I'll try to experiment with it this afternoon. I'm using more information than just the drive letter. What if the user wants to find out the unc path to the share given the drive letter, or copy a file to the local disk that is not a system disk that has the most available space on it, or wants to mount or unmount a network drive. pause... I'm trying to justify why the Folders/Files really need the drive info beyond just the paths and I'm having a hard time. I even just tried to give an example of how it would be used, and couldn't. It seems to make sense on a gut level, but maybe it's just as usefull on it's own. There's definitely justification for having Disks be a subclass of Folder, but not necessarily for there to be an instance of it available within the classes. All that kind of work will be external to the class. I think I'll backtrace and keep it separate. Thanks for letting me think it through. ~Sean half.italian@gmail.com |
|
|
|
#8 |
|
Posts: n/a
|
On Mar 15, 1:55 pm, half.ital...@gmail.com wrote:
> > class Disk(Folder): > > def __init__(self,driveLetter): > > super(Disk,self).__init__(driveLetter+":/") > > What is going on there? Is it just explicitly calling the super's > init function? What is going on is that Disk is being initialized with a single character, such as 'D', and then calling the superclass with 'D:/', the root folder on D. You're the one who said that Disk was a subclass of Folder (sorry, you called it "Data"), so I tried to come up with an example in which this made some kind of sense. > How is that really different from this: > > class Disk(Folder): > def __init__(self,driveLetter): > Folder.Folder.__init__(self.path) # ??? Being that Folder is the > superclass? > Where did self.path come from? Even though Folder is the superclass, self.path doesn't exist until the Folder.__init__ method gets called. This ain't C++ you know. And as I said above, we are taking a single character drive letter, and calling the superclass init with the root directory of that drive, so these are . > I'd like to be able to use the shared Disk objects in any class that > is a subclass of Data. Will the above method still make the Disk > objects available in File.py? Also, what if the classes are in > different modules. > > I'll try to experiment with it this afternoon. I'm using more > information than just the drive letter. What if the user wants to > find out the unc path to the share given the drive letter, or copy a > file to the local disk that is not a system disk that has the most > available space on it, or wants to mount or unmount a network drive. > Knock yourself out. I just hacked together these Folder/Disk classes by way of a half-baked-but-working example. My point is that to initialize a class level variable on class Foo, all that is needed is to assign it in the defining module, that is: class Foo: pass Foo.fooClassVar = "a class level variable" Now any Foo or sub-Foo can access fooClassVar. The type of fooClassVar can be anything you want, whether it is a Foo, subclass of Foo or whatever, as long as it has been defined by the time you assign fooClassVar. -- Paul Paul McGuire |
|
|
|
#9 |
|
Posts: n/a
|
En Thu, 15 Mar 2007 09:01:07 -0300, <> escribió:
> I got it to work, but I had to add a check to see if the class > variable had been set.. > class Foo: > baz = None > def __init__(self): > if Foo.baz == None: > Foo.baz = True > initBaz() This is a different approach. You are using instance initialization (Foo.__init__) to finish class initialization. Foo.__init__ will be called each time you create a Foo instance; that's why you had to check if Foo.baz is None. (BTW, Foo.baz=True is unneeded). The only problem I can see is that the Foo class is not completely initialized until its first instance is created; this may not be a problem in your case. > What exactly is being accomplished by having the init function outside > of the class? If there is no check, wouldn't it just execute every > time an object is instantiated anyway? What I intended was different: ========== C:\TEMP>type foo.py class Foo: baz = None def __init__(self): pass def initFoo(): import baz Foo.baz = baz.Baz() initFoo() C:\TEMP>type bar.py import foo class Bar(foo.Foo): pass C:\TEMP>type baz.py import bar class Baz(bar.Bar): pass C:\TEMP>type test.py import foo,bar,baz print foo.Foo.baz f = foo.Foo() print f.baz b = bar.Bar() print b.baz print baz.Baz.baz C:\TEMP>python test.py <baz.Baz instance at 0x00AD7B20> <baz.Baz instance at 0x00AD7B20> <baz.Baz instance at 0x00AD7B20> <baz.Baz instance at 0x00AD7B20> ========== initFoo is only executed when Foo is imported the first time. Note that you can't do that if > I thought it was a good design, but now I'm not so sure. I'm > untrained, so often I dont know the right way to do things. As I > build this into the libraries, I'll keep an eye on how the code is > developing and go from there. Thanks for the help! Usually Python code is quite concise and straightforward; when I find myself writing things too convoluted, I know it's time to refactor/redesign. (Anyway some things remain not as simple as I'd like Perhaps you later find the need for a different/better way. -- Gabriel Genellina Gabriel Genellina |
|
|
|
#10 |
|
Posts: n/a
|
> > How is that really different from this:
> > > class Disk(Folder): > > def __init__(self,driveLetter): > > Folder.Folder.__init__(self.path) # ??? Being that Folder is the > > superclass? > > Where did self.path come from? Even though Folder is the superclass, > self.path doesn't exist until the Folder.__init__ method gets called. > This ain't C++ you know. My bad. I should have said: class Disk(Folder): def __init__(self,driveLetter): Folder.Folder.__init__(self, driveLetter + ":/") > Knock yourself out. I just hacked together these Folder/Disk classes > by way of a half-baked-but-working example. My point is that to > initialize a class level variable on class Foo, all that is needed is > to assign it in the defining module, that is: > > class Foo: > pass > > Foo.fooClassVar = "a class level variable" > Now any Foo or sub-Foo can access fooClassVar. The type of > fooClassVar can be anything you want, whether it is a Foo, subclass of > Foo or whatever, as long as it has been defined by the time you assign > fooClassVar. That was the first thing I tried, but because the libs were importing each other, etc, it got hung up with wierd "This module doesn't exist" errors, when it clearly did. ~Sean half.italian@gmail.com |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| loading java class from .war file | jayeth | Software | 0 | 04-09-2009 07:06 PM |
| Eclipse how to add external class with different pkg name | jan2321 | General Help Related Topics | 0 | 11-06-2008 10:04 AM |
| 70-536, 3 questions | blade | MCTS | 11 | 03-23-2008 03:47 PM |
| 2007/11/29 Boris 7 new programs, Logic Studio 8 for Mac, MicrosoftVisual Studio 2008 Professional Edition, Microsoft Windows Vista UltimateNov-2007.Win32/64, other new programs | ola@mail.gr | DVD Video | 0 | 11-29-2007 06:15 AM |
| Storing class with session (ASP.Net) | bqmassey | Software | 0 | 09-22-2006 05:37 PM |