Re: [Tutor] class method problem
On Sun, 26 Sep 2010 02:26:25 pm David Hutto wrote: > On Sat, Sep 25, 2010 at 9:16 PM, Steven D'Aprano wrote: > > On Sun, 26 Sep 2010 08:13:23 am David Hutto wrote: > >> Since I had nothing else to do, but practice, this looks much > >> better: > >> > >> def find(word, search): > >> if search in word: > >> print True > >> else: > >> print False [...] > OP wanted to find if a in b. Does my function do that?...Yep I didn't say that the function did the wrong thing, I said the name was misleading for what it actually did. Why didn't you call the function len(), or deleteItemsFromPage()? Because those names would be misleading, deceptive and silly. And so is calling a function find() when it does something completely different from the commonly understood meaning of the word "find". When you find something, you know where it is afterwards. In the context of text searches, that means returning an offset to where the target is found, or something similar. That's what str.find() does, and regular expressions, and list.index(). Your "find" function is a membership test, which is what the `in` operator is for. > > Yes, we found your terms on the Internet, but we won't tell you > > where. If you would like to find something else, we won't tell > > you where that is either. > > It's not supposed to be a four line version of Google. I didn't say it was. I tried to inject a little humour into the email, but it clearly didn't work. [...] > > Even this is slightly misleading, because "text" doesn't need to be > > an actual string. It could be any sequence, such as a list. But > > this gives the *intention* of the function, which is to do text > > searches. So this is (in my opinion) an acceptable compromise > > between intention and generality. > > Semantics, are only important to those who didn't write it. "Semantics" means "meaning". If you are trying to tell me that the meaning of programs -- their *purpose* -- is unimportant, that it doesn't matter what a function does, I'm afraid you'll have your work cut out to convince me. The most important reader of your functions is... you. The function might be fresh in your mind *today*, but tomorrow? Next week? Six months from now when you discover a bug in your program and are trying to remember how it works so you can fix it? Trust me, any non-trivial program that you don't just use once and throw away needs to be written with a careful eye to naming functions and arguments. The ideal is that you should never need to write documentation, because the functions and arguments document themselves. (This is an ideal that never quite works in practice, but we can at least *try*.) An excellent piece of advice I've been given is to write your program's API -- the names of functions, the calling signatures, and so forth -- as if the next person to maintain that code will be a psychopath with a hair-trigger temper and a gun and who knows where you live. Since the next person to maintain it will likely be you, you will save *much* more time in the future by careful and consistent naming than it costs to think of those names right now. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
On Sat, Sep 25, 2010 at 9:16 PM, Steven D'Aprano wrote: > On Sun, 26 Sep 2010 08:13:23 am David Hutto wrote: >> Since I had nothing else to do, but practice, this looks much better: >> >> def find(word, search): >> if search in word: >> print True >> else: >> print False > > > For some definition of "better". > > If I called a function: > > find("anti-disestablishmentarianism", "lish") > > and got back an answer: > > True > > I'd feel ripped off and cheated. That would be like going to Google, > typing in something into the search box, and Google comes back with: OP wanted to find if a in b. Does my function do that?...Yep > > Yes, we found your terms on the Internet, but we won't tell you > where. If you would like to find something else, we won't tell > you where that is either. It's not supposed to be a four line version of Google. > > Aside from the name of the function, which is deceptive because it > doesn't describe what the function does, the names of the arguments are > also poor. The first argument is not necessarily a word. Badly named yes, but I know it just finds a string in a string Nor is there > any need for it to be -- it can be any text. The second argument is > poorly described as "search" -- search is a verb. > > A better function signature might be: > > def search(text, target): > # Search for target in text and print whether it is found or not. > > Even this is slightly misleading, because "text" doesn't need to be an > actual string. It could be any sequence, such as a list. But this gives > the *intention* of the function, which is to do text searches. So this > is (in my opinion) an acceptable compromise between intention and > generality. Semantics, are only important to those who didn't write it. > > Now on to the code itself. The body of the function is needlessly > verbose. You say: > > if search in word: > print True > else: > print False > > This is so simple we can trace the entire function by hand. Say we call > search("I like spam and eggs", "spam"): > > (1) target in text? => True > (2) take the if branch > (3) print True > > Now say we call find("I like spam and eggs", "cheese"): > > (1) target in text? => False > (2) take the else branch > (3) print False > > Can you see the common factor? The object which is printed is always > precisely the same object generated by the `in` test. So we can > simplify the body of the function: > > def search(text, target): > print target in text > > > But this is so simple, there's no point to wrapping it in a function! > > Small functions that do one thing are good, up to a point, but when the > function is so small that it is just as easy to include the body in the > caller code, the function is pointless. It's not like "search(b, a)" is > easier to write or remember than "print a in b" -- if anything the > opposite is the case, because I would never remember which order to > pass the arguments. The reason I put it in a function, was the same reason the OP put it in a class, to eventually expand on the initial program being created.(also I had it in a snippets file, accompanied by an instance for it, a way to conveniently call it later if needed) I do know I could have shortened it further, I'm not all omniscient like yourself. Breath deeply, and remember it's someone elses code who hasn't had the same experience writing code that you have. But thanks for pointing it out, I'll know to eliminate the excess in the future, knowing that the all seeing steven is watching my every function. > > > > -- > Steven D'Aprano > ___ > Tutor maillist - tu...@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] class method problem
On Sun, 26 Sep 2010 08:13:23 am David Hutto wrote: > Since I had nothing else to do, but practice, this looks much better: > > def find(word, search): > if search in word: > print True > else: > print False For some definition of "better". If I called a function: find("anti-disestablishmentarianism", "lish") and got back an answer: True I'd feel ripped off and cheated. That would be like going to Google, typing in something into the search box, and Google comes back with: Yes, we found your terms on the Internet, but we won't tell you where. If you would like to find something else, we won't tell you where that is either. Aside from the name of the function, which is deceptive because it doesn't describe what the function does, the names of the arguments are also poor. The first argument is not necessarily a word. Nor is there any need for it to be -- it can be any text. The second argument is poorly described as "search" -- search is a verb. A better function signature might be: def search(text, target): # Search for target in text and print whether it is found or not. Even this is slightly misleading, because "text" doesn't need to be an actual string. It could be any sequence, such as a list. But this gives the *intention* of the function, which is to do text searches. So this is (in my opinion) an acceptable compromise between intention and generality. Now on to the code itself. The body of the function is needlessly verbose. You say: if search in word: print True else: print False This is so simple we can trace the entire function by hand. Say we call search("I like spam and eggs", "spam"): (1) target in text? => True (2) take the if branch (3) print True Now say we call find("I like spam and eggs", "cheese"): (1) target in text? => False (2) take the else branch (3) print False Can you see the common factor? The object which is printed is always precisely the same object generated by the `in` test. So we can simplify the body of the function: def search(text, target): print target in text But this is so simple, there's no point to wrapping it in a function! Small functions that do one thing are good, up to a point, but when the function is so small that it is just as easy to include the body in the caller code, the function is pointless. It's not like "search(b, a)" is easier to write or remember than "print a in b" -- if anything the opposite is the case, because I would never remember which order to pass the arguments. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
On Sun, 26 Sep 2010 04:15:03 am Roelof Wobben wrote: > Hello, > > I have this code: > > class zoeken() : It is traditional to name classes with an initial capital letter, so Zoeken would be better. > pass What is the point of the "pass" statement there? That does nothing. Why did you put that there? > def __len__(self): > return 0 > def __str__(self): > return test2 What is test2? It doesn't exist. > def find(self, strng, ch, start, stop): Count the arguments: 5, including self. Remember that number. This is important later on. > index = start > while index < len(strng) and index < stop: > if strng[index] == ch: > return index > index += 1 > return -1 Watch the indentation. The "return -1" is *inside* the loop. > test = zoeken() > test.woord = "tamara" > test2 = zoeken.find(test, "a", 1,5) > print test(test2) > > But now I get this message : > > Traceback (most recent call last): > File "C:\Users\wobben\workspace\oefeningen\src\test.py", line 20, > in test2 = zoeken.find(test, "a", 1,5) > TypeError: find() takes exactly 5 arguments (4 given) Right. READ THE ERROR, don't just immediately cry for help. Being a programmer means you must have ATTENTION TO DETAIL -- the error tells you *exactly* what the problem is: the find() method takes five arguments, *including* self. You have only given four arguments: find method expects: 1: self 2: strng 3: ch 4: start 5: stop find method actually gets 1: test 2: "a" 3: 1 4: 5 5: ?? > I can do zoeken.find (test2,test, "a", 1,5) but then I get this > message: > > Traceback (most recent call last): > File "C:\Users\wobben\workspace\oefeningen\src\test.py", line 20, > in zoeken.find( test2, test, "a", 1,5) > NameError: name 'test2' is not defined Exactly. That's because test2 does not exist. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
Since I had nothing else to do, but practice, this looks much better: def find(word, search): if search in word: print True else: print False word = raw_input('Enter string of letters to search: ' ) search = raw_input('Enter character to find: ') find(word,search) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
This is a little better, it returns a if "a" in, or None if using "z": class zoeken() : pass def __len__(self): return 0 def __str__(self): return test2 def find(self, strng, ch, start, stop): index = start while index < len(strng) and index < stop: if strng[index] == ch: return ch index += 1 test = zoeken() test.woord = raw_input('Enter string of letters to search: ' ) stop = len(test.woord) search = raw_input('Enter character to find: ') #print 'search =' ,search test2 = test.find(test.woord, search, 1,stop) print test2 Of course, there are other ways to accomplish this. David ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
This returns a if "a" in, or -1 if using "z": class zoeken() : pass def __len__(self): return 0 def __str__(self): return test2 def find(self, strng, ch, start, stop): index = start while index < len(strng) and index < stop: if strng[index] == ch: return ch index += 1 return -1 test = zoeken() test.woord = "tamara" stop = len(test.woord) test2 = test.find(test.woord, "a", 1,stop) print test2 David ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class function problem
On Thu, 23 Sep 2010 05:55:36 am Steven D'Aprano wrote: > You will find the divmod() function useful. divmod(a, b) returns > two numbers: > > a/b as a whole number, any remainder left only Arggh! Of course I meant any reminder left OVER. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class function problem
On Thu, 23 Sep 2010 01:17:59 am Roelof Wobben wrote: > Sorry. I don't get it. > When I have 62 seconds that's 1 minutes and 2 seconds. > I have no clue how I can this with a division. If you have 60 seconds, you have one minute. If you have 120 minutes, you have two minutes. Can you get from 120 to 2 using a division? You will find the divmod() function useful. divmod(a, b) returns two numbers: a/b as a whole number, any remainder left only -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class function problem
On Wed, Sep 22, 2010 at 5:17 PM, Roelof Wobben wrote: >> >> That's very clever. But you might argue that recursion is technically >> still a loop, albeit an implicit one. There is a simpler way to do >> this, without loops entirely. >> >> Hint: repeated subtraction while your number is greater than some >> constant, what you are doing, is essentially the same as doing one >> division operation. > > > Sorry. I don't get it. > When I have 62 seconds that's 1 minutes and 2 seconds. > I have no clue how I can this with a division. > okay, let's take as an example 314 seconds. We need to convert that into minutes and seconds: >>> seconds = 314 >>> seconds / 60.0 5.2334 See what I did there? This means I can fit 5.2 minutes in 314 seconds.No loops or anything. I'm only interested in the whole minutes, so I can use the "//" operator for integer division: >>> seconds // 60 5 That's our minutes. Now all you need to do is find the number of seconds left over. The remainder (that's another hint). See if you can figure that one out for yourself. Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class function problem
> From: hugo.yo...@gmail.com > Date: Wed, 22 Sep 2010 16:16:45 +0200 > Subject: Re: [Tutor] class function problem > To: rwob...@hotmail.com > CC: tutor@python.org > > On Wed, Sep 22, 2010 at 9:10 AM, Roelof Wobben wrote: >> >> >> HEllo, >> >> I have this exercise : >> >> 3.Rewrite the increment function so that it doesn’t contain any loops. >> >> The increment function looks like this : >> >> def increment(time, seconds): >> time.seconds = time.seconds + seconds >> while time.seconds>= 60: >> time.seconds = time.seconds - 60 >> time.minutes = time.minutes + 1 >> while time.minutes>= 60: >> time.minutes = time.minutes - 60 >> time.hours = time.hours + 1 >> >> >> So I thought that recursion can do the job. >> > > That's very clever. But you might argue that recursion is technically > still a loop, albeit an implicit one. There is a simpler way to do > this, without loops entirely. > > Hint: repeated subtraction while your number is greater than some > constant, what you are doing, is essentially the same as doing one > division operation. Sorry. I don't get it. When I have 62 seconds that's 1 minutes and 2 seconds. I have no clue how I can this with a division. > >> >> But how can i Check the outcome. >> print uitkomst gives the object and print time(uitkomst) gives this error >> message : >> >> Traceback (most recent call last): >> File "C:\Users\wobben\workspace\oefeningen\src\test.py", line 34, in >> print time(uitkomst) >> AttributeError: tijd instance has no __call__ method >> > > You can do "print uitkomst.seconds, uitkomst.minutes, uitkomst.hours". > > Alternatively, write a suitable __str__ method for your tijd class. > Then you can just do "print uitkomst" > >> Roelof Oke, thanks for the tip. Stupid I could thought that myself. Roelof ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class function problem
On Wed, Sep 22, 2010 at 9:10 AM, Roelof Wobben wrote: > > > HEllo, > > I have this exercise : > > 3.Rewrite the increment function so that it doesn’t contain any loops. > > The increment function looks like this : > > def increment(time, seconds): > time.seconds = time.seconds + seconds > while time.seconds>= 60: > time.seconds = time.seconds - 60 > time.minutes = time.minutes + 1 > while time.minutes>= 60: > time.minutes = time.minutes - 60 > time.hours = time.hours + 1 > > > So I thought that recursion can do the job. > That's very clever. But you might argue that recursion is technically still a loop, albeit an implicit one. There is a simpler way to do this, without loops entirely. Hint: repeated subtraction while your number is greater than some constant, what you are doing, is essentially the same as doing one division operation. > > But how can i Check the outcome. > print uitkomst gives the object and print time(uitkomst) gives this error > message : > > Traceback (most recent call last): > File "C:\Users\wobben\workspace\oefeningen\src\test.py", line 34, in > print time(uitkomst) > AttributeError: tijd instance has no __call__ method > You can do "print uitkomst.seconds, uitkomst.minutes, uitkomst.hours". Alternatively, write a suitable __str__ method for your tijd class. Then you can just do "print uitkomst" > Roelof ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class problem
On Sat, 18 Sep 2010 07:14:03 pm Roelof Wobben wrote: > P=(Point) This line does not do what you think it does. Brackets in Python are used for two things, grouping and calling functions. To call a function, or a class, you need to have the brackets *after* the function: P = Point() # what about arguments to the function? If you surround it with brackets, as you do above, it does nothing. It's like this: x = (1+1) # exactly the same as x = 1+1 without brackets > a=0 > b=0 > a=id(P) It is a waste of time to initialise variables immediately before initialising them again. > print a > print b > print P > > But now id is a decimal so I don't can't translate it. id(x) returns an integer. By default, integers always print in decimal, if you want to print them in hex you can do this: hex(id(P)) -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class problem
"Roelof Wobben" wrote Create and print a Point object, and then use id to print the object’s unique identifier. Translate the hexadecimal form into decimal and confirm that they match. I initially had no idea what hexadecimal form the text is talking about. id returns a decimal form... This is a badly worded assignment. class Point: def __init__(self, x=0, y=0): self.x = x self.y = y P=(Point) a=0 b=0 The two a,b assigments are seemingly pointless? a=id(P) print a print b print P Why do you want to print b which will be zero? However your print P gave me a clue to what the assignment is about. When you print the object it gives you a hex value I think they want you to extract that value and convert it to decimal to see if its the same as the value id() gives you. At least that's the only sane thing I can think it means! -- 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] class questions
On Sun, Jun 27, 2010 at 6:47 PM, Shashwat Anand wrote: > >> >> The problem of the MRO isn't that it doesn't work, it's that it causes >> behavior that is unintuitive. In my example, We would expect D.x to be >> equal to C.x (since D inherits from C, and C overrides the x method). >> However, this is not the case. This is what the problem is with the >> old MRO system, not so much that it doesn't work at all, but the >> results aren't consistent with what you'd expect from multiple >> inheritance. >> > > I tried your example in python2.6 class A: > ... def x(self): return "in A" > ... class B(A): pass > ... class C(A): > ... def x(self): return "in C" > ... class D(B, C): pass > ... o = D() o.x() > 'in A' > If MRO was in python2.3, the output of o.x() should be 'in C'. It works fine > on 3.2alpha though. > You forgot that the example as is still uses the old MRO, even in 2.3. This is because these classes are still classic-style classes. To use the new MRO you will have to use new-style classes (A must inherit from object). In 3.x it will of course work fine, since everything without explicit inheritance inherits from object. Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
> The problem of the MRO isn't that it doesn't work, it's that it causes > behavior that is unintuitive. In my example, We would expect D.x to be > equal to C.x (since D inherits from C, and C overrides the x method). > However, this is not the case. This is what the problem is with the > old MRO system, not so much that it doesn't work at all, but the > results aren't consistent with what you'd expect from multiple > inheritance. > > I tried your example in python2.6 >>> class A: ...def x(self): return "in A" ... >>> class B(A): pass ... >>> class C(A): ...def x(self): return "in C" ... >>> class D(B, C): pass ... >>> o = D() >>> o.x() 'in A' If MRO was in python2.3, the output of o.x() should be 'in C'. It works fine on 3.2alpha though. > I just found this link, where Guido explains why he changed the MRO > system for new-style classes. He uses the same example I do. > > http://www.python.org/download/releases/2.2.2/descrintro/#mro > > This was the only useful link I found upon googling. Thanks for your effort though. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
On Sun, Jun 27, 2010 at 4:13 PM, Payal wrote: > Hi Hugo, > > On Sun, Jun 27, 2010 at 01:27:37PM +0200, Hugo Arts wrote: >> Here's my attempt. Consider this simple Diamond hierarchy: > [...] >> Now, with this diagram the following code probably doesn't do what you >> expect: > > Actually, it does what is expected. The old mro specifically says, > bottom-top, left-right. So we expected D-B-A-C-A. > Steven says in some cases even this simple logic of bottom-top, > left-right search will not work. As he says, a simple example of it > failing is diffclt to write, so meanwhile I will take his word for it. > The problem of the MRO isn't that it doesn't work, it's that it causes behavior that is unintuitive. In my example, We would expect D.x to be equal to C.x (since D inherits from C, and C overrides the x method). However, this is not the case. This is what the problem is with the old MRO system, not so much that it doesn't work at all, but the results aren't consistent with what you'd expect from multiple inheritance. I just found this link, where Guido explains why he changed the MRO system for new-style classes. He uses the same example I do. http://www.python.org/download/releases/2.2.2/descrintro/#mro Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
Thanks a lot Eike for the code snippet. I got the idea now. With warm regards, -Payal -- On Sat, Jun 26, 2010 at 10:41:59PM +0200, Eike Welk wrote: > Hello Payal! > > On Saturday June 26 2010 19:05:16 Payal wrote: > > Can we say that our own exception classes have only maybe a doc-string > > and pass, nothing more? > > No, you let the exception transport the information that you need for > handling > the error. This is an exception that I use to transport user visible error > messages in a compiler, that I write as a hobby: > > > class UserException(Exception): > '''Exception that transports user visible error messages.''' > def __init__(self, message, loc=None, errno=None): > Exception.__init__(self) > self.msg = message > self.loc = loc > self.errno = errno > > def __str__(self): > if self.errno is None: > num_str = '' > else: > num_str = '(#%s) ' % str(self.errno) > return 'Error! ' + num_str + self.msg + '\n' + str(self.loc) + '\n' > > def __repr__(self): > return self.__class__.__name__ + str((self.msg, self.loc, > self.errno)) > > It contains: > self.msg : The error message > self.loc : An object encoding the location of the error in the program's >text. Together with the file name and the text. > self.errno : An integer to identify the error, for the test framework. > > That said; the expression's type and the error message are often sufficient > to > handle the error. > > > Eike. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
Hi Steven, Thanks a lot for patiently explaining the concepts. I uderstood most of it. With warm regards, -Payal -- On Sun, Jun 27, 2010 at 10:09:38AM +1000, Steven D'Aprano wrote: > Probably not... it's quite complicated, which is why it's rare. I'll > have a think about it and see what I can come up with. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
Hi Hugo, On Sun, Jun 27, 2010 at 01:27:37PM +0200, Hugo Arts wrote: > Here's my attempt. Consider this simple Diamond hierarchy: [...] > Now, with this diagram the following code probably doesn't do what you expect: Actually, it does what is expected. The old mro specifically says, bottom-top, left-right. So we expected D-B-A-C-A. Steven says in some cases even this simple logic of bottom-top, left-right search will not work. As he says, a simple example of it failing is diffclt to write, so meanwhile I will take his word for it. Thanks for the help. With warm regards, -Payal -- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
On Sun, Jun 27, 2010 at 2:09 AM, Steven D'Aprano wrote: > On Sun, 27 Jun 2010 03:05:16 am Payal wrote: >> >> Can you give any simple example where this simple mro will work >> incorrectly? > > Probably not... it's quite complicated, which is why it's rare. I'll > have a think about it and see what I can come up with. > Here's my attempt. Consider this simple Diamond hierarchy: class A: def x(self): return "in A" class B(A): pass class C(A): def x(self): return "in C" class D(B, C): pass A / \ / \ B C \/ \ / D Now, with this diagram the following code probably doesn't do what you expect: >>> obj = D() >>> obj.x() 'in A' D inherits from C, which overrides the x method. But this is seemingly completely ignored by python, which produces the A.x method! So why does this happen? well, the old MRO uses a simple depth-first, left-to-right search. This means that to find a method, python first looks into the leftmost parent, then its leftmost parent, et cetera et cetera. For our diamond, that means this MRO: D, B, A, C, A so, when you try to access D.x, it will look first in D (not found), B (not found), then A, producing the A.x method. And this probably isn't what you want (we inherited from C for a reason, you know). For new style classes, the MRO is actually D, B, C, A. That produces the correct results. The algorithm is a little complicated, and if you would like to know, the link you posted earlier has all the details. Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
On Sun, 27 Jun 2010 03:05:16 am Payal wrote: > Thanks a lot for the quick answer. Still some doubts below. > > On Sat, Jun 26, 2010 at 11:07:17PM +1000, Steven D'Aprano wrote: > > The old MRO (Method Resolution Order) is broken for classes using > > multiple inheritance with a diamond shape inheritance diagram. Not > > a little bit broken, but horribly, horribly broken. > > > > If you have something like this class hierarchy: > > [...] > > > (only with actual methods, of course) then inheritance with > > old-style classes cannot work correctly in some circumstances. > > Fortunately this > > Can you give any simple example where this simple mro will work > incorrectly? Probably not... it's quite complicated, which is why it's rare. I'll have a think about it and see what I can come up with. > i read, > http://www.python.org/download/releases/2.3/mro/ > butdid not get where mro will fail (ofcourse if python implemented it > corrrectly). I think you have misunderstood, which is probably my fault. It's not that the implementation of the classic MRO was buggy, but that the MRO *itself* does not work as wanted. That's why the fix wasn't "just fix the code", but "change the MRO". > > is rare for old-style classes. But for new-style classes, *all* > > multiple inheritance is diamond-shaped, because all classes inherit > > back to object at the top of the diagram: > > still not getting , how do the new style classes solve the problem > (if there was any). By changing the MRO, new-style classes avoid the problem completely. I know it's hard to understand without seeing an example, sorry. > > Python doesn't have a special "abstract class" type, but it is easy > > to make one with just two lines of boilerplate: > > [...] > > Sorry, I am not getting it. I get, > NameError: global name 'Abstract' is not defined Oops! That was my fault. I changed the name of the class from Abstract to AbstractThing but only changed it in one place. Oh, and I had another bug in it too. Here's the code corrected, and tested this time: class AbstractThing(object): def __init__(self): # Next two lines are boilerplate. if type(self) is AbstractThing: raise TypeError("abstract class, you must subclass this") # init code for non-abstract Thing classes goes here class MyThing(AbstractThing): pass x = MyThing() # works y = AbstractThing() # fails > Was that a working code? (cos' I do not know what you mean by > boilerplate) "Boilerplate" means the sort of boring code that doesn't actually solve your problem, but just sets things up for the rest of your code to solve your problem. Boilerplate is usually bad because you have to repeat it over and over again, e.g. declarations in languages like Pascal, C or Java. The amount of boilerplate sometimes exceeds the amount of code actually doing something! If you have a class with twenty methods that all start like this: def method(self, other): if other is None: other = something_else # more code here you'll quickly get bored and frustrated writing the if clause. Especially when later on you realise that you mean something_different instead of something_else, and now you have to go back and change it in twenty places instead of one. *That's* boilerplate. > > class DomainError(ValueError): > > """Used for mathematics domain errors.""" > > pass > > Can we say that our own exception classes have only maybe a > doc-string and pass, nothing more? Technically speaking, if you have a doc string, you don't need the pass :) This is a common design pattern. It is creating a new exception that is exactly the same as ValueError but with a different name. But that's not all you can do -- you can add as much, or as little, functionality to the exception subclass as you like. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
only new classes can have properties, a major tool On Sat, Jun 26, 2010 at 8:17 AM, Payal wrote: > Hi, > Some questions about which I am a bit confused. > > 1. I know there is a difference between mro of classic and new style > classes. but I do not get why we need the new mro, the old one is easy > to predict and understand? > > 2. A friend of mine told me that in C++ abstract classes are classes > which can not be instatiated. Is she right, do we have them in python, > if yes can someone give a simple example? > > 3. In http://www.alan-g.me.uk/tutor/index.htm , Alan has given an > example in "User Defined Exceptions", > >>> class BrokenError(Exception): pass > > Even after reading the section a few times over, I fail to get utility > of such a class. Can someone please explain with better example? > Alan can you please cleanup that section, maybe make it broader and put > the stuff about "SystemExit" elsewhere. > > Thanks a lot in advance. > > With warm regards, > -Payal > -- > > > ___ > 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] class questions
Well the application of defining ones own error is in a module. For example, if I make a banking account module, I might define a WithdrawError if there is a place where a error might occur. That way if client code tries to withdraw too much, you can have a very descriptive error making it easier to understand. On Sat, Jun 26, 2010 at 8:17 AM, Payal wrote: > Hi, > Some questions about which I am a bit confused. > > 1. I know there is a difference between mro of classic and new style > classes. but I do not get why we need the new mro, the old one is easy > to predict and understand? > > 2. A friend of mine told me that in C++ abstract classes are classes > which can not be instatiated. Is she right, do we have them in python, > if yes can someone give a simple example? > > 3. In http://www.alan-g.me.uk/tutor/index.htm , Alan has given an > example in "User Defined Exceptions", > >>> class BrokenError(Exception): pass > > Even after reading the section a few times over, I fail to get utility > of such a class. Can someone please explain with better example? > Alan can you please cleanup that section, maybe make it broader and put > the stuff about "SystemExit" elsewhere. > > Thanks a lot in advance. > > With warm regards, > -Payal > -- > > > ___ > 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] class questions
Hello Payal! On Saturday June 26 2010 19:05:16 Payal wrote: > Can we say that our own exception classes have only maybe a doc-string > and pass, nothing more? No, you let the exception transport the information that you need for handling the error. This is an exception that I use to transport user visible error messages in a compiler, that I write as a hobby: class UserException(Exception): '''Exception that transports user visible error messages.''' def __init__(self, message, loc=None, errno=None): Exception.__init__(self) self.msg = message self.loc = loc self.errno = errno def __str__(self): if self.errno is None: num_str = '' else: num_str = '(#%s) ' % str(self.errno) return 'Error! ' + num_str + self.msg + '\n' + str(self.loc) + '\n' def __repr__(self): return self.__class__.__name__ + str((self.msg, self.loc, self.errno)) It contains: self.msg : The error message self.loc : An object encoding the location of the error in the program's text. Together with the file name and the text. self.errno : An integer to identify the error, for the test framework. That said; the expression's type and the error message are often sufficient to handle the error. Eike. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
Thanks a lot for the quick answer. Still some doubts below. On Sat, Jun 26, 2010 at 11:07:17PM +1000, Steven D'Aprano wrote: > The old MRO (Method Resolution Order) is broken for classes using > multiple inheritance with a diamond shape inheritance diagram. Not a > little bit broken, but horribly, horribly broken. > > If you have something like this class hierarchy: [...] > (only with actual methods, of course) then inheritance with old-style > classes cannot work correctly in some circumstances. Fortunately this Can you give any simple example where this simple mro will work incorrectly? i read, http://www.python.org/download/releases/2.3/mro/ butdid not get where mro will fail (ofcourse if python implemented it corrrectly). > is rare for old-style classes. But for new-style classes, *all* multiple > inheritance is diamond-shaped, because all classes inherit back to > object at the top of the diagram: still not getting , how do the new style classes solve the problem (if there was any). > Python doesn't have a special "abstract class" type, but it is easy to > make one with just two lines of boilerplate: [...] Sorry, I am not getting it. I get, NameError: global name 'Abstract' is not defined Was that a working code? (cos' I do not know what you mean by boilerplate) > class DomainError(ValueError): > """Used for mathematics domain errors.""" > pass Can we say that our own exception classes have only maybe a doc-string and pass, nothing more? Thanks a lot again. With warm regards, -Payal -- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class questions
On Sat, 26 Jun 2010 10:17:45 pm Payal wrote: > Hi, > Some questions about which I am a bit confused. > > 1. I know there is a difference between mro of classic and new style > classes. but I do not get why we need the new mro, the old one is > easy to predict and understand? The old MRO (Method Resolution Order) is broken for classes using multiple inheritance with a diamond shape inheritance diagram. Not a little bit broken, but horribly, horribly broken. If you have something like this class hierarchy: class A: pass class B(A): pass class C(A): pass class D(B, C): pass (only with actual methods, of course) then inheritance with old-style classes cannot work correctly in some circumstances. Fortunately this sort of inheritance diagram: A / \ B C \ / D is rare for old-style classes. But for new-style classes, *all* multiple inheritance is diamond-shaped, because all classes inherit back to object at the top of the diagram: object /\ list str \/ myclass So in order to allow people to inherit from built-ins, we had a choice: (1) Keep the old MRO and a bug which used to be rare would become common; (2) Keep the old MRO but prohibit multiple inheritance and mixins (which would mean breaking a lot of existing code); or (3) Change the MRO to one which doesn't have the bug. The Python developers choose 3. Well, actually, that's not quite true: nobody noticed that the MRO was broken until *after* new-style classes were added in version 2.2, and so the new MRO was added in version 2.3. http://www.python.org/download/releases/2.3/mro/ > 2. A friend of mine told me that in C++ abstract classes are classes > which can not be instatiated. Is she right, do we have them in > python, if yes can someone give a simple example? Python doesn't have a special "abstract class" type, but it is easy to make one with just two lines of boilerplate: class AbstractThing: def __init__(self): # Next two lines are boilerplate. if type(self) is Abstract: raise TypeError("abstract class, you must subclass this") # init code for non-abstract Thing classes goes here > 3. In http://www.alan-g.me.uk/tutor/index.htm , Alan has given an > example in "User Defined Exceptions", > > >>> class BrokenError(Exception): pass > > Even after reading the section a few times over, I fail to get > utility of such a class. Can someone please explain with better > example? Alan can you please cleanup that section, maybe make it > broader and put the stuff about "SystemExit" elsewhere. The utility of user-defined exceptions is simply to allow your code to distinguish between *your* exceptions and other exceptions. Different people have different policies. Some people prefer this: def func(x): if x <= 0: raise ValueError('x must be positive') return sqrt(x) + x**2 Other people prefer this: class DomainError(ValueError): """Used for mathematics domain errors.""" pass def func(x): if x <= 0: raise DomainError('x must be positive') return math.sqrt(x) + math.asin(x**2) Then when you catch an error: try: print func(y) except DomainError: # only catches my own error except ValueError: # catches any other ValueError But both solutions are equally good. Normally you don't want fifty different exception classes in a module, nor do you want every exception to be the same generic class. How finely you divide the error classes is up to you. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods as static methods?
On 5/30/10, Alan Gauld wrote: > "Alex Hall" wrote > >> that it will hit. I would like to not instantiate a Harpoon object, >> just call the Harpoon's getImpactCoords method and pass it the >> required arguments. Is this possible? > > Others have pointed out that > a) This is possible using staticmetjhod or classmetjod decorators and > b) it seems a strange choice since you would expect the ability to > use more than one harpoon and hence be better with an instance... > > I will add that if you really want a class method then maybe > you can do without the class completely and just use a function? Yes, that is what I ended up doing for testing, but it works well and I do not think I will be making missile classes, just put each missile type in its own file in a weapons subfolder, then import "from weapons import *" to import all weapon files. > > The usual reason for class methods is to operate on the > class as a whole - ie all instances - it is not to provide > functionality > without any instances (except in languages without functions, > like Java, which really use static methods as a kluge to cover > their limitations!) > > And functioons are much easiert to write and manage than > instanceless classes! > > 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 > -- Have a great day, Alex (msg sent from GMail website) mehg...@gmail.com; http://www.facebook.com/mehgcap ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods as static methods?
"Alex Hall" wrote that it will hit. I would like to not instantiate a Harpoon object, just call the Harpoon's getImpactCoords method and pass it the required arguments. Is this possible? Others have pointed out that a) This is possible using staticmetjhod or classmetjod decorators and b) it seems a strange choice since you would expect the ability to use more than one harpoon and hence be better with an instance... I will add that if you really want a class method then maybe you can do without the class completely and just use a function? The usual reason for class methods is to operate on the class as a whole - ie all instances - it is not to provide functionality without any instances (except in languages without functions, like Java, which really use static methods as a kluge to cover their limitations!) And functioons are much easiert to write and manage than instanceless classes! 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] class methods as static methods?
Hi Alex, thanks for the response, please see below. On 30/05/2010 02:50, Alex Hall wrote: On 5/29/10, Mark Lawrence wrote: On 29/05/2010 20:49, Alex Hall wrote: Hi all, In Battleship, I have a weapons.py file, currently with just one missile type (a Harpoon anti-ship missile). This Harpoon class defines a getImpactCoords method, which returns all coordinates on the map that it will hit. I would like to not instantiate a Harpoon object, just call the Harpoon's getImpactCoords method and pass it the required arguments. Is this possible? Thanks. Sorry if I got the terms backwards in the subject; I can never remember which is static and which is non-static. Hi Alex, See you're still going for it :) I think that you're trying to build a Yamoto/Musashi before you've built a raft from oil drums or whatever :) If I'm wrong, I'll apologise here and now. I have built one app in Python and have experience in Java and Javascript, as well as some in PHP; in fact, I am going into my fourth year of college for a computer science degree in September. While they have not done as much programming as I would like, I have had enough that I can find the commonalities between languages and generally know what I am looking for (make this public, turn that into a class instead of an independent collection of vars...) That said, I have no professional experience programming and do only assigned problems and hobby-level programming. My Screenless Widgets app is nearing beta testing and works to my satisfaction, but I am sure there is much I could do to improve it. Still, everyone has to start somewhere... I say all this not to express any offense at your message - believe me, none taken - but rather to tell everyone just where I am coming from. I should hope not, I used to be big-headed, but now I'm perfect :) For a really great introduction to Python, I suggest diveintopython, it's what got me going eight years ago. I feel that I understand the basics; what I am running into are things that crop up and I learn them as needed; if I learn a concept but then never use it, I will forget it, or mix it up with a similar comcept in another language, so I generally attack things by reading intro tutorials, modifying them, and then continuing from there until I feel that I can start my own project from scratch and figure out the pieces as I go along. I suggest that you do *NOT* understand the basics, at least wrt Python, otherwise you would not have placed your original queries on c.l.py, before being asked to move to this ng/ml. Regardless of that, you're on *THE* finest group of mls/ngs going for getting very sound advice from some of the most highly respected guys/gals going. And if you want some kind of feeling of industry experiences, subscribe to the Python bugs/development/ideas ngs/mls (if you haven't already done so) and you'll very rapidly get an idea of just how difficult software development can get. As an example, look for the thread on comp.lang.python within the last 24 hours from myself subject "xrange issue 7721". A relatively simple thing you'd have thought, but read the background on the Python bug tracker, and you'll see it ain't quite that easy. But then, what do I know, I've only 34 years industry experience, albeit slightly tempered over the last nine years by physical and mental ill health. Kindest regards. Mark Lawrence. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor I'm now going to bed, as it's 04:08 BST and I'm absolutely shattered. Kindest regards. Mark Lawrence. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods as static methods?
On Sun, 30 May 2010 05:49:45 am Alex Hall wrote: > Hi all, > In Battleship, I have a weapons.py file, currently with just one > missile type (a Harpoon anti-ship missile). This Harpoon class > defines a getImpactCoords method, which returns all coordinates on > the map that it will hit. I would like to not instantiate a Harpoon > object, just call the Harpoon's getImpactCoords method and pass it > the required arguments. I don't understand the logic here. Surely the impact coordinates depends on the individual missile (an instance)? > Is this possible? Thanks. Sorry if I got the > terms backwards in the subject; I can never remember which is static > and which is non-static. In Python terminology, a static method is an ordinary function that is called as a method from either a class or a class instance: class C(object): @staticmethod def method(x): return "Called with argument %s", % x Note that the method does not receive an automatic instance argument (usually called self) when you call it. A class method is like an ordinary method, except instead of receiving the instance (self) as the first argument, it receives the class (usually called cls): class C(object): @classmethod def method(cls, x): return "Called from class %s with argument %s", % (cls, x) The method always receives the class, regardless of whether you call it from the class using C.method(x) or from an instance C().method(x). You might also be interested in what I call "dualmethod", which passes the class as first argument if you call it from the class, and the instance if you call it from the instance: http://code.activestate.com/recipes/577030-dualmethod-descriptor/ -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods as static methods?
On 5/29/10, Mark Lawrence wrote: > On 29/05/2010 20:49, Alex Hall wrote: >> Hi all, >> In Battleship, I have a weapons.py file, currently with just one >> missile type (a Harpoon anti-ship missile). This Harpoon class defines >> a getImpactCoords method, which returns all coordinates on the map >> that it will hit. I would like to not instantiate a Harpoon object, >> just call the Harpoon's getImpactCoords method and pass it the >> required arguments. Is this possible? Thanks. Sorry if I got the terms >> backwards in the subject; I can never remember which is static and >> which is non-static. >> > > Hi Alex, > > See you're still going for it :) > > I think that you're trying to build a Yamoto/Musashi before you've built > a raft from oil drums or whatever :) If I'm wrong, I'll apologise here > and now. I have built one app in Python and have experience in Java and Javascript, as well as some in PHP; in fact, I am going into my fourth year of college for a computer science degree in September. While they have not done as much programming as I would like, I have had enough that I can find the commonalities between languages and generally know what I am looking for (make this public, turn that into a class instead of an independent collection of vars...) That said, I have no professional experience programming and do only assigned problems and hobby-level programming. My Screenless Widgets app is nearing beta testing and works to my satisfaction, but I am sure there is much I could do to improve it. Still, everyone has to start somewhere... I say all this not to express any offense at your message - believe me, none taken - but rather to tell everyone just where I am coming from. > > For a really great introduction to Python, I suggest diveintopython, > it's what got me going eight years ago. I feel that I understand the basics; what I am running into are things that crop up and I learn them as needed; if I learn a concept but then never use it, I will forget it, or mix it up with a similar comcept in another language, so I generally attack things by reading intro tutorials, modifying them, and then continuing from there until I feel that I can start my own project from scratch and figure out the pieces as I go along. > > Kindest regards. > > Mark Lawrence. > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor > -- Have a great day, Alex (msg sent from GMail website) mehg...@gmail.com; http://www.facebook.com/mehgcap ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods as static methods?
On 29/05/2010 20:49, Alex Hall wrote: Hi all, In Battleship, I have a weapons.py file, currently with just one missile type (a Harpoon anti-ship missile). This Harpoon class defines a getImpactCoords method, which returns all coordinates on the map that it will hit. I would like to not instantiate a Harpoon object, just call the Harpoon's getImpactCoords method and pass it the required arguments. Is this possible? Thanks. Sorry if I got the terms backwards in the subject; I can never remember which is static and which is non-static. Hi Alex, See you're still going for it :) I think that you're trying to build a Yamoto/Musashi before you've built a raft from oil drums or whatever :) If I'm wrong, I'll apologise here and now. For a really great introduction to Python, I suggest diveintopython, it's what got me going eight years ago. Kindest regards. Mark Lawrence. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods as static methods?
On 05/30/10 05:49, Alex Hall wrote: > Hi all, > In Battleship, I have a weapons.py file, currently with just one > missile type (a Harpoon anti-ship missile). This Harpoon class defines > a getImpactCoords method, which returns all coordinates on the map > that it will hit. I would like to not instantiate a Harpoon object, > just call the Harpoon's getImpactCoords method and pass it the > required arguments. Is this possible? Thanks. Sorry if I got the terms > backwards in the subject; I can never remember which is static and > which is non-static. > Yes you can make it a static method or class method: class Harpoon(object): @staticmethod def inst(a, b, c): print a, b, c @classmethod def cmeth(cls, a, b, c): print cls print a, b, c Harpoon.inst(1, 2, 3) Harpoon.cmeth(1, 2, 3) the question is, why would you want to? getImpactCoords() doesn't seem to be a function that makes sense without a missile instance (I may be mistaken). ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods: using class vars as args?
On Fri, 28 May 2010 07:42:30 am Alex Hall wrote: > Thanks for all the explanations, everyone. This does make sense, and > I am now using the > if(arg==None): arg=self.arg > idea. It only adds a couple lines, and is, if anything, more explicit > than what I was doing before. You should use "if arg is None" rather than an equality test. In this case, you are using None as a sentinel value. That is, you want your test to pass only if you actually receive None as an argument, not merely something that is equal to None. Using "arg is None" as the test clearly indicates your intention: The value None, and no other value, is the sentinel triggering special behaviour while the equality test is potentially subject to false positives, e.g. if somebody calls your code but passes it something like this: class EqualsEverything: def __eq__(self, other): return True instead of None. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods: using class vars as args?
Thanks for all the explanations, everyone. This does make sense, and I am now using the if(arg==None): arg=self.arg idea. It only adds a couple lines, and is, if anything, more explicit than what I was doing before. On 5/27/10, Mark Lawrence wrote: > On 23/05/2010 20:40, Alex Hall wrote: >> Hello all, >> I know Python reasonably well, but I still run into basic questions >> which those over on the other python list request I post here instead. >> I figure this would be one of them: >> Why would this not work: >> >> class c(object): >> def __init__(self, arg1, arg2): >>self.arg1=arg1 >>self.arg2=arg2 >> >> def doSomething(self, arg3=self.arg1): >>... >> >> The above results in an error that "name 'self' is not defined". Why >> can I not set the default values of a method's arguments to class vars >> like that? Thanks! >> >> > You've already had some explanations as to what happens, but what are > you trying to achieve? Why don't you forget about arg3 because it is > arg1, which must exist by creating an instance of class c, or you > wouldn't be able to call doSomething in the first place? > > HTH. > > Mark Lawrence > > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor > -- Have a great day, Alex (msg sent from GMail website) mehg...@gmail.com; http://www.facebook.com/mehgcap ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods: using class vars as args?
On 23/05/2010 20:40, Alex Hall wrote: Hello all, I know Python reasonably well, but I still run into basic questions which those over on the other python list request I post here instead. I figure this would be one of them: Why would this not work: class c(object): def __init__(self, arg1, arg2): self.arg1=arg1 self.arg2=arg2 def doSomething(self, arg3=self.arg1): ... The above results in an error that "name 'self' is not defined". Why can I not set the default values of a method's arguments to class vars like that? Thanks! You've already had some explanations as to what happens, but what are you trying to achieve? Why don't you forget about arg3 because it is arg1, which must exist by creating an instance of class c, or you wouldn't be able to call doSomething in the first place? HTH. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods: using class vars as args?
On Sun, 23 May 2010 15:40:13 -0400 Alex Hall wrote: > Hello all, > I know Python reasonably well, but I still run into basic questions > which those over on the other python list request I post here instead. > I figure this would be one of them: > Why would this not work: > > class c(object): > def __init__(self, arg1, arg2): > self.arg1=arg1 > self.arg2=arg2 > > def doSomething(self, arg3=self.arg1): > ... > > The above results in an error that "name 'self' is not defined". Why > can I not set the default values of a method's arguments to class vars > like that? Thanks! Python gives you the answer (I'm not kidding): "name 'self' is not defined". "self" is not a magic name in python, unlike in some other languages, automagically receiving a value. It is just a name you can use for anything, like "self=1". A *convention* tells that this name is used for the *target* of a message. For instance: l = [3,1,2] l.sort() calls sort on the target l, which becomes the object on which sort applies. Right? Then, python magically (this is the only magic) adds l as first argument to the method sort of the list class, at call time. If sort were defined in python, its header could look like: def sort(target_list, compare_function=None): The convention requires "target_list" to be rather called "self". In your code, nowhere is a variable called "self" defined, before you try to use it. Since this happens in a class def, it should be first defined outside (probably in the global scope). If you write "self=1" somewhere before the class def, python will stop complaining about "self"... but it will complain about "arg1"! A solution for what I guess you're trying to do is: def doSomething(self, arg3=None): if arg3 is None then arg3=self.arg1 The reason is that your default value, not only is not a constant, but is a variable depending on the actual instance, at call time. The only handle available to address an instance is precisely as target of a method call. So, you can only define something (here a default value) that depends on the instance from *inside* a method body, where the handle exists (magically brought by python). Hope it's clear. Denis vit esse estrany ☣ spir.wikidot.com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class methods: using class vars as args?
Hey Alex, What's happening is that you're still in "defining functions" mode on the line def doSomething(self, arg3=self.arg1): self, which is really nothing more than a parameter being passed in (special parameter, but a parameter none the less) hasn't been assigned a value yet. Imagine this function definition: def do_something(a, b, c=a+b): The parameter instances haven't been instantiated yet. Another way to look at it: You haven't finished defining the class yet, so you can't access data specific to an instance. Not the most technical description, but it's certainly how I look at it. -- I enjoy haiku but sometimes they don't make sense; refrigerator? On Sun, May 23, 2010 at 1:40 PM, Alex Hall wrote: > Hello all, > I know Python reasonably well, but I still run into basic questions > which those over on the other python list request I post here instead. > I figure this would be one of them: > Why would this not work: > > class c(object): > def __init__(self, arg1, arg2): > self.arg1=arg1 > self.arg2=arg2 > > def doSomething(self, arg3=self.arg1): > ... > > The above results in an error that "name 'self' is not defined". Why > can I not set the default values of a method's arguments to class vars > like that? Thanks! > > > -- > Have a great day, > Alex (msg sent from GMail website) > mehg...@gmail.com; http://www.facebook.com/mehgcap > ___ > 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] class methods: using class vars as args?
"Alex Hall" wrote class c(object): def __init__(self, arg1, arg2): self.arg1=arg1 self.arg2=arg2 def doSomething(self, arg3=self.arg1): ... The above results in an error that "name 'self' is not defined". Why can I not set the default values of a method's arguments to class vars like that? Thanks! Because they are not class vars they are instance vars. self.arg1 does not exist until after an instance has been created and they have been set by __init__. At the time the class is defined self.arg1 does not exist. You could do class c(object): defArg = 42 def __init__(self, arg1, arg2): self.arg1=arg1 def doSomething(self, arg3=defArg): ... 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] Class Inheritance, Beat it into the Ground
"Steven D'Aprano" wrote Yes, Tkinter could have had a ScrolledCanvas. It could have had lots of things, you have to draw the line somewhere otherwise you end up with one giant module that does *everything*: And for completeness there are a number of add-on modules in the standard library that provide many of these extra widgets. Tix and the turtle module are two examples. The standard dialogs etc are also in separate modules. And there are several other add-on moduiles not in the standard library that you can download that extend Tkinter even further. This is all designed so you only need to use the bits you actually need. 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] Class Inheritance, Beat it into the Ground
"David Hutto" wrote In previous post I asked about turtle module importing from tkinter. But what I don't understand is why does Tkinter default it's casnvas to ScrolledCanvas in turtle.py, Tkinter doesn't. The author of the turtle module - which is not part of Tkinter but simply uses it - chose to use a Scrolled Canvas. Presumably because he wanted a canvas that scrollled! and then as a 'metaclass' for ScrolledCanvas in turtle it calls TK.Frame, Its not a meta-class its a super class - the two concepts are completely different and you don't want to be thinking about meta classes for a long time yet! which could have been set as a default within Tkinter itself? No it couldn't because turtle.py didn't exist when Tkinter was created. And even if it did you couldn't guarantee that everyone would want it that way. Tkinter is a generic UI framework that can be used in many applications. It should not be defined to suit any single application. You appear to be struggling with the concept of module use and dependencies. You should be trying to create a tree structure of dependencies with no circular loops. turtle depends on Tkinter but Tkinter does not depend on turtle. And your code can depend on Tkinter, turtle or both. But neither module should know anything about your code. Inheritance is a mechanism for taking an existing class and specialising it for your specific application. So turtle specialised Frame to produce a ScrolledCanvas which it uses to display the turtle. 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] Class Inheritance, Beat it into the Ground
On Sat, 24 Apr 2010 03:41:04 pm David Hutto wrote: > In previous post I asked about turtle module importing from tkinter. > But what I don't understand is why does Tkinter default it's casnvas > to ScrolledCanvas in turtle.py, and then as a 'metaclass' for > ScrolledCanvas in turtle it calls TK.Frame, which could have > been set as a default within Tkinter itself? Tkinter doesn't know anything about turtle. turtle is an independent module which is built on top of Tkinter. >>> Tkinter.turtle Traceback (most recent call last): File "", line 1, in Tkinter.turtle AttributeError: 'module' object has no attribute 'turtle' Yes, Tkinter could have had a ScrolledCanvas. It could have had lots of things, you have to draw the line somewhere otherwise you end up with one giant module that does *everything*: >>> import UniversalModuleWithEverything # takes a few hours to load >>> UniversalModuleWithEverything. \ ... Klingon_Wordprocessor_With_Graphics_Imbedded_Spreadsheet().run() *wink* Tkinter doesn't do anything in turtle. turtle wants a ScrolledCanvas, and since Tkinter doesn't have one, it creates it. It uses Tkinter's Frame object as the base class (not a metaclass, metaclasses are an advanced technique which are very different). That way the ScrolledCanvas class inherits behaviour from Frame. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance
On Sat, 24 Apr 2010 01:22:54 am David Hutto wrote: > I'm new, I touched the Holy lib, and > didn't check to reset the original Tkinter directory before posting. > Won't happen again. I'm sorry we got off on the wrong foot, you caught me at a time when I was frustrated about other things, and after spending 30 minutes wasting my time trying to reproduce the errors you were getting, I snapped at you. It's nothing about the library being "Holy", that's an asinine thing to say. It's a software package, not a piece of the One True Cross. But you wouldn't randomly plug and unplug parts in your car engine, and then complain that "Perhaps I've misunderstood something, but it seems to me that the Ford Fiesta doesn't have a working internal combustion engine." You've got the right idea about learning by experimentation, but there's a right way and a wrong way to do it, and the way you've chosen is actively harmful to *you*, as well as wasting the time of those who volunteer to give help. How many hours did you waste because you thought that Python's implementation of inheritance was buggy, due to changes you introduced? Even if it were only *one minute*, it would be too long because it is completely, 100% unnecessary. Keep the standard library as it is supplied. If you want to modify a module to see what happens, make a copy of it and put it in your home directory with another name, and make the changes there. I applaud the fact that you are actively trying to solve problems before asking for help. I'm not being sarcastic or condescending when I say this is fantastic. But I am saying that your practice of *how* you try to solve problems yourself is actually counterproductive, making a rod for your own back, by introducing bugs into code that wasn't buggy in the first place. Learning to code is hard enough when you can trust the library to be (mostly) bug free, don't make it any harder! -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance
On Fri, 23 Apr 2010 04:54:11 pm David Hutto wrote: [...] > > Something is screwy there. I believe you have broken your > > installation by making changes to files without having any > > understanding of what you are doing. > > My original post was incorrect: the first error should be: > > C:\Users\ascent>c:\python26/Script3.py > Traceback (most recent call last): > File "C:\python26\Script3.py", line 1, in > from Tkinter import * > File "C:\Python26\lib\lib-tk\Tkinter.py", line 44, in > from turtle import * > File "C:\Python26\lib\lib-tk\turtle.py", line 374, in > class ScrolledCanvas(TK.Frame): > AttributeError: 'module' object has no attribute 'Frame' For anyone else reading this, this is a good example of why retyping error messages is a bad, bad idea. That just wastes everybody's time, and sends us on wild-goose chases trying to diagnose problems that didn't actually occur. > > Please don't try to "fix" library files when you don't understand > > what they are doing. Confine your experiments to your own code, so > > that when things break, you know that the cause is in your code, > > not some random change you have done to the library. > > I know this, but I reinstall regularly, so evereything is 'pristine'. You know it but continue to do it anyway? If you want to experiment with library modules, make a copy of them into your home directory, with a different name, and experiment to your heart's desire. That gives you all the benefits of experimentation with none of the disadvantages. When you mangle a standard library module, then post long complicated posts suggesting that the Python development team don't understand their own language, you waste our time as well as yours. If you want to waste your time, go right ahead, but don't send us on wild goose chases with nonsense about the turtle module not allowing inheritance when the breakage was due to your tinkering. Next time you do something like this, be up front about it. Tell us right from the beginning that you've been editing the modules, so we don't have to spend our time discovering this for ourselves. If you had, this conversation would have taken a completely different turn. > If I get an error, I don't wait for mailing list responses, I usually > try to analyze, from what I've learned so far, what's wrong and > figure out why on my own All that is good practice. What's not good practice is making random changes to complicated libraries. A good exercise in programming discipline is to try to reproduce the fault in the smallest amount of code possible. When asking for help, you'll often be asked to do this, because when asking for volunteers to spend their time solving your problems for free, it is only fair that you reduce the amount of effort needed as much as possible. As an exercise, I've reproduced your error in minimal form: >>> import mytkinter Traceback (most recent call last): File "", line 1, in File "mytkinter.py", line 1, in from myturtle import * File "myturtle.py", line 3, in class ScrolledCanvas(TK.Frame): AttributeError: 'module' object has no attribute 'Frame' and here's the minimal implementation: # mytinkinter.py from myturtle import * class Frame: pass # myturtle.py import mytkinter as TK class ScrolledCanvas(TK.Frame): pass > P.S. I bet you've been waiting since you got your first condescending > response to a similar question, to lay it on someone about touching > the Almighty Library. > > Way to keep up the cycle. Don't try to psychoanalyse people you've never met, you aren't any good at it. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance
"David Hutto" wrote While experimenting with Tkinter(python2.6), when from Tkinter import* is used I came across the following error: File "C:\Python26\lib\lib-tk\Tkinter.py", line 44, in from turtle import * Huh? Why is Tkinter.py importing from turtle? It doesn't in my Python 2.5 version. File "C:\Python26\lib\lib-tk\turtle.py", line 374, in class ScrolledCanvas(Tkinter.Frame): AttributeError: 'module' object has no attribute 'Frame' Which is also odd since turtle.py imports Tkinter as TK so why would it be referring to Tkinter? Something is broken in your standard modules! Which stems from the below in turtle.py: class ScrolledCanvas(TK.Frame) I know that ScrolledCanvas is trying to use class TK.Frame as it's base class to build from, and the class Frame is what is trying to be called from the Tkinter module. Yes, TK is an alias for Tkinter. So why is your error showing Tkinter when the module imports it as TK? So I tried to alter the turtle.py. When I try to just 'from Tkinter import *, such as: Don't ever modify the standard modules! There lies chaos. If you want to try changing something make a copy and work on that. Then you know you can go back to something that has been tested and proven to work. from Tkinter import * class ScrolledCanvas(Tkinter.Frame): I get: * class ScrolledCanvas(Tkinter.Frame): NameError: name 'Tkinter' is not defined Thats right, when you import * you import all the names inside the module but not the module itself. So any references to the module will generate this error. I know pretty much what is going on there. But when I try to use: import Tkinter from Tkinter import * Don't mix these two styles. It is very common for modules to contain objects of the same name as the module so the second import often hides the module name. And if you do it the other way round the module name hides the internal object. Its just confusing. Use one or the other and preferrably don't use import * except for experimenting at the >>> prompt. class ScrolledCanvas(Tkinter.Frame): It takes me back to the first error. Which means in both instances both directly called by me, and when called from the original turtle.py call, it's not finding the Frame class. Because by messing about with the imports you have confused things to the point where Python doesn't know where to look for it. Go back to the standard modules and work with them as-is. They work. for example, when the base class is defined in another module: class DerivedClassName(modname.BaseClassName) " So why does the above, from turtle.py, a standard module, not allow this, It does and in its original form import Tkinter as TK ... class ScrolledCanvas(TK.Frame) It works just fine! the module writer got wrong, or more likely, that I'm not understanding about what it's doing? You don't understand how Python module imports and namespaces work. Try reading the "Modules and Function" topic in my tutorial followed by "Whats in a name"? As a sidenote, I ended up removing the from turtle import * line from Tkinter which resolved the problem(the example I was using didn't have a canvas, and I'm pretty sure Tkinter was defaulting to the ScrolledCanvas). How did it get there in the first place? Did you add it? Why would Tkinter import turtle? turtle is built using Tkinter not the other way around. Do not change the standard library modules - they work just fine as they are. And because they are used by other modules beeaking one is likely to cause an avalanche effect. If you really think you can improve on them make a copy with a new name and change it. 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] Class Inheritance
On Fri, 23 Apr 2010 03:11:36 pm David Hutto wrote: > Hello List! > > While experimenting with Tkinter(python2.6), when from Tkinter > import* is used I came across the following error: > > C:\Users\ascent>c:\python26/Script3.py > Traceback (most recent call last): > File "C:\python26\Script3.py", line 1, in > from Tkinter import * > File "C:\Python26\lib\lib-tk\Tkinter.py", line 44, in > from turtle import * > File "C:\Python26\lib\lib-tk\turtle.py", line 374, in > class ScrolledCanvas(Tkinter.Frame): > AttributeError: 'module' object has no attribute 'Frame' Something is screwy there. I believe you have broken your installation by making changes to files without having any understanding of what you are doing. The turtle module does this: import Tkinter as TK so that line should be "class ScrolledCanvas(TK.Frame)", and in fact that's what I find when I go and look at the source code: class ScrolledCanvas(TK.Frame): The line number is different too. How many breakages have you introduced to the library? > Which stems from the below in turtle.py: > > class ScrolledCanvas(TK.Frame) Note the difference between Tkinter.Frame and TK.Frame. > I know that ScrolledCanvas is trying to use class TK.Frame as it's > base class to build from, and the class Frame is what is trying to be > called from the Tkinter module. > > So I tried to alter the turtle.py. Please don't try to "fix" library files when you don't understand what they are doing. Confine your experiments to your own code, so that when things break, you know that the cause is in your code, not some random change you have done to the library. > When I try to just 'from Tkinter > import *, such as: > > from Tkinter import * > class ScrolledCanvas(Tkinter.Frame): That won't work, because there is no Tkinter defined. One wrong way to do it is: from Tkinter import * class ScrolledCanvas(Frame): but that risks stomping over the top of other variables with great big hob-nailed boots. Better to avoid import *, and do this: import Tkinter class ScrolledCanvas(Tkinter.Frame): but that's still a silly thing to do, because the turtle module has already imported Tkinter. The right way is to leave the module alone, it was working before you changed it: import Tkinter as TK class ScrolledCanvas(TK.Frame): > I get: > * > C:\Users\ascent>c:\python26/Script3.py > Traceback (most recent call last): > File "C:\python26\Script3.py", line 1, in > from Tkinter import * > File "C:\Python26\lib\lib-tk\Tkinter.py", line 44, in > from turtle import * > File "C:\Python26\lib\lib-tk\turtle.py", line 373, in > class ScrolledCanvas(Tkinter.Frame): > NameError: name 'Tkinter' is not defined Now you have two errors. (1) You have introduced a circular import dependency, where turtle tries to import Tkinter which tries to import Tkinter which tries to import turtle... (2) You have no Tkinter object, since you import it's contents, not the module itself. > I know pretty much what is going on there. I doubt it, or else you wouldn't have done what you did. > But when I try to use: > > import Tkinter > from Tkinter import * Why would you do that when turtle has already imported Tkinter under the name TK? > class ScrolledCanvas(Tkinter.Frame): > > It takes me back to the first error. Which means > in both instances both directly called by me, and > when called from the original turtle.py call, > it's not finding the Frame class. I suspect you've broken it. I recommend you re-install the Tkinter library, including turtle.py, in order to get it back to a known working state. > >From the docs (9.5. Inheritance) it states: > > "The name BaseClassName must be defined in a > scope containing the derived class definition. > In place of a base class name, other arbitrary > expressions are also allowed. This can be useful, > for example, when the base class is defined in another module: > > class DerivedClassName(modname.BaseClassName) > " > > > So why does the above, from turtle.py, a standard module, > not allow this, or is their something > the module writer got wrong, or more likely, that I'm not > understanding about what it's doing? I don't have this problem with an unmodified version of turtle and Tkinter in Python 2.6. I get: >>> import turtle >>> turtle.TK.Frame >>> turtle.ScrolledCanvas > As a sidenote, I ended up removing the from turtle import * > line from Tkinter which resolved the problem(the example I was using > didn't have a canvas, and I'm pretty sure Tkinter was defaulting > to the ScrolledCanvas). I should say so! Tkinter doesn't have a "from turtle import *" line, as that would set up a circular import dependency. No wonder you have had problems, making random changes to libraries without understanding them. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscri
Re: [Tutor] Class understanding
Che M wrote: Date: Tue, 24 Nov 2009 10:27:05 -0600 From: jammer10...@gmail.com To: tutor@python.org Subject: [Tutor] Class understanding Hi all... Have been attempting to understand classes... Been getting along without them for a while now and feel it's time to jump in What I want to do it start a log with the logging module... I have this working without classes, but want to try... Here is a snippet of the code that I am hacking on: I'm sure the better explainers will jump in presently, but let me try a few tips... class logger(): The convention in Python is to make class names capitalized. It is not necessary, but it is a good habit to get into, so class Logger(). import logging Imports are traditionally done at the top of a Python file, not within a class. logger() This calls the class but doesn't create a name for an instance of the class, so you won't be able to access it later. Instead, try (assuming you rename logger() to Logger() ), logger_instance = Logger() Now you have a name for that instance of the class, and so can access the goodies inside the class. logger.write2log(log_info) So that would now be: logger_instance.write2log(log_info) encouragement, or pointers to good docs would be helpful... I've done a lot of searching via Google on classes, and it's all confusing to me... Keep trying. There have to be tons of good tutorials on classes. They fall under the heading of "Object Oriented Programming". I tend to think of a class as a "container" that has all the stuff you will need to do a certain set of actions. It can contain data (facts) and it can contain methods (functions). You can create one or more "instances" of any class (a traditional example being that Dog() is a class whereas fluffy is an instance of a dog, and therefore has all the traditional dog methods, like bark(), wag(), etc.) CM For my first class, I'd have picked something self-contained, and probably something dumb & simple, so as not to be confused between the stuff in the imports and the problems in understanding how class instances, methods, and attributes work. Anyway, you probably understand the logging module better than I; you certainly couldn't understand less. Also, probably because you used tabs, the current code is heavily indented, and pretty hard to follow. The def line is indented about 26 columns, where I'd expect four. CM has pointed out several important things. In addition, I need to point out that you need a "self" parameter on your method(s). And that if you use the same name for the argument as you used in the parameter, you can get confused as to who is doing what. Also, you want to derive new classes from object, for reasons that probably won't matter now, but when they do, it's easier if you've already got the habit. And finally I don't think you were planning to return an empty tuple. Probably you used syntax from other languages. In Python, to return nothing, use one of three forms: 1) fall off the end of the function/method 2) return with no argument 3) return None So your code would become: import logging class Logger: ... some initialization logic, which I don't know about... def write2log(self, log_msg): print "writing to log", log_msg ... some logging stuff... return inst = Logger() log_info = "This is first msg" inst.write2log(log_info) I'm not sure why this is a class, unless you want to be able to have multiple loggers (instances of Logger). And in that case, you presumably would need another method, the Python constructor, which is called __init__() DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class understanding
> Date: Tue, 24 Nov 2009 10:27:05 -0600 > From: jammer10...@gmail.com > To: tutor@python.org > Subject: [Tutor] Class understanding > > Hi all... Have been attempting to understand classes... Been getting > along without them for a while now and feel it's time to jump in > > What I want to do it start a log with the logging module... I have > this working without classes, but want to try... Here is a snippet of > the code that I am hacking on: I'm sure the better explainers will jump in presently, but let me try a few tips... > class logger(): The convention in Python is to make class names capitalized. It is not necessary, but it is a good habit to get into, so class Logger(). > import logging Imports are traditionally done at the top of a Python file, not within a class. > logger() This calls the class but doesn't create a name for an instance of the class, so you won't be able to access it later. Instead, try (assuming you rename logger() to Logger() ), logger_instance = Logger() Now you have a name for that instance of the class, and so can access the goodies inside the class. > logger.write2log(log_info) So that would now be: logger_instance.write2log(log_info) > encouragement, or pointers to good docs would be helpful... I've done > a lot of searching via Google on classes, and it's all confusing to > me... Keep trying. There have to be tons of good tutorials on classes. They fall under the heading of "Object Oriented Programming". I tend to think of a class as a "container" that has all the stuff you will need to do a certain set of actions. It can contain data (facts) and it can contain methods (functions). You can create one or more "instances" of any class (a traditional example being that Dog() is a class whereas fluffy is an instance of a dog, and therefore has all the traditional dog methods, like bark(), wag(), etc.) CM _ Windows 7: It works the way you want. Learn more. http://www.microsoft.com/Windows/windows-7/default.aspx?ocid=PID24727::T:WLMTAGL:ON:WL:en-US:WWL_WIN_evergreen:112009v2___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
Hello Alan, I see a new way to look at this design so I'm pretty excited to refactor the code. I've also been looking for an example to use 'overloading operators' as the Learn Python book calls it. I think its time to close this discussion because the parameters question has gotten much advice, and this discussion seems to changing to objectness. Thanks, T On Wed, Nov 11, 2009 at 7:19 PM, Alan Gauld wrote: > > "C.T. Matsumoto" wrote > > The Table object you described I find more complicated if each table >> stands >> on its own it is decoupled from its compare partner. I suppose a function >> that pairs the tables, feeding a Table object to its partner Table.compare >> method. >> > > Kind of. > > Think about something simpler. Like numbers. > > when we do > > if number1 == number2: > > what we actually do in Python is > > if number1.__eq__(number2): > > > In other words we call the special method __eq__() of number1 passing > in number2. > > So == is actually a method of the object on the left hand side. > > Similarly if you want to compare tables for equality you can define a class > Table and provide an __eq__() method and you will be able to write > > if table1 == table2 > > and it will work. > > And your __eq__() method can be a completely bespoke algorithm for > determining what equality means for your table class. It could mean that > every value of every field is the same or it could mean that the 3rd field > in number1 is twice the value of the 5th field in number2. Its entirely up > to you. > But the ability to compare two things of the same class is an operation > of the class. > > The same applies to >, <, >=, <= etc. They all have special methods > that you can override to make object comparisons work the way you > want them to. > > > Hmm ... This has got to sink in. >> > > Its quite a big jump from traditional programming but one of the areas > where OOP can dramatically simplify your code. Once you build the > objects to act like the built in types your code that uses those objects > suddenly becomes much more readable > > > -- > 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 > -- Todd Matsumoto ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
On 11/11/2009 10:19 AM Alan Gauld said... what we actually do in Python is if number1.__eq__(number2): In other words we call the special method __eq__() of number1 passing in number2. So == is actually a method of the object on the left hand side. ... and sometimes the right hand side. Consider: >>> class A: ... def __eq__(self,other): ... print 'in A.__eq__' ... return True ... >>> class C: ... pass ... >>> c = C() >>> a == c in A.__eq__ True >>> c == a in A.__eq__ True >>> Emile ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
"C.T. Matsumoto" wrote The Table object you described I find more complicated if each table stands on its own it is decoupled from its compare partner. I suppose a function that pairs the tables, feeding a Table object to its partner Table.compare method. Kind of. Think about something simpler. Like numbers. when we do if number1 == number2: what we actually do in Python is if number1.__eq__(number2): In other words we call the special method __eq__() of number1 passing in number2. So == is actually a method of the object on the left hand side. Similarly if you want to compare tables for equality you can define a class Table and provide an __eq__() method and you will be able to write if table1 == table2 and it will work. And your __eq__() method can be a completely bespoke algorithm for determining what equality means for your table class. It could mean that every value of every field is the same or it could mean that the 3rd field in number1 is twice the value of the 5th field in number2. Its entirely up to you. But the ability to compare two things of the same class is an operation of the class. The same applies to >, <, >=, <= etc. They all have special methods that you can override to make object comparisons work the way you want them to. Hmm ... This has got to sink in. Its quite a big jump from traditional programming but one of the areas where OOP can dramatically simplify your code. Once you build the objects to act like the built in types your code that uses those objects suddenly becomes much more readable -- 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] class initialization with a lot of parameters
Great, I do see my objects working as functions so my OOP understanding needs development. I've got to roll this around to come up with a design which will be more OOP centered and change the code accordingly. To start I could move CompareTableList into DB. This will make a list of tables that need to retrieved. The Table object you described I find more complicated if each table stands on its own it is decoupled from its compare partner. I suppose a function that pairs the tables, feeding a Table object to its partner Table.compare method. Hmm ... This has got to sink in. T On Wed, Nov 11, 2009 at 10:28 AM, Alan Gauld wrote: > "C.T. Matsumoto" wrote > > First I've got a db class >> >> class DB(object): >> """ This does all the database handling. >> """ >> > > That's fine. > > > Then I've got a class to filter a list of potential tables to be compared. >> These tables need to be tested. >> > > OK, Could that be a method of your database? > > > class CompareTableList(DB): >> """ Make a master list, from a source list of compare tables >>that need to be compared. >>If the tables in the list pass the tests make a CompareItem. >>Store all the CompareItems in a compare_list. >> """ >> > > I still think that from an OOP sense it would be m,ore logical to > have a Table cklass that knows hhow to compare itself to another table. > > You are trying to build an object which is a function, thats rarely > a good idea. You wind up with the worst of procedural and OOP > worlds coming together. > > > CompareItem is the class in question. >> >> CompareItem(object): >> def __init__(self, ref_table, ref_dburi, ref_rows, test_table, >> test_dburi, test_rows, keys): >> ... >> ... >> >> This would be your suggested TestTable only it already has the pair and is >> ready to be compared. Rather than a method compare is a class. >> > > I suspect thats your problem. cComparing things is normally an > operation of a class not a class in its own right. A compare class > would need to inspect the internal details of at least 2 objects. > But objects should manage their own data not expose it to third parties. > So either you have to pass in all the object attributes you want to know > about - long parameter lists or you pass in two objects and violate data > hiding within the comparison. > > > Compare(CompareTableList): >> """ Foreach CompareItem in the CompareTableList.compare_list. Workout >>the differences and store difference in something that can format >>a report. >> """ >> > > Again this looks like a method of your database. > > db.compare(tables) >foreach table in tables: > if table.compare(masterTable?): >storeDifferences() > > or > > db.compare(table_sets): >for table1, table2 in table_sets: > if table1.compare(table2) > storeDifferences() > > Or similar. > > By trying to create objects which are functions instead of making > the function a method of the objects that they act on you are > complicating your code. > > > -- > 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 > -- Todd Matsumoto ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
"C.T. Matsumoto" wrote First I've got a db class class DB(object): """ This does all the database handling. """ That's fine. Then I've got a class to filter a list of potential tables to be compared. These tables need to be tested. OK, Could that be a method of your database? class CompareTableList(DB): """ Make a master list, from a source list of compare tables that need to be compared. If the tables in the list pass the tests make a CompareItem. Store all the CompareItems in a compare_list. """ I still think that from an OOP sense it would be m,ore logical to have a Table cklass that knows hhow to compare itself to another table. You are trying to build an object which is a function, thats rarely a good idea. You wind up with the worst of procedural and OOP worlds coming together. CompareItem is the class in question. CompareItem(object): def __init__(self, ref_table, ref_dburi, ref_rows, test_table, test_dburi, test_rows, keys): ... ... This would be your suggested TestTable only it already has the pair and is ready to be compared. Rather than a method compare is a class. I suspect thats your problem. cComparing things is normally an operation of a class not a class in its own right. A compare class would need to inspect the internal details of at least 2 objects. But objects should manage their own data not expose it to third parties. So either you have to pass in all the object attributes you want to know about - long parameter lists or you pass in two objects and violate data hiding within the comparison. Compare(CompareTableList): """ Foreach CompareItem in the CompareTableList.compare_list. Workout the differences and store difference in something that can format a report. """ Again this looks like a method of your database. db.compare(tables) foreach table in tables: if table.compare(masterTable?): storeDifferences() or db.compare(table_sets): for table1, table2 in table_sets: if table1.compare(table2) storeDifferences() Or similar. By trying to create objects which are functions instead of making the function a method of the objects that they act on you are complicating your code. -- 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] class initialization with a lot of parameters
Thanks for the ideas, I see I still don't have the hang of this context thing! I still haven't provided enough context. So here goes again, to show the entire chain. This might change the discussion to be about design practice but it will give overview of how I'm using the class in question. First I've got a db class class DB(object): """ This does all the database handling. """ ... Then I've got a class to filter a list of potential tables to be compared. These tables need to be tested. class CompareTableList(DB): """ Make a master list, from a source list of compare tables that need to be compared. If the tables in the list pass the tests make a CompareItem. Store all the CompareItems in a compare_list. """ ... CompareItem is the class in question. CompareItem(object): def __init__(self, ref_table, ref_dburi, ref_rows, test_table, test_dburi, test_rows, keys): ... ... This would be your suggested TestTable only it already has the pair and is ready to be compared. Rather than a method compare is a class. Compare(CompareTableList): """ Foreach CompareItem in the CompareTableList.compare_list. Workout the differences and store difference in something that can format a report. """ ... Cheers, T On Tue, Nov 10, 2009 at 10:12 PM, Alan Gauld wrote: > > "C.T. Matsumoto" wrote > >> This list provides defines 2 tables that need to be paired and then >> compared. >> > > So two instances of a TestTable object maybe? > > > reference_table_name >> reference_dburi >> reference_rows >> test_table_name >> test_dburi >> test_rows >> keys >> > > Looks like two TestTable objects and a set of keys? > And maybe TestTable has a comparison method that compares one table to > another? Or maybe can index a row based on a key? > Maybe the Rows are objects too and they can compare themselves? > > Lots of possibilities depending on your problem. > > > Just a thought. > > -- > 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 > -- Todd Matsumoto ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
Luke Paireepinart wrote: On Tue, Nov 10, 2009 at 1:21 PM, Dave Angel wrote: (Removing out of sequence history) DaveA instances of that class. Better than using tuples. makes sense to make a class to hold the seven parameters, and pass two If you're passing two sets of 7 parameters to the same function, it probably I'm sorry Dave but I'm not really sure what's going on with this e-mail. Did it get truncated / reordered at some point or am I reading it wrong? Perhaps it was too subtle. I was trying to show what top-posting feels like to me. When the messages are out of order, it takes extra effort to interpret them. So I was doing the same with the lines of my message. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
On Tue, Nov 10, 2009 at 1:21 PM, Dave Angel wrote: > (Removing out of sequence history) > > DaveA > > instances of that class. Better than using tuples. > makes sense to make a class to hold the seven parameters, and pass two > If you're passing two sets of 7 parameters to the same function, it > probably > > I'm sorry Dave but I'm not really sure what's going on with this e-mail. Did it get truncated / reordered at some point or am I reading it wrong? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
"C.T. Matsumoto" wrote This list provides defines 2 tables that need to be paired and then compared. So two instances of a TestTable object maybe? reference_table_name reference_dburi reference_rows test_table_name test_dburi test_rows keys Looks like two TestTable objects and a set of keys? And maybe TestTable has a comparison method that compares one table to another? Or maybe can index a row based on a key? Maybe the Rows are objects too and they can compare themselves? Lots of possibilities depending on your problem. Just a thought. -- 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] class initialization with a lot of parameters
(Removing out of sequence history) DaveA instances of that class. Better than using tuples. makes sense to make a class to hold the seven parameters, and pass two If you're passing two sets of 7 parameters to the same function, it probably ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
C.T. Matsumoto wrote: Hello All, I'm making a class and the parameters I'm feeding the class is getting quite large. I'm up to 8 now. Is there any rules of thumb for classes with a lot of parameters? I was thinking to put the parameters into a tuple and then in the __init__ of the class, iterate over the tuple and assign attributes. Right now my class basically looks like this: class Foo(object): def __init__(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8): ... There are several "tricks": 1. pass a tuple class Foo(object): def __init__(self, args): Foo(("blah", 1, 2, 3)) bad, just adds more parentheses and make argument unpacking more complex, as Dave Angel said, an exception would be if the values are related like coordinates 2. use default value and named argument class Foo(object): def __init__(self, arg0="", arg1=1, arg2=2, arg3=3): Foo("blah") simplifies the caller, but the function signature is a bit complex. You might want to split the signature into lines: def __init__(self, arg0="", arg1=1, arg2=2, arg3=3): 3. use *args and/or **kwargs class Foo(object): def __init__(self, *args): unpacking argument becomes complex 4. your class might be doing too much! Look for ways to split it into several smaller classes ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
This reply is also to Alan's suggestion to provide more context. The situation concerns databases, where in one schema table I've got a 'compare list'. This list provides defines 2 tables that need to be paired and then compared. Before any comparing happens I 'filter' the compare list doing several validation tests. Once all the test succeed (exists, with the necessary things to compare) I'm left with the information describing the 2 tables: reference_table_name reference_dburi reference_rows test_table_name test_dburi test_rows keys It is with this information that I wanted to create a class object. Filling a 'master list' of 'CompareItem' objects. Cheers, T On Tue, Nov 10, 2009 at 1:05 AM, Dave Angel wrote: > C.T. Matsumoto wrote: > >> Hello All, >> >> I'm making a class and the parameters I'm feeding the class is getting >> quite >> large. I'm up >> to 8 now. Is there any rules of thumb for classes with a lot of >> parameters? >> I was thinking >> to put the parameters into a tuple and then in the __init__ of the class, >> iterate over the tuple >> and assign attributes. >> >> >> >> >> > Don't do it. Putting the parameters into a tuple only makes sense if > they're somehow related to each other. And if all the parameters are in the > tuple, all you've done is to add another parenthesis pair around the > argument list. > > Now, if the parameters are related to each other (like the coordinates of > an n-dimensional point), then it makes sense to group them. As Alan said, a > class can be good for that. So can tuples, but only if there's some > connection, or if they already were being treated as a tuple. > > Note that if you want to declare your parameters as a tuple, you can use > the * notation in the parameter list. And if you want to pass the arguments > as a tuple, you can use the * notation in the argument list. Or both. But > you need to have a reason, other than "too many parameters." > > > DaveA > > -- Todd Matsumoto ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
C.T. Matsumoto wrote: Hello All, I'm making a class and the parameters I'm feeding the class is getting quite large. I'm up to 8 now. Is there any rules of thumb for classes with a lot of parameters? I was thinking to put the parameters into a tuple and then in the __init__ of the class, iterate over the tuple and assign attributes. Don't do it. Putting the parameters into a tuple only makes sense if they're somehow related to each other. And if all the parameters are in the tuple, all you've done is to add another parenthesis pair around the argument list. Now, if the parameters are related to each other (like the coordinates of an n-dimensional point), then it makes sense to group them. As Alan said, a class can be good for that. So can tuples, but only if there's some connection, or if they already were being treated as a tuple. Note that if you want to declare your parameters as a tuple, you can use the * notation in the parameter list. And if you want to pass the arguments as a tuple, you can use the * notation in the argument list. Or both. But you need to have a reason, other than "too many parameters." DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class initialization with a lot of parameters
"C.T. Matsumoto" wrote I'm making a class and the parameters I'm feeding the class is getting quite large. I'm up to 8 now. Is there any rules of thumb for classes with a lot of parameters? There are no rules as such. Some of the Tkinter classes for excample take a lot of arguments. But you can usually simplify it by using default values and named parameters. Also can any of the input values be grouped together into an object? OOP means programming with objects, and that includes passing whole objects aropund as arguments. class Foo(object): def __init__(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8): But with only a generic example to guide us we can only offer limited help. -- 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] class Knights vs class Knights(object)
Wayne Werner wrote: and my question is what is the difference between the two? Is there a difference other than one is an object the other is an instance? I googled "python object vs. instance" and didn't find anything terribly useful. Yes there is a difference. One class inherits from object, the other doesn't. You may want to try to check this, e.g.: issubclass(Knight, object) So the first keyword you may want to google for is inheritance. The second keyword is old/new-style classes. Python 2 changed the way how classes work, but to be backward compatible the old mechanism still remained. If you want new style classes inherit from object. If you want to understand the details you may want to look up what metaclasses - your third keyword - are, old-style classes have the metaclass classobj, new-style classes type. You can check this using the builtin type-function. Beware that this is python 2 stuff. In python 3 class X: and class X(object): are the same. - Patrick ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
> > > Vincent Davis wrote: > >> DaveA posted >> import random, functools >> >> class Person: >>def __init__(self, size): >>self.size = size >> >>def __str__(self): >>return "Person of size %s" % self.size >> >> class MakePeople: >>def __init__(self, random_func): >>self.random_func = random_func >> >>def make_them(self, count): >>return [Person(self.random_func()) for i in xrange(count)] >> >> people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) >> persons = people_maker.make_them(100) >> for person in persons: >>print person.size >> >> I changed the last line, from >> print person >> print person.size >> >> So this does what I want, but I am not sure why. >> I read the entry about functools.partial but it was not very clear to me. >> If I >> people_maker = MakePeople(random.gauss(100, 2)) >> then I only get 1 random #. >> and if I >> MakePeople('random.gauss(100, 2)') >> then I just a fix string >> So DaveA uses >> >> functools.partial(random.gauss, 100, 2) >> >> not obvious to me from that it should not be >> >> functools.partial(random.gauss(100, 2)) >> >> and I guess the other key is >> >> Person(self.random_func()) >> >> Also now this >> people_maker = MakePeople(123) >> >> does not work, which is not terrible. >> >> Anyone have some more to add, I would not have confidence in applying this >> to new situations and it seems. >> >> Also I thank DaveA improving my Python conventions. I am really bad about >> that. Is there a cheat sheet for Python conventions. >> >> Like class (Capitals), def (two_words), I guess I should make my own. >> >> Thanks >> Vincent Davis >> 720-301-3003 >> >> >> >> >> > For the official Python style guide, see > http://www.python.org/dev/peps/pep-0008/ > > There are a couple of things going on in my code sample, and I'll try to > elaborate on them. I'm not claiming it's the 'right' answer, just that it > satisfies what I think were the most important goals you had. But if you > want to save the list in the MakePeople() instance, you'd add an additional > parameter to its constructor, and combine the second method into __init__(). > But as someone else points out, at that point, it's then hardly worth > making a class out of it. > > First the tough part. In your original code, your caller was doing: > > > > listofp = makepeople(random.guass(100, 2)) > > But that passes only a single value into the makepeople constructor. If > you're always going to use gaussian, then you can just move the function > call into the make_them() loop. But if you want to do the same thing, but > with a different distribution, you need to pass a function object instead. > Learning about function objects is very useful. You should really play > with them in a simpler situation, to get an idea how they work. > > At its simplest, a function object is just the function name, without > parentheses. You can store it (and pass it as a parameter to another > function) just like any other object. And then when you actually want to > call it, you can use the new name with parentheses, kind of like an alias to > the original function name. > > import math > > def indirection(funcobject, argument): > return funcobject(math.pi/180 * argument) > > print indirection(math.sin, 30) > print indirection(math.cos, 30) > > > Now what happens here? The indirection() function calls an entirely > different function the two times it's called, one time it calls sin, and the > other time it calls cos. As long as all the arguments to the function are > going to be supplied here, there's no confusion. Try the same thing with > any other set of functions, given that all of them take the same number and > types of arguments. > > This opens the door to all sorts of things, such as a mini-calculator > (following is mostly pseudo-code): > > funcname = getnamefrom user() > angleinradians = getnumberfromuser() > > converter_dict = { "sin": math.sin, "cos":math.cos } > print converter_dict[funcname](angleinradians) > > So the values of the dictionary are actual function objects, ready to be > called. > > What happens if some of the function parameters are known to the caller, > and not to the callee? I'll use the random.gauss example again. If we want > the caller to be able to specify them, we could do something like the > following: > > def print_indirection(funcobject, arg1, arg2, count): > for i in xrange(count): > print funcobject(arg1, arg2) > > and call it: > print_indirection(random.gauss, 100, 2, 44) > > to get 44 values with a gaussian distributon. But now suppose we wanted to > be able to use the same function with random.getrandbits() ? That function > only takes a single parameter, so the print funcobject() would blow up. > > functools.partial lets us bind a function object with some or all of its > arguments already attached. So in our case, the caller (who knows what the > arguments look like) gets to lay them out,
Re: [Tutor] class attribute to initiate more classes
(You top-posted, which confuses the sequence of message text. So I clipped it off and posted my message at the bottom, which is the convention on this newsgroup) Vincent Davis wrote: DaveA posted import random, functools class Person: def __init__(self, size): self.size = size def __str__(self): return "Person of size %s" % self.size class MakePeople: def __init__(self, random_func): self.random_func = random_func def make_them(self, count): return [Person(self.random_func()) for i in xrange(count)] people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) persons = people_maker.make_them(100) for person in persons: print person.size I changed the last line, from print person print person.size So this does what I want, but I am not sure why. I read the entry about functools.partial but it was not very clear to me. If I people_maker = MakePeople(random.gauss(100, 2)) then I only get 1 random #. and if I MakePeople('random.gauss(100, 2)') then I just a fix string So DaveA uses functools.partial(random.gauss, 100, 2) not obvious to me from that it should not be functools.partial(random.gauss(100, 2)) and I guess the other key is Person(self.random_func()) Also now this people_maker = MakePeople(123) does not work, which is not terrible. Anyone have some more to add, I would not have confidence in applying this to new situations and it seems. Also I thank DaveA improving my Python conventions. I am really bad about that. Is there a cheat sheet for Python conventions. Like class (Capitals), def (two_words), I guess I should make my own. Thanks Vincent Davis 720-301-3003 For the official Python style guide, see http://www.python.org/dev/peps/pep-0008/ There are a couple of things going on in my code sample, and I'll try to elaborate on them. I'm not claiming it's the 'right' answer, just that it satisfies what I think were the most important goals you had. But if you want to save the list in the MakePeople() instance, you'd add an additional parameter to its constructor, and combine the second method into __init__(). But as someone else points out, at that point, it's then hardly worth making a class out of it. First the tough part. In your original code, your caller was doing: listofp = makepeople(random.guass(100, 2)) But that passes only a single value into the makepeople constructor. If you're always going to use gaussian, then you can just move the function call into the make_them() loop. But if you want to do the same thing, but with a different distribution, you need to pass a function object instead. Learning about function objects is very useful. You should really play with them in a simpler situation, to get an idea how they work. At its simplest, a function object is just the function name, without parentheses. You can store it (and pass it as a parameter to another function) just like any other object. And then when you actually want to call it, you can use the new name with parentheses, kind of like an alias to the original function name. import math def indirection(funcobject, argument): return funcobject(math.pi/180 * argument) print indirection(math.sin, 30) print indirection(math.cos, 30) Now what happens here? The indirection() function calls an entirely different function the two times it's called, one time it calls sin, and the other time it calls cos. As long as all the arguments to the function are going to be supplied here, there's no confusion. Try the same thing with any other set of functions, given that all of them take the same number and types of arguments. This opens the door to all sorts of things, such as a mini-calculator (following is mostly pseudo-code): funcname = getnamefrom user() angleinradians = getnumberfromuser() converter_dict = { "sin": math.sin, "cos":math.cos } print converter_dict[funcname](angleinradians) So the values of the dictionary are actual function objects, ready to be called. What happens if some of the function parameters are known to the caller, and not to the callee? I'll use the random.gauss example again. If we want the caller to be able to specify them, we could do something like the following: def print_indirection(funcobject, arg1, arg2, count): for i in xrange(count): print funcobject(arg1, arg2) and call it: print_indirection(random.gauss, 100, 2, 44) to get 44 values with a gaussian distributon. But now suppose we wanted to be able to use the same function with random.getrandbits() ? That function only takes a single parameter, so the print funcobject() would blow up. functools.partial lets us bind a function object with some or all of its arguments already attached. So in our case, the caller (who knows what the arguments look like) gets to lay them out, without being stuck with any particular ones. So, we rewrite print_indirection something like thi
Re: [Tutor] class attribute to initiate more classes
DaveA posted import random, functools class Person: def __init__(self, size): self.size = size def __str__(self): return "Person of size %s" % self.size class MakePeople: def __init__(self, random_func): self.random_func = random_func def make_them(self, count): return [Person(self.random_func()) for i in xrange(count)] people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) persons = people_maker.make_them(100) for person in persons: print person.size I changed the last line, from print person print person.size So this does what I want, but I am not sure why. I read the entry about functools.partial but it was not very clear to me. If I people_maker = MakePeople(random.gauss(100, 2)) then I only get 1 random #. and if I MakePeople('random.gauss(100, 2)') then I just a fix string So DaveA uses functools.partial(random.gauss, 100, 2) not obvious to me from that it should not be functools.partial(random.gauss(100, 2)) and I guess the other key is Person(self.random_func()) Also now this people_maker = MakePeople(123) does not work, which is not terrible. Anyone have some more to add, I would not have confidence in applying this to new situations and it seems. Also I thank DaveA improving my Python conventions. I am really bad about that. Is there a cheat sheet for Python conventions. Like class (Capitals), def (two_words), I guess I should make my own. Thanks Vincent Davis 720-301-3003 On Sat, Oct 31, 2009 at 5:55 AM, Dave Angel wrote: > Vincent Davis wrote: > >> I have a program that generates many instances of a class with an >> attribute >> self.x = random.gauss(10, 2). So each instance has a different value for >> self.x. This is what I want. Now I want to make a class that starts my >> program and sets the attributes. >> class people: >>def __init__(self, size) >>self.size = size >> >> class makepeople: >>def __init__(self, randomsize) >>self.rsize = randomsize >>self.allpeople = [] >>def makethem(): >>for x in range(1,100): >>p+str(x) = people(self.rsize) >>allpeople.append(p+str(x)) >> >> so what I would like to have work is set the attribute of makepeople so >> that >> when it is used to make instances of people each will have a different >> size. >> >> listofp = makepeople(random.guass(100, 2)) >> listofp.makethem() >> >> I would then what listofp.allpeople to be a list of people with different >> sizes. The above code does not work, I don't think it does anyway. >> >> I hope this makes sense, I am sure there is a term for what I am trying to >> do but I don't know it. >> >> Thanks >> Vincent Davis >> >> >> > You're trying to do several things here, and I'm unclear on many of the > details. So here's a new spec, and the implementation for it. > > We want a factory class, which can be given a particular distribution > function and parameters, and using those parameters generate a list of > Person objects, whose heights are distributed according to that random > function. There might be duplicates in that list, but they'd be random > coincidence, and the list as a whole would be as random as the function > specified by the caller. > > I also took a few liberties on the names of things, trying to use Python > conventions for naming, and things like using a singular word for a > classname of a single item. And I removed the allpeople attribute, as the > class only makes sense to me if you can use its instance multiple times, to > generate more items with the same given distribution. > > > CODE > import random, functools > > class Person: > > def __init__(self, size): > self.size = size > def __str__(self): > return "Person of size %s" % self.size > > class MakePeople: > def __init__(self, random_func): > self.random_func = random_func > > def make_them(self, count): > return [Person(self.random_func()) for i in xrange(count)] > > > people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) > persons = people_maker.make_them(100) > for person in persons: > print person > > /CODE--- > > DaveA > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
On Sat, Oct 31, 2009 at 1:01 AM, Vincent Davis wrote: > I have a program that generates many instances of a class with an attribute > self.x = random.gauss(10, 2). So each instance has a different value for > self.x. This is what I want. Now I want to make a class that starts my > program and sets the attributes. > class people: > def __init__(self, size) > self.size = size > class makepeople: > def __init__(self, randomsize) > self.rsize = randomsize > self.allpeople = [] > def makethem(): > for x in range(1,100): > p+str(x) = people(self.rsize) > allpeople.append(p+str(x)) > so what I would like to have work is set the attribute of makepeople so that > when it is used to make instances of people each will have a different size. > listofp = makepeople(random.guass(100, 2)) Here you are calling makepeople() and passing it a single random number that will be used for all people. You need to call random.gauss() in the loop. > listofp.makethem() > I would then what listofp.allpeople to be a list of people with different > sizes. The above code does not work, I don't think it does anyway. > I hope this makes sense, I am sure there is a term for what I am trying to > do but I don't know it. I would just make a function that creates the list of people. There is no need to put it in a class. For example, def make_people(): return [people(random.gauss(100,2)) for x in range(1, 100)] # Note this only makes 99 people Kent ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
Vincent Davis wrote: I have a program that generates many instances of a class with an attribute self.x = random.gauss(10, 2). So each instance has a different value for self.x. This is what I want. Now I want to make a class that starts my program and sets the attributes. class people: def __init__(self, size) self.size = size class makepeople: def __init__(self, randomsize) self.rsize = randomsize self.allpeople = [] def makethem(): for x in range(1,100): p+str(x) = people(self.rsize) allpeople.append(p+str(x)) so what I would like to have work is set the attribute of makepeople so that when it is used to make instances of people each will have a different size. listofp = makepeople(random.guass(100, 2)) listofp.makethem() I would then what listofp.allpeople to be a list of people with different sizes. The above code does not work, I don't think it does anyway. I hope this makes sense, I am sure there is a term for what I am trying to do but I don't know it. Thanks Vincent Davis You're trying to do several things here, and I'm unclear on many of the details. So here's a new spec, and the implementation for it. We want a factory class, which can be given a particular distribution function and parameters, and using those parameters generate a list of Person objects, whose heights are distributed according to that random function. There might be duplicates in that list, but they'd be random coincidence, and the list as a whole would be as random as the function specified by the caller. I also took a few liberties on the names of things, trying to use Python conventions for naming, and things like using a singular word for a classname of a single item. And I removed the allpeople attribute, as the class only makes sense to me if you can use its instance multiple times, to generate more items with the same given distribution. CODE import random, functools class Person: def __init__(self, size): self.size = size def __str__(self): return "Person of size %s" % self.size class MakePeople: def __init__(self, random_func): self.random_func = random_func def make_them(self, count): return [Person(self.random_func()) for i in xrange(count)] people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) persons = people_maker.make_them(100) for person in persons: print person /CODE--- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
On 31 Oct 2009, at 06:01 , Vincent Davis wrote: I hope this makes sense, I am sure there is a term for what I am trying to do but I don't know it. What a strange program. But at least it compiles: import random class people: def __init__(self, size): self.size = size class makepeople: def __init__(self, randomsize): self.rsize = randomsize self.allpeople = [] def makethem(self): for x in range(self.rsize): self.allpeople.append(people(self.rsize)) listofp = makepeople(int(random.gauss(100, 2))) listofp.makethem() ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class with objects
wrote I want to display the ship default value for zero and display the ship's initial fuel level. Also have a method called status that displays an object's name and fuel values. So far so good. I want to have several Ship objects and call their status() methods to test various aspects of the class constructor. Now I'm confused. Does status "test various aspects of the class constructor" or does it "display an objects name and fuel values"? These are not the same thing... Here's my code: class Ship(object): """A spaceship""" total = 0 def __init__(self, name, fuel = 0): print "My spaceship has arrived! The",name self.name = name self.fuel = fuel print "My fuel level is", fuel def status(): Ship.total += 1 What is the puropse of thoe above line? Why is it part of status()? print "The total number of objects is", Ship.total status = staticmethod(status) And why is it a staticmethod? ship = Ship("Galaxia") print "\nCreating objects." ship1 = Ship("object 1") ship2 = Ship("object 2") ship3 = Ship("object 3") Ship.status() What do you expect the output to be? And what is it really? Are they different? Why? 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] class with objects
On Sun, Oct 11, 2009 at 2:42 PM, shellc...@juno.com wrote: > I want to display the ship default value for zero and display the ship's > initial fuel level. Also have a method called status that displays an > object's name and fuel values. I want to have several Ship objects and call > their status() methods to test various aspects of the class constructor. > And what problems have you run into? What would you like from us? This sounds vaguely like homework which we don't do here. We are, however, more than happy to offer pointers in the right direction if you get stuck. For an explanation of /how/ to ask a good question, check out this: http://catb.org/~esr/faqs/smart-questions.html#examples HTH, Wayne > > Here's my code: > > class Ship(object): >"""A spaceship""" >total = 0 >def __init__(self, name, fuel = 0): > >print "My spaceship has arrived! The",name >self.name = name >self.fuel = fuel > >print "My fuel level is", fuel > >def status(): >Ship.total += 1 >print "The total number of objects is", Ship.total >status = staticmethod(status) > > #main > ship = Ship("Galaxia") > > print "\nCreating objects." > ship1 = Ship("object 1") > ship2 = Ship("object 2") > ship3 = Ship("object 3") > Ship.status() > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
> In simple terms I was trying to create a 'folder with a view' which > displays all the data it contains on one page, rather than having to > view each node individually. In that case I'd probably create a FolderView class with a show or display method. If you want to do something with the contents then I'd have a Folder object and associate each FolderView with its Folder -0 which is what Kent recommended in another post. But I'd expect the Folder to be doing more than simply returning the items in the Folder, I'd expect you to be doing something with it - moving it, copying it, deleting it etc. ie Actually manipulating the Folder itself in some way. Otherwise the View can fetch and display the contents itself using standard OS functions. HTH, Alan G. http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
On Sat, Jun 6, 2009 at 10:43 AM, Norman Khine wrote: > http://docs.hforge.org/itools/web.html although this is for the newer > version, in my case i am maintaining an older version. >From that page it seems that itools does as I suggest. They claim to follow the Model-View-Controller pattern which separates the model and view. The View classes are responsible for display of data but not for the contents. It's not clear from the examples where the model fits in but it is distinct from the view. Kent > On Sat, Jun 6, 2009 at 3:24 PM, Kent Johnson wrote: >> On Sat, Jun 6, 2009 at 8:26 AM, Norman Khine wrote: >> You probably don't want the view code in the same class with the data. It's generally a good idea to separate the model - the representation of data - from the view - the display of the data. >>> >>> In iTools, each class has a view, edit, state etc... functions >>> depending on the class. >> >> Can you point to an example in the itools docs? ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
http://docs.hforge.org/itools/web.html although this is for the newer version, in my case i am maintaining an older version. On Sat, Jun 6, 2009 at 3:24 PM, Kent Johnson wrote: > On Sat, Jun 6, 2009 at 8:26 AM, Norman Khine wrote: > >>> You probably don't want the view code in the same class with the data. >>> It's generally a good idea to separate the model - the representation >>> of data - from the view - the display of the data. >> >> In iTools, each class has a view, edit, state etc... functions >> depending on the class. > > Can you point to an example in the itools docs? I don't see this > usage. There are a some of disadvantages to this design. > - it ties the data model to a specific view technology, whether text, > Tkinter, HTML, or whatever > - it makes it more difficult to have multiple views, for example > summary and detail views, or admin edit vs user edit > > I only couple a model class to a representation of the model when they > are very tightly linked, for example in serialization. User views > should be decoupled from the model. > > Kent > ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
On Sat, Jun 6, 2009 at 8:26 AM, Norman Khine wrote: >> You probably don't want the view code in the same class with the data. >> It's generally a good idea to separate the model - the representation >> of data - from the view - the display of the data. > > In iTools, each class has a view, edit, state etc... functions > depending on the class. Can you point to an example in the itools docs? I don't see this usage. There are a some of disadvantages to this design. - it ties the data model to a specific view technology, whether text, Tkinter, HTML, or whatever - it makes it more difficult to have multiple views, for example summary and detail views, or admin edit vs user edit I only couple a model class to a representation of the model when they are very tightly linked, for example in serialization. User views should be decoupled from the model. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
Hi On Sat, Jun 6, 2009 at 2:38 PM, Alan Gauld wrote: > > "Norman Khine" wrote > >> In my application I have 3 folders each containing images, something like: >> >> $ tree -L 3 /database/companies/company/ >> |-- product >> | |-- itinerary >> | | |-- img1.gif >> | | |-- img1.gif.metadata >> | | |-- day1 >> | | | |-- img2.gif >> | | | `-- img2.gif.metadata >> | | |-- day1.metadata >> >> where I have the Product, Itinerary and Day folders, each containing >> images and other files. >> >> Here is what I have so far that works, but I am looking for better >> solution. > > When you say it "works" I'm not sure what it is you are trying to do? > It seems that kmostly the classes are just containers representing > the file structure and mostly you could accomplish the same, more > simply, with os.walk? > > Do the classes actually do anything? What exactly do you do with > a Product object? What is it for? Can you fill in a (virtual) CRC card > for each class? I will do this and see if I can improve the design. > > Until we know what the cklasses are for its hard to know what you > want improved... Each class is an object containing elements from generated from data based on the current .metadata file, it's contents plus any data which is within the 'folder' In simple terms I was trying to create a 'folder with a view' which displays all the data it contains on one page, rather than having to view each node individually. Thanks > > -- > Alan Gauld > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > > ___ > Tutor maillist - tu...@python.org > http://mail.python.org/mailman/listinfo/tutor > ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
"Norman Khine" wrote In my application I have 3 folders each containing images, something like: $ tree -L 3 /database/companies/company/ |-- product | |-- itinerary | | |-- img1.gif | | |-- img1.gif.metadata | | |-- day1 | | | |-- img2.gif | | | `-- img2.gif.metadata | | |-- day1.metadata where I have the Product, Itinerary and Day folders, each containing images and other files. Here is what I have so far that works, but I am looking for better solution. When you say it "works" I'm not sure what it is you are trying to do? It seems that kmostly the classes are just containers representing the file structure and mostly you could accomplish the same, more simply, with os.walk? Do the classes actually do anything? What exactly do you do with a Product object? What is it for? Can you fill in a (virtual) CRC card for each class? Until we know what the cklasses are for its hard to know what you want improved... -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
Thanks for the reply. I am using the iTools python library from http://hforge.org (http://git.hforge.org/) and the data is stored as XML files. On Sat, Jun 6, 2009 at 1:02 PM, Kent Johnson wrote: > On Sat, Jun 6, 2009 at 5:04 AM, Norman Khine wrote: >> Hello, >> I would like help to design the following: >> http://paste.lisp.org/display/81448 > > Product.get_days() may have a bug, it only returns the first container it > finds. It was an error when I simplified the code for posting on the list. > > You probably don't want the view code in the same class with the data. > It's generally a good idea to separate the model - the representation > of data - from the view - the display of the data. In iTools, each class has a view, edit, state etc... functions depending on the class. > > The get_images() methods are all very similar. If each class had a > get_children() method then you could combine the get_images(). For > example Here is what I wanted to improve on, I will try to combine this as suggested. > > class Product(Folder): > ... > def get_children(self): > children = [ self ] > children.extend(self.get_itinerary()) > children.extend(self.get_days()) > > class Folder(object): > def get_images(self): > images = [] > for child in self.get_children(): > images.extend(child.search_handlers(handler_class=File)) > return images > > You might be able to do something similar with get_days(). > > I wonder why you are not using a database to store all this? I can't > help wondering what the code would look like in Django. > > Kent > Thank you for your feedback Norman ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design
On Sat, Jun 6, 2009 at 5:04 AM, Norman Khine wrote: > Hello, > I would like help to design the following: > http://paste.lisp.org/display/81448 Product.get_days() may have a bug, it only returns the first container it finds. You probably don't want the view code in the same class with the data. It's generally a good idea to separate the model - the representation of data - from the view - the display of the data. The get_images() methods are all very similar. If each class had a get_children() method then you could combine the get_images(). For example class Product(Folder): ... def get_children(self): children = [ self ] children.extend(self.get_itinerary()) children.extend(self.get_days()) class Folder(object): def get_images(self): images = [] for child in self.get_children(): images.extend(child.search_handlers(handler_class=File)) return images You might be able to do something similar with get_days(). I wonder why you are not using a database to store all this? I can't help wondering what the code would look like in Django. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Tips
"David" wrote OK, this is what I came up with, how else could I do it so as not to use sys.exit() ? You don;t need the exit(), The program will just drop off the end silently without it. Thre are several other redundant bits you could just miss out: class FertRate: def __init__(self, rate, nitrogen, acre, bag): self.area = 43.560 self.app = rate / (nitrogen / 100.00) self.acre = acre self.bag = bag def result(self): result = self.app * self.area * self.acre / self.bag return result leave out the variable and just return the calculated value: return self.app * self.area * self.acre / self.bag def main(): while True: try: frate = FertRate( *get_inputs() ) result = frate.result() print 'You should apply %0.2f bags.' % result And here miss the variable and use the functin in the format string: print 'You should apply %0.2f bags.' % frate.result() exit() And just delete this. except TypeError, UnboundLocalError: pass def get_inputs(): try: print 'Rate: Pounds nitrogen per 1000 (square feet)' rate = float(raw_input('Enter Rate i.e., (0.5): ')) print "Nitrogen: The first number of the fertilizer's analysis" nitrogen = float(raw_input('Enter Nitrogen From Bag i.e., (14): ')) acre = int(raw_input("Enter Total Acre's To Be Treated i.e, (3): ")) bag = int(raw_input('Enter Bag Weight (lb): i.e., (50) ')) return rate, nitrogen, acre, bag except ValueError: print 'Invalid input!' print 'You must enter a number!' You could put the whole thing in a while loop so the error gets printed but the user has a chance to corect it. def get_inputs(): while True: try: # blah blah return . # breaks from the while loop except ValueError, TypeError: print blah HTH, -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Tips
W W wrote: One thing that's probably not in the scope of the program but really usually a good idea is error checking. i.e. this line: rate = float(raw_input("Enter rate i.e. (0.5) : ")) could be converted to something like: try: rate = float(raw_input("Enter rate...")) except ValueError: print "Invalid input" #Quit or loop until valid input is entered. HTH, Wayne OK, this is what I came up with, how else could I do it so as not to use sys.exit() ? #!/usr/bin/python """Determine the number of bags to use to fertilize a given area given the application rate.""" from sys import exit class FertRate: def __init__(self, rate, nitrogen, acre, bag): self.area = 43.560 self.app = rate / (nitrogen / 100.00) self.acre = acre self.bag = bag def result(self): result = self.app * self.area * self.acre / self.bag return result def main(): while True: try: frate = FertRate( *get_inputs() ) result = frate.result() print 'You should apply %0.2f bags.' % result exit() except TypeError, UnboundLocalError: pass def get_inputs(): try: print 'Rate: Pounds nitrogen per 1000 (square feet)' rate = float(raw_input('Enter Rate i.e., (0.5): ')) print "Nitrogen: The first number of the fertilizer's analysis" nitrogen = float(raw_input('Enter Nitrogen From Bag i.e., (14): ')) acre = int(raw_input("Enter Total Acre's To Be Treated i.e, (3): ")) bag = int(raw_input('Enter Bag Weight (lb): i.e., (50) ')) return rate, nitrogen, acre, bag except ValueError: print 'Invalid input!' print 'You must enter a number!' if __name__ == "__main__": main() -- Powered by Gentoo GNU/Linux http://linuxcrazy.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Tips
ALAN GAULD wrote: but I get an error here; def main(): frate = FertRate(get_inputs()) File "./fert_class.py", line 15, in main frate = FertRate(get_inputs()) TypeError: __init__() takes exactly 5 arguments (2 given) Sorry my mistake. Because get_inputs() returns a tuple you have to tell the function to unpack it by placing an asterisk in front of the function call: frate = FerrtRate( *get_inputs() ) That should work now. Alan G. Super, I had seen that in other programs and now I know why. I have used; def c(*args, **kwargs): My understanding is 'args' is a tuple with all the positional arguments, kwargs is a dictionary with all the named arguments. -- Powered by Gentoo GNU/Linux http://linuxcrazy.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Tips
On Sat, May 30, 2009 at 8:20 PM, David wrote: > > Alan Gauld wrote: >> >> "David" wrote >> >>> I took this program that determines a fertilizer application rate; >>> ... >>> And converted it to class/object to learn how they work. Just looking for some pointers, if I did it correctly etc. >>> >>> One thing that's probably not in the scope of the program but really usually a good idea is error checking. i.e. this line: rate = float(raw_input("Enter rate i.e. (0.5) : ")) could be converted to something like: try: rate = float(raw_input("Enter rate...")) except ValueError: print "Invalid input" #Quit or loop until valid input is entered. HTH, Wayne ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Tips
Alan Gauld wrote: "David" wrote I took this program that determines a fertilizer application rate; ... And converted it to class/object to learn how they work. Just looking for some pointers, if I did it correctly etc. For such a small program its hard to see what else you could have done. Technically itys not too bad, I've made a couple of suggestions below. However, leaving the fact that its an excercise I'd say that really this is just a function rather than a class. class FertRate: def __init__(self, rate, nitrogen, acre, bag): self.area = 43.560 self.app = rate / (nitrogen / 100.00) self.acre = acre self.bag = bag def result(self): result = self.app * self.area * self.acre / self.bag print 'You should apply %0.2f bags.' % result Its never a good idea to include printing in the same function as calculation. IT would be better to have two functions one to calculate and one to generate the printable output. (The actual printing is best done outside the class altogether, it improves the reusability. For example prints don't work in a GUI but a formatted string can be used. But even if you keep it as one function at lest return the result as a string rather than print it def main(): rate, nitrogen, acre, bag = get_inputs() frate = FertRate(rate, nitrogen, acre, bag) This could have just been: frate = FertRate( get_inputs() ) which saves the need for the variables. frate.result() So if you took my advice about returning a string this becomes print frate.result() But as I say you could just have made FertRate a function: print FertRate( get_inputs() ) and it would have been just as effective, classes really only start to be useful on slightly larger programs than this. But as an example of using a class its nearly OK, just the tweak of the return value to think about - and that applies to the function version too! Thanks Alan, this works; def main(): rate, nitrogen, acre, bag = get_inputs() frate = FertRate(rate, nitrogen, acre, bag) result = frate.result() print 'You should apply %0.2f bags.' % result but I get an error here; def main(): frate = FertRate(get_inputs()) result = frate.result() print 'You should apply %0.2f bags.' % result Traceback (most recent call last): File "./fert_class.py", line 26, in main() File "./fert_class.py", line 15, in main frate = FertRate(get_inputs()) TypeError: __init__() takes exactly 5 arguments (2 given) -- Powered by Gentoo GNU/Linux http://linuxcrazy.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Tips
"David" wrote I took this program that determines a fertilizer application rate; ... And converted it to class/object to learn how they work. Just looking for some pointers, if I did it correctly etc. For such a small program its hard to see what else you could have done. Technically itys not too bad, I've made a couple of suggestions below. However, leaving the fact that its an excercise I'd say that really this is just a function rather than a class. class FertRate: def __init__(self, rate, nitrogen, acre, bag): self.area = 43.560 self.app = rate / (nitrogen / 100.00) self.acre = acre self.bag = bag def result(self): result = self.app * self.area * self.acre / self.bag print 'You should apply %0.2f bags.' % result Its never a good idea to include printing in the same function as calculation. IT would be better to have two functions one to calculate and one to generate the printable output. (The actual printing is best done outside the class altogether, it improves the reusability. For example prints don't work in a GUI but a formatted string can be used. But even if you keep it as one function at lest return the result as a string rather than print it def main(): rate, nitrogen, acre, bag = get_inputs() frate = FertRate(rate, nitrogen, acre, bag) This could have just been: frate = FertRate( get_inputs() ) which saves the need for the variables. frate.result() So if you took my advice about returning a string this becomes print frate.result() But as I say you could just have made FertRate a function: print FertRate( get_inputs() ) and it would have been just as effective, classes really only start to be useful on slightly larger programs than this. But as an example of using a class its nearly OK, just the tweak of the return value to think about - and that applies to the function version too! -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition...
>> I am looking for a good tutorial to walk through that really explains class >> definition. > > I assume from that you have been through the basic tutors like mine? >: > OK, I explain self in my OOP tutor topic ( a sub heading under > "Using Classes"), but again if thats not sufficient then you probably > need to give us explicit examples of what you don't understand and > your concerns. similarly, i go through a deep and comprehensive treatment of all aspects of object-oriented programming in Python, from the highest-level intro all the way through metaclasses in the OOP chapter (13) of Core Python (see below). when you're beyond alan's great tutorial as well as mark's dive, i hope you'll find Core Python a useful resource to putting it all together. best of luck! -- wesley - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "Core Python Programming", Prentice Hall, (c)2007,2001 "Python Fundamentals", Prentice Hall, (c)2009 http://corepython.com wesley.j.chun :: wescpy-at-gmail.com python training and technical consulting cyberweb.consulting : silicon valley, ca http://cyberwebconsulting.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class instance understanding = None
David wrote: but when I change it to; start_total() start = start_total() a = Account(start) here is the error; Enter Amount: 100 Traceback (most recent call last): File "./py_pettycash.py", line 77, in menu() File "./py_pettycash.py", line 53, in menu a.deposit(cash) File "./py_pettycash.py", line 15, in deposit self.balance = self.balance + amt TypeError: unsupported operand type(s) for +: 'NoneType' and 'Decimal' -david Ok I got it, same problem I had before no return :) def start_total(): fname = open("cash.dat", "r") contents = cPickle.Unpickler(fname) data = contents.load() print "The current balance is", data fname.close() return data start = start_total() a = Account(start) Thanks all, any other comments?, I am going to add some error checking but, I am so happy, woopee -david -- Powered by Gentoo GNU/LINUX http://www.linuxcrazy.com pgp.mit.edu ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class instance understanding = None
Andre Engels wrote: The more preferable method is to leave the class alone, and call getbalance by hand: data = float('100.00') a = Account(data) p = a.getbalance() print 'balance = ', p remove_data = float('50.00') a.withdraw(remove_data) w = a.getbalance() print "withdraw = ", w add_data = float('50.00') a.deposit(add_data) add = a.getbalance() print "deposit = ", add Some other things: 1. data = float('100.00') is unnecessarily clumsy - you can specify floats directly without creating a string first by doing data = 100.0 2. You are creating a lot of variables only to use them for the one and only time on the next line. That's not necessarily bad, it sometimes improves readability especially if a lot is being done (which can then be split up in more readable parts), but doing it this much mostly causes your coding to look more complicated than it actually is. I would either prefer something like this: data = 100.0 remove_data = 50.0 add_data = 50.0# first all input-like elements, so I know where to go when I want to change something trivial a = Account(data) print 'balance = ',a.getbalance() a.withdraw(remove_data) print 'balance after withdraw = ',a.getbalance() a.deposit(add_data) print 'balance after deposit = ',a.getbalance() doing away with p, w and add, or the even shorter variant where data, remove_data and add_data are also removed: a = Account(100.0) print 'balance = ',a.getbalance() a.withdraw(50.0) print 'balance after withdraw = ',a.getbalance() a.deposit(50.0) print 'balance after deposit = ',a.getbalance() Ok almost there, here is what i have now; http://linuxcrazy.pastebin.com/m6b090d2d My problem now is the balance is updated from the file that is pickled fine, but the first entry goes is not added to that total. I know it is in this part; start_total() start = 0 a = Account(start) but when I change it to; start_total() start = start_total() a = Account(start) here is the error; Enter Amount: 100 Traceback (most recent call last): File "./py_pettycash.py", line 77, in menu() File "./py_pettycash.py", line 53, in menu a.deposit(cash) File "./py_pettycash.py", line 15, in deposit self.balance = self.balance + amt TypeError: unsupported operand type(s) for +: 'NoneType' and 'Decimal' -david -- Powered by Gentoo GNU/LINUX http://www.linuxcrazy.com pgp.mit.edu ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition...
Your tutorial is awesome...thanks again... The biggest confusion I have just had is the self.balance kind of thing. I need to just remember how it is treating each individual statement is all. Remember how everything is basically an object...just wrapping my brain around it for the most part. On Thu, Feb 26, 2009 at 11:42 AM, Alan Gauld wrote: > > "Spencer Parker" wrote > > I am looking for a good tutorial to walk through that really explains >> class >> definition. This has been one sticking point that always messes me up >> > > I assume from that you have been through the basic tutors like mine? > > Have you tried the deeper material in Dive into Python and the official > tutorial? > > If so then it is probnably better for you to give us some specific > questions you have. Or post a bit of a tutorialyou don't understand > and we can collectively try to clarify it. Specific questions are always > easier to answer than generalities. > > the most part. That and when people use "self". For some reason I just >> can't grasp what people say. Any good pointers to throw at me? >> > > OK, I explain self in my OOP tutor topic ( a sub heading under > "Using Classes"), but again if thats not sufficient then you probably > need to give us explicit examples of what you don't understand and > your concerns. > > HTH, > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > > ___ > 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] Class instance understanding = None
Thank you spir and Andre for the explanation. You are very good teachers. I can now continue. I am sure I will be back. Next I am going to set up a menu to enter amounts and also a way to store the resulting balance. Is cPickle a good way to do this? -david -- Powered by Gentoo GNU/LINUX http://www.linuxcrazy.com pgp.mit.edu ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class instance understanding = None
Thank you spir and Andre for the explanation. You are very good teachers. I can now continue. I am sure I will be back. Next I am going to set up a menu to enter amounts and also a way to store the resulting balance. Is cPickle a good way to do this? -david -- Powered by Gentoo GNU/LINUX http://www.linuxcrazy.com pgp.mit.edu ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class instance understanding = None
On Fri, Feb 27, 2009 at 6:06 AM, David wrote: > Hi Everyone, > I go through the archived [Tutor] mail list to find programs others have > tried to do. I found one that would keep track of a petty cash fund. please > point out my misunderstanding. > Here is what I started with; > > #!/usr/bin/python > > from reportlab.lib.normalDate import ND > #import cPickle as p > #import pprint > > today = ND() > > class Account: > def __init__(self, initial): > self.balance = initial > def deposit(self, amt): > self.balance = self.balance + amt > def withdraw(self, amt): > self.balance = self.balance - amt > def getbalance(self): > return self.balance > print 'The current date is: ', today.formatUS() > > > data = float('100.00') > a = Account(data) > p = a.getbalance() > print 'balance = ', p > remove_data = float('50.00') > w = a.withdraw(remove_data) > print "withdraw = ", w > add_data = float('50.00') > add = a.deposit(add_data) > print "deposit = ", add > > > results; > The current date is: 02/27/09 > balance = 100.0 > withdraw = None > deposit = None > > expected results; > The current date is: 02/27/09 > balance = 100.0 > withdraw = 50.0 > deposit = 100.0 A method only returns a value if you do so explicitly, that is, end it with return value That's what happens in getbalance: return self.balance deposit and withdraw however do not return a value. If, like you do, you still try to extract their return value, it gives None. There are two ways to resolve this. The first gets closer to what you are trying to do, but is considered less proper programming, because it mixes functions of methods. In it, you add the returns to the methods: class Account: def __init__(self, initial): self.balance = initial def deposit(self, amt): self.balance = self.balance + amt return self.balance def withdraw(self, amt): self.balance = self.balance - amt return self.balance def getbalance(self): return self.balance The more preferable method is to leave the class alone, and call getbalance by hand: data = float('100.00') a = Account(data) p = a.getbalance() print 'balance = ', p remove_data = float('50.00') a.withdraw(remove_data) w = a.getbalance() print "withdraw = ", w add_data = float('50.00') a.deposit(add_data) add = a.getbalance() print "deposit = ", add Some other things: 1. data = float('100.00') is unnecessarily clumsy - you can specify floats directly without creating a string first by doing data = 100.0 2. You are creating a lot of variables only to use them for the one and only time on the next line. That's not necessarily bad, it sometimes improves readability especially if a lot is being done (which can then be split up in more readable parts), but doing it this much mostly causes your coding to look more complicated than it actually is. I would either prefer something like this: data = 100.0 remove_data = 50.0 add_data = 50.0 # first all input-like elements, so I know where to go when I want to change something trivial a = Account(data) print 'balance = ',a.getbalance() a.withdraw(remove_data) print 'balance after withdraw = ',a.getbalance() a.deposit(add_data) print 'balance after deposit = ',a.getbalance() doing away with p, w and add, or the even shorter variant where data, remove_data and add_data are also removed: a = Account(100.0) print 'balance = ',a.getbalance() a.withdraw(50.0) print 'balance after withdraw = ',a.getbalance() a.deposit(50.0) print 'balance after deposit = ',a.getbalance() -- André Engels, andreeng...@gmail.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class instance understanding = None
Le Fri, 27 Feb 2009 00:06:59 -0500, David s'exprima ainsi: > Hi Everyone, > I go through the archived [Tutor] mail list to find programs others have > tried to do. I found one that would keep track of a petty cash fund. > please point out my misunderstanding. > Here is what I started with; > > #!/usr/bin/python > > from reportlab.lib.normalDate import ND > #import cPickle as p > #import pprint > > today = ND() > > class Account: > def __init__(self, initial): > self.balance = initial > def deposit(self, amt): > self.balance = self.balance + amt > def withdraw(self, amt): > self.balance = self.balance - amt > def getbalance(self): > return self.balance > print 'The current date is: ', today.formatUS() > > > data = float('100.00') > a = Account(data) > p = a.getbalance() > print 'balance = ', p > remove_data = float('50.00') > w = a.withdraw(remove_data) > print "withdraw = ", w > add_data = float('50.00') > add = a.deposit(add_data) > print "deposit = ", add > > > results; > The current date is: 02/27/09 > balance = 100.0 > withdraw = None > deposit = None > > expected results; > The current date is: 02/27/09 > balance = 100.0 > withdraw = 50.0 > deposit = 100.0 > > thanks, > -david PS: I guess you misunderstand the methods withdraw and deposit: If you read the code (read it again), they *do* something, meaning they process an *action*. Understand they name as verbs. As a consequence they do not return anything result (they do not *make* anything). They are like Pascal procedures. So that you should state instead: w = float('50.00') ###w = a.withdraw(remove_data) print "withdraw = ", w denis -- la vita e estrany ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class instance understanding = None
Le Fri, 27 Feb 2009 00:06:59 -0500, David s'exprima ainsi: > Hi Everyone, > I go through the archived [Tutor] mail list to find programs others have > tried to do. I found one that would keep track of a petty cash fund. > please point out my misunderstanding. > Here is what I started with; > [...] > > > results; > The current date is: 02/27/09 > balance = 100.0 > withdraw = None > deposit = None > > expected results; > The current date is: 02/27/09 > balance = 100.0 > withdraw = 50.0 > deposit = 100.0 > > thanks, > -david So, what is your question, actually? If you do not want None, replace it with 0.0. None is good as a flag value. Denis -- la vita e estrany ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition...
"Spencer Parker" wrote I am looking for a good tutorial to walk through that really explains class definition. This has been one sticking point that always messes me up I assume from that you have been through the basic tutors like mine? Have you tried the deeper material in Dive into Python and the official tutorial? If so then it is probnably better for you to give us some specific questions you have. Or post a bit of a tutorialyou don't understand and we can collectively try to clarify it. Specific questions are always easier to answer than generalities. the most part. That and when people use "self". For some reason I just can't grasp what people say. Any good pointers to throw at me? OK, I explain self in my OOP tutor topic ( a sub heading under "Using Classes"), but again if thats not sufficient then you probably need to give us explicit examples of what you don't understand and your concerns. HTH, -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class arguments?
Forwarding to the list with my reply... On Fri, Jan 23, 2009 at 1:35 PM, spir wrote: > Le Fri, 23 Jan 2009 06:45:04 -0500, > Kent Johnson a écrit : > >> On Fri, Jan 23, 2009 at 6:04 AM, spir wrote: >> >> > Thank you Alan and sorry for not having been clear enough. The point >> > actually was class (definition) attributes. I thought at e.g. Guido's >> > views that lists were for homogeneous sequences as opposed to tuples >> > rather like records. And a way to ensure sich a homogeneity, in the sense >> > of items beeing of the same type or super type. >> > The straightforward path to ensure that, as I see it, is to add proper >> > argument to a class definition. >> >> A simple way to do this is with a class factory function, for example: >> >> def makeMonoList(typ, number): >> class MonoListSubtype(MonoList): >> item_type = type >> item_number = number >> return MonoListSubtype > > That's it! Stupid me!! [Just realize I have a kind of mental blocage that > prevents me *imagining* a class beeing defined inside a func. As for me a > class is a higher level kind of thing. Actually I also have problems with > defs insides defs. Maybe there should be more introduction to that in python > literature. Probably it may help and simplify a whole lot of models.] > Thank you again. >> then e.g. >> IntegerList = makeMonoList(int, 5) >> myIntegerList = IntegerList() >> >> This is similar in spirit to collections.namedtuple() in Python 2.6 >> though the implementation is different; namedtuple() actually creates >> and evaluates the text of the new class definition: >> http://docs.python.org/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields >> http://svn.python.org/view/python/trunk/Lib/collections.py?rev=68853&view=auto > > I have watched that some time ago -- as you pointed to it already. I take the > opportunity to ask why this contruct is so complicated. There is an > alternative in the cookbook (also pointed by Kent, if I remmember well) that > is only a few lines long. Something like: > > class Record(dict): >def __init__(self,**kwargs): >dict.__init__(self,kwargs) ># and/or >self.__dict__ = kwargs > > [There are several versons around, +/- based on the same principle] namedtuple() creates a new class that has exactly the desired attributes, so it is a bit more specific and typesafe - you have to have the correct number of points. The generated class subclasses tuple so it can be used as a dict key (if the items themselves can be). Class instances are lightweight because they don't have a __dict__ member. > Actually, the thing I like at least in the namedtuple recipe is that it > writes the class def as a string to be executed: Yeah, I know...with all the time we spend on the list telling people not to use eval()... > > I know there are several advantages: > * a docstring > * For large collections of records of the same (sub)type, as the list of > field is held by the class (instances record the actual data only), which > spares memory. But doesn't this lead to lower performance, as attribute > access by name requires adressing a class level attribute? The attributes are properties, so attribute access is like a method call, I suppose this is slower than direct field access but it is a common Python technique. > * attributes can be accessed by index, too > > Also, as this factory create kinds of records, meaning data constructs with > an identical structure, that would perfectly hold table records, why isn't it > simply called "record". > To sum up in a word: why so much *complication*? I guess you would have to search comp.lang.python or python-dev to find the reasons, I don't think there is a PEP for this (at least not referenced in the What's New). Kent > > Denis > -- > la vida e estranya > ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class arguments?
On Fri, Jan 23, 2009 at 6:04 AM, spir wrote: > Thank you Alan and sorry for not having been clear enough. The point actually > was class (definition) attributes. I thought at e.g. Guido's views that lists > were for homogeneous sequences as opposed to tuples rather like records. And > a way to ensure sich a homogeneity, in the sense of items beeing of the same > type or super type. > The straightforward path to ensure that, as I see it, is to add proper > argument to a class definition. A simple way to do this is with a class factory function, for example: def makeMonoList(typ, number): class MonoListSubtype(MonoList): item_type = type item_number = number return MonoListSubtype then e.g. IntegerList = makeMonoList(int, 5) myIntegerList = IntegerList() This is similar in spirit to collections.namedtuple() in Python 2.6 though the implementation is different; namedtuple() actually creates and evaluates the text of the new class definition: http://docs.python.org/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields http://svn.python.org/view/python/trunk/Lib/collections.py?rev=68853&view=auto Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class arguments?
Le Thu, 22 Jan 2009 23:29:59 -, "Alan Gauld" a écrit : > > "Alan Gauld" wrote > > >> is there a way to give arguments to a class definition? > > I see that Kent interpreted your question differently to me. > If you do mean that you want to dynamically define class > attributes rather than instance attributes then __init__() > won't work. But I'd be interested to understand why and > how you would want to do that? And in particular how > you would use them after creating them? Thank you Alan and sorry for not having been clear enough. The point actually was class (definition) attributes. I thought at e.g. Guido's views that lists were for homogeneous sequences as opposed to tuples rather like records. And a way to ensure sich a homogeneity, in the sense of items beeing of the same type or super type. The straightforward path to ensure that, as I see it, is to add proper argument to a class definition. But I couldn't find a way to do this. In pseudo-code, it would look like that: class MonoList(list, item_type): typ = item_type def __init__(self,items): self._check_types(items) list.__init__(self,items) def _check_types(self,items): for item in items: if not isinstance(item,MonoList.typ): message = "blah!" raise TypeError(message) def __setitem__(self,index,item): if not isinstance(item,MonoList.typ): message = "blah!" raise TypeError(message) list.__setitem__(self,index,item) def __add__(self,other): self._check_types(other) list.__add__(self,other) ... Well, I realize now that it is a bit more complicated. MonoList itself should be an intermediate base class between list and and subclasses that each allow only a single item type. Otherwise all monolist-s have the same item type ;-) Just exploring around... denis > ___ > Tutor maillist - Tutor@python.org > http://mail.python.org/mailman/listinfo/tutor > -- la vida e estranya ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class design - base classes with optional properties?
On Thu, Jan 22, 2009 at 6:24 PM, Alan Gauld wrote: > "Marcus Goldfish" wrote > >> I'm trying to design a base class for a hierarchy. The properties I want >> to >> specify for the base class depend on the values of other properties of the >> base class. > > Don't worry so much about the properties, the important thing to focus on > in your base classes is the behaviour. What exactly will these classes do? > What methods will they have? How will they be overridden in your > subclasses. > > Ideally the properties are invisible to the users of the class so the > interactions of the properties should all be controlled by the > methods. Class attributes can be a useful way to configure behaviour of subclasses. For example an HTML rendering widget might have attributes giving the type of tag to use to render or other HTML attributes. The Django HTML widgets are an example of this: http://code.djangoproject.com/browser/django/trunk/django/forms/widgets.py Look at the Input class and subclasses. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor