Comet points at the word self, which appears in every line of __init__. "Who is self?" she asks. "I never pass it in. I only give three values."
Wren counts the parameters on his clipboard. "What does the evidence say?" he asks. "The def line has four names, but the call has three values. Something fills the first one."
Nova projects a call, Sample("S05", "granite", 30), and draws arrows from each value into __init__. "How can I help?" she asks. "Follow the arrows. One of them comes from Python itself."
Comet leans in. "Lead programmer, trace it with us."
A method is a function defined inside a class. Called on an object, it gets that object as its first argument, usually named self.
__init__ is a method too. When you call Sample(...), Python passes the brand new object to __init__ as self, then your arguments after it.
Some samples have no spot on the field yet. This step gives row and col default values of 0, so a call can leave them out.
S05 granite is made-up data from the FieldSim story, a sample that has not been placed on the field.
# sample_defaults.py
class Sample:
"""One sample token from the test field."""
def __init__(self, label, kind, grams, row=0, col=0):
self.label = label
self.kind = kind
self.grams = grams
self.row = row
self.col = col
s01 = Sample("S01", "basalt", 42, 0, 2)
s05 = Sample("S05", "granite", 30)
print(s01.row, s01.col)
print(s05.row, s05.col)
print(s05.label, s05.grams) | Parameter of __init__ | Value in Sample("S05", "granite", 30) | Where it came from |
|---|---|---|
| self | the new Sample object | Python passes it in |
| label | "S05" | first argument |
| kind | "granite" | second argument |
| grams | 30 | third argument |
| row | 0 | default |
| col | 0 | default |
0 2 0 0 S05 30
This step adds a method of its own, weight_line(). Watch the last two calls: they do the same job in two ways.
# self_demo.py
class Sample:
def __init__(self, label, kind, grams, row=0, col=0):
self.label = label
self.kind = kind
self.grams = grams
self.row = row
self.col = col
def weight_line(self):
return f"{self.label} weighs {self.grams} g"
a = Sample("S01", "basalt", 42, 0, 2)
b = Sample("S02", "quartz", 18, 2, 4)
print(a.weight_line())
print(b.weight_line())
print(Sample.weight_line(b)) The name self is only a convention. It has no special meaning to Python, as this run shows.
Every Python programmer reads self, though, so this course always uses it.
# not_self.py
class Tag:
def __init__(me, label):
me.label = label
def show(me):
return "Tag " + me.label
print(Tag("S03").show()) An object's state is its attributes and their values at a given time. The object has a has-a relationship with them: s05 has a grams of 30.
A constructor sets the starting state. It should give every instance variable a starting value, as __init__ does for all five.
| Statement | True or false? |
|---|---|
| A method gets the object it was called on as its first argument. | ? |
| self is a keyword that Python reserves. | ? |
| A constructor should give every instance variable a starting value. | ? |
| A default value is used even when the call gives that argument. | ? |
Now you know who self is. Tomorrow is Sim Lab: you will type the real sample.py for FieldSim.