Alan, The concept and purpose of classes is starting to sink in a little bit, but I still haven't had my "Ah-ha" moment yet. I just can't seem to visualize the execution of classes, nor am I able to explain to myself how it actually works. For example:
class Person: def __init__ (self, name, age): # is self just a placeholder for an arbitrary object? How does __init__ actually work? self.name = name # why assign name to self.name variable? self.age = age # same as previous def salute (self): # again with the self print ("Hello, my name is " + self.name + " and I am " + str(self.age) " years old.") On Mon, Jan 20, 2014 at 4:20 PM, spir <denis.s...@gmail.com> wrote: > On 01/19/2014 10:59 PM, Christian Alexander wrote: > >> Hello Tutorians, >> >> Looked all over the net for class tutorials >> Unable to understand the "self" argument >> Attempting to visual classes >> >> I have searched high and low, for easy to follow tutorials regarding >> classes. Although I grok the general concept of classes, I am unable to >> visually understand what exactly "self" does, or why it is even necessary. >> It seems very "magic" to me. Also I am having the most difficult with >> the >> "__init__()" method in classes, and why that is also required. Keep in >> mind that I am a visual person (maybe I should have been a graphic >> designer), therefore most programming concepts flow irritatingly slow for >> me. >> > > Imagine that for an app you had to define 2 persons p1 & p2 (maybe game > characters for instance). In an imaginary programming language, a > definition of p1 could look like this: > > p1 = {name="Maria", age=33} # no good python code > > This would be a composite piece of data, made of 2 fields (attributes, > properties...). In python there is no such generic type Object or Composite > to which such data as p1 could belong. You must define a custom type > (class) for them, eg: > > class Person: pass > > Now, you can have p1 of type Person, which is written as if you would call > the type Person, like a func, to make a new person (this is close to what > happens): > > p1 = Person() > > Then, one can define fields on it: > > p1.name = "Maria" > p1.age = 33 > print(p1.name, p1.age) > > We could do the same thing for p2: > > p2 = Person() > p2.name = "paulo" > p2.age = 22 > print(p2.name, p2.age) > > Now, say persons are supposed to do things, and all can do the same > things. To define something all persons can do, you would define it on > their class (this is the second purpose of a class), eg: > > class Person: > def salute (self): > print ("Hello, my name is " + self.name + > " and I am " + str(self.age) " years old.") > > As you can see, this method uses the attributes 'name' & 'age' we manually > defined on both p1 & p2. Then, how does the method, which is defined on the > type, not on individual objects, know where to find these attributes? You > are right to say there is some magic at play here. Let us use the method > first, before explaining: > > p1.salute() > p2.salute() > > [Copy-paste & run all this code.] On the first call, we ask the method > 'salute' to operate on p1, and it writes p1's name & age. Same for p2. > Inside the method, the attributes are searched on the weird param called > 'self'. This is just what happens: when calling a method, the object on > which it operates is assigned to the parameter self. 'self' is just a name > for the-object-on-which-this-method-operates-now. When it operates on p1, > self is p1, thus attributes are searched on p1; same for p2. We need some > placeholder because the method is defined on the type and works for any > object of this type (any "instance"). [We can define a method on p1 which > works on p1 only. Maybe try it.] > > Finally, if we define a whole range of persons that way, it is annoying to > set all attributes manually. We could define a method, say 'def_attrs', to > be called at startup. But python has a specially dedicated method for that, > which we don't even need to call explicitely, named '__init__'. We will use > it to set person attributes: > > class Person: > def __init__ (self, name, age): > self.name = name > self.age = age > def salute (self): > print ("Hello, my name is " + self.name + > " and I am " + str(self.age) " years old.") > > (yes, init methods typically are as stupid as this; too bad python does > not do the mechanical job automagically) And this is used like this: > > p1 = Person("maria", 33) # no need to call __init__ explicitely > p1.salute() > p2 = Person("paulo", 22) # ditto > p2.salute() > > denis > > _______________________________________________ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Regards, Christian Alexander
_______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor