Which part of the loop is it going through in this class frame?
On 07Mar2018 16:57, C W <tmrsg11 at gmail.com> wrote:
>I am new to OOP. I'm a bit confused about the following code.
> def __init__(self, time):
> self.time = time
> def print_time(self):
> time = '6:30'
>clock = Clock('5:30')
>I set time to 6:30, but it's coming out to 5:30. I guess it's because I
>passed in 5:30, so, it's replaced?
No, it is because the scope isn't what you think. In the print_time() method,
the variable "time" is just a local variable. It is unrelated the the instance
("self")'s "self.time" value. So you're printing self.time, which is unchanged
from when the object was initialised. Try adding:
to the method and compare the values.
>How does line-by-line execution run inside a frame? How does __init__ work?
>I understand you must have __init__. Is it run before print_time(), if so,
>why don't I just set self.time = '6:30' instead of self.time = time?
A "frame" is normally what we refer to as a "stack frame": if it a little
record which the language implementation uses to keep track of nested function
calls. When you call a function, a new stack frame is pushed, which amongst
other things contains a reference to the local variables alive during the call.
When you return from a function the frame is popped and discarded.
The __init__ method is called as the initial setup of an object, just after it
is created. When you program went:
clock = Clock('5:30')
a new "Clock" instance was made. Then that instance's __init__ method was
called with the '5:30' which you passed to the class name. That is how the
string '5:30' gets stored as the .time attribute of the instance.
The reason you say "self.time = time" is that you want to store the value
passed to the constructor. It might be any time.
clock1 = Clock('5:30')
clock2 = Clock('5:45')
Now you have to distinct Clock instances, one holding the time '5:30' and one
holding the time '5:45'.
Your print_time method is a little odd. Normally such a function would not take
an argument, just print the internal value from the Clock instance. So
typically it would look like this:
See that is doesn't take a time parameter?
Regarding setting self.time directly to '6:30', that depends what you want to
do with it. A "Clock" might have different purposes, and you should decide what
the purpose of yours actually is.
As an example, Python's "datetime" module contains classes for dates and times
and "datetimes" containing a date and a clocklike time. Normally these are made
once and NOT CHANGED. So they're like a special kind of number. They have
various methods for computing, for you, things like the day of the week or
writing the date or time out in particular formats, or comparing two dates.
But a sometimes you don't want a fixed timestamp. You might be modelling a
clock, whose value changes as time passes. In that case you may well want to
adjust the values inside it.
You're print_time method seems odd because it does 2 things: it prints a time,
but it also seems to want to change the internal time. It is usually good to
separate such things.
Finally, setting the time attrubute directly is a reasonable thing to do, but
it varies with (a) your needs and (b) the OOP paradigm you're following and how
strict you're being.
In a "pure" OOP environment one never sets the internal state of an object
directly, so one never goes:
clock1.time = '5:55'
Instead you would always go:
and be _unaware_ of how the object may be storing that vaue internally. Some
languages will enforce this, and provide no way to modify an object except via
"setter" methods. This has some advantages:
You can switch out objects implementations provided they provide the same
setter methods - your calling code doesn't know or care how the clock manages
the internal values.
In principle you can make objects "remote" i.e. not local im-memory things at
all, if that is sensible. This is why some OOP descriptions treat methods as
messages: you send a "set_time" request to the clock with a new time, or you
send a "get_time" request to a clock the retrive the current time.
Also, because everything is done through setter or getter methods, you can't
accidentally damage the object internal state by setting to nonsense. The
setter methods should sanity check the incoming values, and the getters will
always return sensible values. If the caller expects to directly modify the
internals then they might set the minutes to negative values, or values >= 60,
or some other nonsensical value. By using methods all the responsibility is
inside the class where it is easy to keep correct.
Python lets you use that paradigm, but it doesn't prevent you directly
accessing or changing the internals. The philosophy is that you should exercise
restraint. So you _can_ directly set the clock.time value; whether that is a
good idea depends on the clock implementation and your program.
In Python there is a naming convention: values which may be directy accessed
are given ordinary names (like ".time") and values which are part of the
internals, subject to change, or tricky to keep correct are given names
starting with underscores (like "._time"). If you're accessing a _name that is
a clue that you're probably doing the wrong thing (if your outside the class -
obviously the class itself must work on these values).
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)