Re: [Tutor] Class Inheritance

2017-02-21 Thread Peter Otten
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

2017-02-21 Thread Alan Gauld via Tutor
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

2017-02-21 Thread Alan Gauld via Tutor
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

2017-02-21 Thread Rafael Knuth
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

2010-04-24 Thread Steven D'Aprano
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

2010-04-24 Thread Alan Gauld

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

2010-04-24 Thread Alan Gauld

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

2010-04-23 Thread Alan Gauld
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

2010-04-23 Thread Steven D'Aprano
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

2010-04-23 Thread Steven D'Aprano
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

2010-04-23 Thread David Hutto
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

2010-04-22 Thread David Hutto
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

2010-04-22 Thread Steven D'Aprano
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

2007-09-14 Thread Eric Brunson

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

2007-09-13 Thread Lamonte Harris
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

2007-09-13 Thread Eric Brunson
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

2005-11-30 Thread Tim Johnson
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

2005-11-30 Thread Christopher Arndt
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

2005-11-30 Thread Liam Clarke-Hutchinson
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

2005-11-30 Thread Tim Johnson
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

2005-11-30 Thread John Fouhy
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

2005-11-30 Thread Tim Johnson
* 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