简体   繁体   中英

Variable Usage in Python Class Declaration

Here is a code snippet from Zed Shaw's "Learn Python the Hard Way" tutorial 40:

class Song(object):

    def __init__(self, lyrics):
        self.lyrics = lyrics

    def sing_me_a_song(self):
        for line in self.lyrics:
            print line

Why does Python allow "self.lyrics" to be used when defining "sing_me_a_song" function? Is it because whatever variable is defined under " init " can also be used elsewhere in the same class?

Thanks.

Instance Variables

This is called an instance variable. Any variable defined with self. as a "prefix" can be used in any method of an object. Typically such variables are created in __init__ , so they can be accessed from the moment the object is initialized, though you can define instance variables in other methods. For example:

>>> class foo:
...     def fun(self):
...             self.heh=3
... 
>>> f = foo()
>>> f.heh 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: foo instance has no attribute 'heh'
>>> f.fun()
>>> f.heh
3

Notice the danger in initializing instance variables outside of __init__ ; if the method in which they are initialized is not called before you try to access them, you get an error.

Class Variables

This is not to be confused with "class variables," which are another type of variable that can be accessed by any method of a class. Class variables can be set for an entire class, rather than just specific objects of that class. Here's an example class with both instance and class variables to show the difference:

class MyClass:
    classVar = "I'm a class var."
    def __init__(self):
        self.instanceVar = "I'm an instance var."
    def fun(self):
        methodVar = "I'm a method var; I cannot be accessed outside of this method."
        self.instanceVar2 = "I'm another instance var, set outside of __init__."

A Note on "methods" vs "functions"

In your question, you call sing_me_a_song a "function." In reality, it is a method of the class Song . This is different from a regular old function, because it is fundamentally linked up with the class, and thus objects of that class as well.

When you define the init function, you'll notice that the first argument is "self" - this is a reference to the object that is being created. When you do "self.lyrics = lyrics", this is actually assigning the value to an attribute of the object, not a variable.

So when you then go to access it elsewhere, it is visible - but not because it's a variable! You're right in thinking that, were we following normal scope rules, it shouldn't be visible. However, it's not a variable, and any code can access the value of self.lyrics, so long as they have a reference to the object.

eg:

test = Song(["This is some lyrics."])
test.sing_me_a_song() #this works
print test.lyrics[0] #but so does this!

As per the code, self.lyrics is defined in the constructor of the class. The constructor is always called first when creating an object. There by self.lyrics can be used in other class methods.

self is used to refer to the actual instance of the Song class that the method is being called on. For instance, if you do...

foo = Song("hello")
bar = Song("world")

then foo.lyrics is set to "hello" , and bar.lyrics is set to "world" . If you then call a method on one of these instances, like so...

foo.sing_me_a_song()

Then the method is called with self set to foo , and thus self.lyrics looks up "hello" because it's the instance in foo that had its lyrics set to "hello" .

It's important to realize that it's not a class definition in quite the same way that java or c++ defines a class.

Self is a dynamic object. Be it self, or any other object, myObj.newField = value is always a valid thing to do. since the init was run when the object was initialized, there is a self.lyrics element.

you could have


def foo(self):
    self.thing = "turtle"

and then in any function that was called after foo, you could refrence self.thing. (this is probably a very bad idea, but there's nothing syntactically wrong about it).

The name self isn't anything special. In python, every method of an object takes a reference to that object as it's first parameter, automatically.

This means that in the __init__ (constructor) method, your setting the attribute lyrics on the object. Later on, you can call sing_me_a_song , and that will get a reference to the same object with lyrics attribute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM