Re: [Tutor] Class Inheritance
Rafael Knuth wrote: > Hey there, > > I am trying to wrap my head around Class Inheritance in Python, and I > wrote a little program which is supposed to calculate revenues from > customers who don't get a discount (parent class) and those who get a > 30% discount (child class): > > class FullPriceCustomer(object): > def __init__(self, customer, rate, hours): > self.customer = customer > self.rate = rate > self.hours = hours > > print ("Your customer %s made you %s USD this year." % > (customer, rate * hours)) > > class DiscountCustomer(FullPriceCustomer): > discount = 0.7 > def calculate_discount(self, rate, hours): > print ("Your customer %s made you %s USD at a 30% discount > rate this year." % (self.customer, self.rate * rate * discount)) > > customer_one = DiscountCustomer("Customer A", 75, 100) > customer_two = FullPriceCustomer("Customer B", 75, 100) > > The DiscountCustomer class instance gets me the wrong result (it does > not calculate the discount) and I was not able to figure out what I > did wrong here. > Can anyone help? Thanks! In a real application you would not introduce two classes for this -- a FullPriceCustomer would be a customer with a discount of 0%. Then you mix output with initialisation, so let's fix that first: class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print( "Your customer %s made you %s USD this year." % (self.customer, self.rate * self.hours) ) customer = FullPriceCustomer("Customer B", 75, 100) customer.print_summary() Now look at your code: what has to change for a customer who gets a discount? self.rate * self.hours will become self.discount * self.rate * self.hours or as I prefer to store the part that the customer doesn't pay as the discount (1 - self.discount) * self.rate * self.hours To make overriding easy we put that calculation into a separate method: class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print( "Your customer %s made you %s USD this year." % (self.customer, self.get_total()) ) def get_total(self): return self.rate * self.hours customer = FullPriceCustomer("Customer B", 75, 100) customer.print_summary() Then the DiscountCustomer class can be written class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print( "Your customer %s made you %s USD this year." % (self.customer, self.get_total()) ) def get_total(self): return self.rate * self.hours class DiscountCustomer(FullPriceCustomer): discount = 0.3 def get_total(self): return (1 - self.discount) * self.rate * self.hours customers = [ DiscountCustomer("Customer A", 75, 100), FullPriceCustomer("Customer B", 75, 100), ] for customer in customers: customer.print_summary() If we run that we see that the calculation may be correct, but the discount is not mentioned. We could solve this by overriding print_summary, but here's another way: class FullPriceCustomer(object): summary_template = ( "Your customer {0.customer} made you {0.total} USD this year." ) def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print(self.summary_template.format(self)) @property def total(self): return self.rate * self.hours class DiscountCustomer(FullPriceCustomer): summary_template = ( "Your customer {0.customer} made you {0.total} USD " "at a {0.discount:.0%} this year." ) discount = 0.3 @property def total(self): return (1 - self.discount) * self.rate * self.hours class VIC(DiscountCustomer): discount = 0.33 customers = [ DiscountCustomer("Customer A", 75, 100), FullPriceCustomer("Customer B", 75, 100), VIC("Customer C", 75, 100), ] for customer in customers: customer.print_summary() If one day you choose to use an isinstance check to see if you have a FullPriceCustomer for customer in customers: if isinstance(customer, FullPriceCustomer): print(customer.customer, "pays the full price") you may be surprised to see that all customers seem to be paying the full price. That's because isinstance(obj, class_) is true even if the actual class of obj is a subclass of class_. Therefore I recommend that you change your class hierarchy to class Customer(object): ... class FullPriceCustomer(Customer): ...
Re: [Tutor] Class Inheritance
On 21/02/17 09:49, Rafael Knuth wrote: > class DiscountCustomer(FullPriceCustomer): > discount = 0.7 > def calculate_discount(self, rate, hours): > print ("Your customer %s made you %s USD at a 30% discount > rate this year." % (self.customer, self.rate * rate * discount)) I meant to add... are you sure that calculation is what you meant? First point is that discount is not defined, you need to prefix it with either self or DiscountCustomer. But also, it doesn't use hours? Is that correct? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance
On 21/02/17 09:49, Rafael Knuth wrote: > class FullPriceCustomer(object): > def __init__(self, customer, rate, hours): > > > class DiscountCustomer(FullPriceCustomer): > discount = 0.7 > def calculate_discount(self, rate, hours): > > customer_one = DiscountCustomer("Customer A", 75, 100) > customer_two = FullPriceCustomer("Customer B", 75, 100) You create two instances and as such the FullPriceCustomer.__init__() method gets executed in both cases. This is because the subclass does not provide an __init__() of its own, so the inherited one is used. Your discount is calculated in the calculate_discount() method, but that is never called. If you added a line: customer_one.calculate_discount(75,100) you would see the discount appear. Alternatively create an init() for your subclass that calls the superclass init() then calls self.calculate_discount(rate,hours) BTW It's bad practice to mix calculations and display(print) in the same method, it's better to separate them, but that's probably a topic for another thread Get the inheritance sorted first :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Class Inheritance
Hey there, I am trying to wrap my head around Class Inheritance in Python, and I wrote a little program which is supposed to calculate revenues from customers who don't get a discount (parent class) and those who get a 30% discount (child class): class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours print ("Your customer %s made you %s USD this year." % (customer, rate * hours)) class DiscountCustomer(FullPriceCustomer): discount = 0.7 def calculate_discount(self, rate, hours): print ("Your customer %s made you %s USD at a 30% discount rate this year." % (self.customer, self.rate * rate * discount)) customer_one = DiscountCustomer("Customer A", 75, 100) customer_two = FullPriceCustomer("Customer B", 75, 100) The DiscountCustomer class instance gets me the wrong result (it does not calculate the discount) and I was not able to figure out what I did wrong here. Can anyone help? Thanks! All the best, Rafael ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://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 pyshell#2, line 1, in module 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, Beat it into the Ground
David Hutto smokefl...@gmail.com 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
Steven D'Aprano st...@pearwood.info 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
David Hutto smokefl...@gmail.com 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 module 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 module 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 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\ascentc:\python26/Script3.py Traceback (most recent call last): File C:\python26\Script3.py, line 1, in module 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 stdin, line 1, in module File mytkinter.py, line 1, in module from myturtle import * File myturtle.py, line 3, in module 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
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
[Tutor] Class Inheritance, Beat it into the Ground
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? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
[Tutor] Class Inheritance
Hello List! While experimenting with Tkinter(python2.6), when from Tkinter import* is used I came across the following error: C:\Users\ascentc:\python26/Script3.py Traceback (most recent call last): File C:\python26\Script3.py, line 1, in module from Tkinter import * File C:\Python26\lib\lib-tk\Tkinter.py, line 44, in module from turtle import * File C:\Python26\lib\lib-tk\turtle.py, line 374, in module class ScrolledCanvas(Tkinter.Frame): AttributeError: 'module' object has no attribute 'Frame' * 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. So I tried to alter the turtle.py. When I try to just 'from Tkinter import *, such as: from Tkinter import * class ScrolledCanvas(Tkinter.Frame): I get: * C:\Users\ascentc:\python26/Script3.py Traceback (most recent call last): File C:\python26\Script3.py, line 1, in module from Tkinter import * File C:\Python26\lib\lib-tk\Tkinter.py, line 44, in module from turtle import * File C:\Python26\lib\lib-tk\turtle.py, line 373, in module class ScrolledCanvas(Tkinter.Frame): NameError: name 'Tkinter' is not defined *** I know pretty much what is going on there. But when I try to use: import Tkinter from Tkinter import * 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. 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? 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). TIA, David ___ 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\ascentc:\python26/Script3.py Traceback (most recent call last): File C:\python26\Script3.py, line 1, in module from Tkinter import * File C:\Python26\lib\lib-tk\Tkinter.py, line 44, in module from turtle import * File C:\Python26\lib\lib-tk\turtle.py, line 374, in module 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\ascentc:\python26/Script3.py Traceback (most recent call last): File C:\python26\Script3.py, line 1, in module from Tkinter import * File C:\Python26\lib\lib-tk\Tkinter.py, line 44, in module from turtle import * File C:\Python26\lib\lib-tk\turtle.py, line 373, in module 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 class Tkinter.Frame at 0x00BC2F60 turtle.ScrolledCanvas class turtle.ScrolledCanvas at 0x00F71720 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
Re: [Tutor] Class Inheritance
You're still using the wrong terminology... A subclass is derived (or subclassed) from its parent class (or super class) A function that is part of the class definition (def func1(self): pass) is a method A variable that is part of the class definition or added after instantiation is an attribute When you create an object (a = A()) you are instantiating the class and the resultant object is an instance Lamonte Harris wrote: So ok, when I inherit a class, all the classes methods. Classes have methods (functions) and attributes (variables). in the parent class will overwrite override. all the functions methods. in the class I inherited the parent class into? No, exactly the opposite. If they have the same class names that is? # declare a class class A(object): this = is a class attribute def method1(self): self.thisthing = is an attribute print class A: method1 def method2(self): print class A: method2 # subclass it class B(A): def method2(self): print class B: method2 def method3(self): print class B: method3 # create an instance of each class a = A() b = B() a.method1() OUTPUT classA: method1 a.method2() OUTPUT classA: method2 b.method1() OUTPUT classA: method1 b.method2() OUTPUT classB: method2 super(B,b).method2() OUTPUT classA: method2 # super() only works because B is a subclass of object by virtue or A being derived from object b.method3() OUTPUT classB: method3 a.method3() Traceback (most recent call last): File stdin, line 1, in module AttributeError: A instance has no attribute 'method3' When you derive a subclass from another class all methods of the parent class are available Is that clear? On 9/13/07, *Eric Brunson* [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] wrote: Lamonte Harris wrote: Okay class A: def __init__(self,x,y): self.x = x self.y = y def save(self,fn): f = open(fn,w) f.write(str(self.x)+ '\n') # convert to a string and add newline f.write(str(self.y)+'\n') return f # for child objects to use def restore(self, fn): f = open(fn) self.x = int(f.readline()) # convert back to original type self.y = int(f.readline()) return f class B(A): def __init__(self,x,y,z): A.__init__(self,x,y) self.z = z def save(self,fn): f = A.save(self,fn) # call parent save f.write(str(self.z)+'\n') return f # in case further children exist def restore(self, fn): f = A.restore(self,fn) self.z = int(f.readline()) return f In the class B, I'm not understanding the A.__init(self,x,y) part. So its initializing the class A, and basically you can use the A class like normal? Essentially, yes, but the way you've worded it is imprecise. Any instance of B is a subclass of A, essentially an A: Every boy is a male, but not all males are boys. When you override a method in a subclass you have essentially turned off all behavior in the parent method, including magic methods like the constructor. You have to call the parent constructor explicitly to get its benefits. A method of an instance can be called like this: instance.method() and python makes sure that a pointer to the instance is passed in as the first argument, generally self. But a method of a class can be called without instantiating the class, but you have to supply self on you own. The method you are using is valid, yet depricated. Using new style classes (which aren't actually that new) you'd write your code like this: class A(object): def __init__(self, a): self.aye = a class B(A): def __init__(self, a, b): self.bee = b super( B, self ).__init__( a ) Notice that you don't have to supply self. You can use any method of A in an instance of B that you haven't overridden in B without having to use super(). Part im confused about is the self.z, does that belong to the class A or class B? z is an attribute B only. Hope that helps, e. Else I think I'm understanding it correctly. ___ Tutor maillist - Tutor@python.org mailto:Tutor@python.org http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Class Inheritance
Okay class A: def __init__(self,x,y): self.x = x self.y = y def save(self,fn): f = open(fn,w) f.write(str(self.x)+ '\n') # convert to a string and add newline f.write(str(self.y)+'\n') return f # for child objects to use def restore(self, fn): f = open(fn) self.x = int(f.readline()) # convert back to original type self.y = int(f.readline()) return f class B(A): def __init__(self,x,y,z): A.__init__(self,x,y) self.z = z def save(self,fn): f = A.save(self,fn) # call parent save f.write(str(self.z)+'\n') return f # in case further children exist def restore(self, fn): f = A.restore(self,fn) self.z = int(f.readline()) return f In the class B, I'm not understanding the A.__init(self,x,y) part. So its initializing the class A, and basically you can use the A class like normal? Part im confused about is the self.z, does that belong to the class A or class B? Else I think I'm understanding it correctly. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance
Lamonte Harris wrote: Okay class A: def __init__(self,x,y): self.x = x self.y = y def save(self,fn): f = open(fn,w) f.write(str(self.x)+ '\n') # convert to a string and add newline f.write(str(self.y)+'\n') return f # for child objects to use def restore(self, fn): f = open(fn) self.x = int(f.readline()) # convert back to original type self.y = int(f.readline()) return f class B(A): def __init__(self,x,y,z): A.__init__(self,x,y) self.z = z def save(self,fn): f = A.save(self,fn) # call parent save f.write(str(self.z)+'\n') return f # in case further children exist def restore(self, fn): f = A.restore(self,fn) self.z = int(f.readline()) return f In the class B, I'm not understanding the A.__init(self,x,y) part. So its initializing the class A, and basically you can use the A class like normal? Essentially, yes, but the way you've worded it is imprecise. Any instance of B is a subclass of A, essentially an A: Every boy is a male, but not all males are boys. When you override a method in a subclass you have essentially turned off all behavior in the parent method, including magic methods like the constructor. You have to call the parent constructor explicitly to get its benefits. A method of an instance can be called like this: instance.method() and python makes sure that a pointer to the instance is passed in as the first argument, generally self. But a method of a class can be called without instantiating the class, but you have to supply self on you own. The method you are using is valid, yet depricated. Using new style classes (which aren't actually that new) you'd write your code like this: class A(object): def __init__(self, a): self.aye = a class B(A): def __init__(self, a, b): self.bee = b super( B, self ).__init__( a ) Notice that you don't have to supply self. You can use any method of A in an instance of B that you haven't overridden in B without having to use super(). Part im confused about is the self.z, does that belong to the class A or class B? z is an attribute B only. Hope that helps, e. Else I think I'm understanding it correctly. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Class Inheritance - NameError
The following code snippet is meant to test inheritance: class test: def __init__(self,v): self.__val = v def val(self): print self.__val class sub(test): def __init__(self): val() The following console session has an error: T = mylib.test('hello') s = mylib.sub() Traceback (most recent call last): File stdin, line 1, in ? File mylib.py, line 1612, in __init__ val() NameError: global name 'val' is not defined ## what do I need to do to make the 'test method visible ## class 'sub? thanks tim -- Tim Johnson [EMAIL PROTECTED] http://www.alaska-internet-solutions.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance - NameError
Tim Johnson schrieb: The following code snippet is meant to test inheritance: class test: def __init__(self,v): self.__val = v def val(self): print self.__val class sub(test): def __init__(self): val() The following console session has an error: Beware test.__val is a 'private' attribute. See http://www.python.org/doc/current/tut/node11.html#SECTION001160 for an explanation. T = mylib.test('hello') s = mylib.sub() Traceback (most recent call last): File stdin, line 1, in ? File mylib.py, line 1612, in __init__ val() NameError: global name 'val' is not defined ## what do I need to do to make the 'test method visible ## class 'sub? Surely you mean the 'val' method (see the traceback)? it lives in the namespace of the class 'test'. So if you want to call it as a class method: test.val(instance) if you want to call it as an instance method: instance = sub() instance.val() resp. in the class and sub-classes itself: self.val() HTH, Chris ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance - NameError
Hi Tim, Either - class test: def __init__(self,v): self.__val = v def val(self): print self.__val class sub(test): def __init__(self, v): test.__init__(v) self.val() or - class sub(test): def __init__(self, v): test.__init__(v) test.val() That will resolve your calling the method problem, but self.__val won't inherit (I think). I don't recommend using double underscored variables unless there's a really good reason, C# et al be damned. Oh, and if self.__val / val is set by the superclasses __init__ method, then you'll need to call it specifically, or otherwise you'll get a UnboundLocalError, because self.__val/val won't exist. Liam Clarke-Hutchinson -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Tim Johnson Sent: Thursday, 1 December 2005 3:46 p.m. To: tutor@python.org Subject: [Tutor] Class Inheritance - NameError The following code snippet is meant to test inheritance: class test: def __init__(self,v): self.__val = v def val(self): print self.__val class sub(test): def __init__(self): val() The following console session has an error: T = mylib.test('hello') s = mylib.sub() Traceback (most recent call last): File stdin, line 1, in ? File mylib.py, line 1612, in __init__ val() NameError: global name 'val' is not defined ## what do I need to do to make the 'test method visible ## class 'sub? thanks tim -- Tim Johnson [EMAIL PROTECTED] http://www.alaska-internet-solutions.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor A new monthly electronic newsletter covering all aspects of MED's work is now available. Subscribers can choose to receive news from any or all of seven categories, free of charge: Growth and Innovation, Strategic Directions, Energy and Resources, Business News, ICT, Consumer Issues and Tourism. See http://news.business.govt.nz for more details. http://www.govt.nz - connecting you to New Zealand central local government services Any opinions expressed in this message are not necessarily those of the Ministry of Economic Development. This message and any files transmitted with it are confidential and solely for the use of the intended recipient. If you are not the intended recipient or the person responsible for delivery to the intended recipient, be advised that you have received this message in error and that any use is strictly prohibited. Please contact the sender and delete the message and any attachment from your computer. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance - NameError
My thanks to Christopher and Liam. I've revisited this with the following: class test: def __init__(self): self.s = ' there' def val(self,V): print '%s%s' % (V,self.s) class sub(test): def __init__(self): pass The following console session: T = mylib.test() S = mylib.sub() S.val('hello') Traceback (most recent call last): File stdin, line 1, in ? File mylib.py, line 1609, in val print '%s%s' % (V,self.s) AttributeError: sub instance has no attribute 's' Removing references to self.s as in class test: def __init__(self): pass def val(self,V): print V class sub(test): def __init__(self): pass gives a console session without the AttributeError -- | Do I understand that classes inherit methods, but not | | variable attributes? | -- Thanks: I've use inherited classes before but haven't tried anything with variables. tim -- Tim Johnson [EMAIL PROTECTED] http://www.alaska-internet-solutions.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance - NameError
On 01/12/05, Tim Johnson [EMAIL PROTECTED] wrote: My thanks to Christopher and Liam. I've revisited this with the following: class test: def __init__(self): self.s = ' there' def val(self,V): print '%s%s' % (V,self.s) class sub(test): def __init__(self): pass The following console session: T = mylib.test() S = mylib.sub() S.val('hello') Traceback (most recent call last): File stdin, line 1, in ? File mylib.py, line 1609, in val print '%s%s' % (V,self.s) AttributeError: sub instance has no attribute 's' Hi Tim, When you create an instance of a class, python calls the __init__ method of the class you just created, but it _doesn't_ call the __init__ method of any superclasses. There are several good reasons for this --- it doesn't know what parameters you want to pass to the superclass __init__ methods, or when you want to call them. So, it is up to you to make that call. You can do that like this: class sub(test): def __init__(self): test.__init__(self) Because self.s is only created in test.__init__, you have to call the __init__ method to get access to it. HTH! -- John. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Inheritance - NameError
* John Fouhy [EMAIL PROTECTED] [051130 19:21]: ..snip... On 01/12/05, Tim Johnson [EMAIL PROTECTED] wrote: superclass __init__ methods, or when you want to call them. So, it is up to you to make that call. You can do that like this: class sub(test): def __init__(self): test.__init__(self) Because self.s is only created in test.__init__, you have to call the __init__ method to get access to it. HTH! :-) It does indeed! thanks everybody tim -- Tim Johnson [EMAIL PROTECTED] http://www.alaska-internet-solutions.com ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor