简体   繁体   English

Python类声明中的变量用法

[英]Variable Usage in Python Class Declaration

Here is a code snippet from Zed Shaw's "Learn Python the Hard Way" tutorial 40: 这是Zed Shaw的“以困难的方式学习Python”教程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? 为什么在定义“ sing_me_a_song”函数时Python允许使用“ self.lyrics”? Is it because whatever variable is defined under " init " can also be used elsewhere in the same class? 是否因为在“ init ”下定义的任何变量也可以在同一类的其他地方使用?

Thanks. 谢谢。

Instance Variables 实例变量

This is called an instance variable. 这称为实例变量。 Any variable defined with self. self.定义的任何变量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. 通常,此类变量是在__init__中创建的,因此尽管您可以在其他方法中定义实例变量,但也可以从初始化对象开始就对其进行访问。 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__ ; 注意在__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." 在您的问题中,您将sing_me_a_song称为“函数”。 In reality, it is a method of the class Song . 实际上,它是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. 定义init函数时,您会注意到第一个参数是“ self”-这是对正在创建的对象的引用。 When you do "self.lyrics = lyrics", this is actually assigning the value to an attribute of the object, not a variable. 当您执行“ self.lyrics =歌词”时,实际上是将值分配给对象的属性,而不是变量。

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. 但是,它不是变量,并且任何代码都可以访问self.lyrics的值,只要它们具有对该对象的引用即可。

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. 根据代码, self.lyrics是在类的构造函数中定义的。 The constructor is always called first when creating an object. 创建对象时,始终首先调用构造函数。 There by self.lyrics can be used in other class methods. 通过self.lyrics可以在其他类方法中使用。

self is used to refer to the actual instance of the Song class that the method is being called on. self用于引用调用该方法的Song类的实际实例。 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" . 然后foo.lyrics设置为"hello" ,而bar.lyrics设置为"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" . 然后在self设置为foo情况下调用该方法,因此self.lyrics查找"hello"因为foo中的实例的lyrics设置为"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. 重要的是要意识到它不是类定义,与java或c ++定义类的方式完全不同。

Self is a dynamic object. 自我是一个动态的对象。 Be it self, or any other object, myObj.newField = value is always a valid thing to do. 无论是自身还是任何其他对象, myObj.newField = value始终是有效的操作。 since the init was run when the object was initialized, there is a self.lyrics element. 由于初始化是在初始化对象时运行的,因此存在self.lyrics元素。

you could have 你可以有


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

and then in any function that was called after foo, you could refrence self.thing. 然后在foo之后调用的任何函数中,您都可以引用self.thing。 (this is probably a very bad idea, but there's nothing syntactically wrong about it). (这可能是一个非常糟糕的主意,但是在语法上没有错)。

The name self isn't anything special. self这个名字没什么特别的。 In python, every method of an object takes a reference to that object as it's first parameter, automatically. 在python中,对象的每个方法都会自动引用该对象作为其第一个参数。

This means that in the __init__ (constructor) method, your setting the attribute lyrics on the object. 这意味着在__init__ (构造函数)方法中,您可以在对象上设置属性lyrics Later on, you can call sing_me_a_song , and that will get a reference to the same object with lyrics attribute. 稍后,您可以调用sing_me_a_song ,这将获得对具有歌词属性的同一对象的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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