[Tutor] Help understanding classes

Alan Gauld alan.gauld at btinternet.com
Sat Nov 15 22:56:21 CET 2014

On 15/11/14 18:19, Bo Morris wrote:

> With the first part…
> class Message:
>      def __init__(self, aString):
>          self.text = aString
> Will I always use “_init_” when defining the first function in a class?

It can go anywhere in the class definition. it is just another method of 
the class. But because it is where the initialization of the class data 
happens, it is logical and conventional to have it first. But there is 
no rule about it.

> I noticed on your website, you created a class where you did not use
> “_init_” (see below). Was this because you did not define a function?
> class BalanceError(Exception):
>        value = "Sorry you only have $%6.2f in your account”

Any class where you do not need to initialize any data can do without an 
__init__(). In this case it's just a subclass of the built in exception 
class  - a new bespoke error type -  so has no need of an init()

> I noticed that I can change “text” to anything and I still get the same
> results by running the code; I changed them to “blah” just as a test.

text is just a name. Its a variable inside the class.
In this case its where the message text is stored.
Remember, classes are trying to model real concepts.
a message has text so it has to be stored somewhere
and an attribute called text is as good as anything.

> When I define a function in a class, will I always use “self” as the
> first entry in the parenthesis?

Its a convention that is best observed. Pythoin doesn't
actually care, you can use any name. The first parameter
will allways refer to the instance calling the method.
Other names sometimes seen are 'this' and 'object' but
in Python self is the convention.

> m = Message("This is a test")
> m.printIt()
> I noticed I cannot run “printIt()” unless I make it an object i.e. “m =
> Message("This is a test”)…?”

Because printIt() is a method of the class. You must have an instance to 
call a method. That's what makes it a method rather than an ordinary 

> I noticed I could change "m = Message("This is a test”)” to "m =
> Message(raw_input()),” which works.

Because the init expects a string. it doesn't matter how you create the 
string, it canbe a literal, a variable or using raw_ijnput. So long sas 
the result is a string it will work(Actually because of pythons flexible 
approach to types it can be other things too...

m = Message(42)

will print 42.
But thats because the print will convert it to a string for you.

> What if I wanted to create a function in Message that receives text from
> another function and then prints that text instead of the text from  “m
> = Message("This is a test”)…; can I pass or return values to another
> function inside a class?

Of course, methods are just functions, they can have any kind of 
parameter that an ordinary function can have. methods can call
other methods (using the self. prefix) and methods can be called by 
external functions provided that function has an object of the right 
type to call it on.

> The”self” is really throwing me off, when I
> think about creating different functions that do misc things just to
> practice.

methods shouldn't do miscellaneous things. Thats what modules andv 
functions are for(sort of). Methods should define the behaviour of an 
object type. Try to think of an object and what you can do with that 
object. Write methods that do those things.

> For example, I have a function that kills a Linux program. I
> just don’t see how to rethink that function to where it could be defined
> in a class?

You could have a program class.
It starts, it stops, it ends. It may produce output.
In fact we already have a class that does this, its the Popen class in 
the subprocess module.

You can learn a lot about OOOP by looking at the classes defined in the 
standard library and seeing what methods (and attributes) they define.

> def kill_proc(process1):
>      i = psutil.Popen(["ps", "cax"], stdout=PIPE)
>      for proc in psutil.process_iter():
>          if proc.name(process1):
>              proc.kill()
> Would it be something like…?
> class processKiller:

class names should be nouns. Everytime you have a verb name
it probably means you are just writing a function.
The classic case is a xxxManager class, that's usually wrong.

So you want

class Process:

>      def _init_(self):

You might want a command string in the init. That would let you start 
the process before you can kill it.
You might want to store the PID in the process object

self.pid = ....

>      def kill_proc(self, process1):

self will be process1 so you don't need to pass it as a parameter.

>          i = psutil.Popen(["ps", "cax"], stdout=PIPE)

You shouldn't need this if you start the process in init() since you can 
get the pid at that stage.

>          for proc in psutil.process_iter():
>              if proc.name(process1):
>                  proc.kill()

> Then outside of the class, call it like so…?
> p = processKiller()
> p.proc.kill()

So I'd suggest

p = Process('top')

> Oh yeah, Alan I preordered your new book maybe a month or so ago. Any
> word on when it will be released and shipped?

According to Amazon it's out on 26th December...
It has a whole chapter on scripting, including a section on
using subprocess to manage external processes.

Alan G
Author of the Learn to Program web site

More information about the Tutor mailing list