2020
2121## ` self ` {#self}
2222
23- 类方法与普通函数只有一种特定的区别——前者必须有一个额外的名字 ,这个名字必须添加到参数列表的开头,但是你* 不用* 在你调用这个功能时为这个参数赋值,Python 会为它提供。这种特定的变量引用的是对象_本身_ ,按照惯例,它被赋予 ` self ` 这一名称。
23+ 类方法与普通函数只有一种特定的区别——前者必须多加一个参数在参数列表开头 ,这个名字必须添加到参数列表的开头,但是你* 不用* 在你调用这个功能时为这个参数赋值,Python 会为它提供。这种特定的变量引用的是对象_本身_ ,按照惯例,它被赋予 ` self ` 这一名称。
2424
2525尽管你可以为这一参数赋予任何名称,但是_强烈推荐_你使用 ` self ` 这一名称——其它的任何一种名称绝对会引人皱眉。使用一个标准名称能带来诸多好处——任何一位你的程序的读者能够立即认出它,甚至是专门的 IDE(Integrated Development Environments,集成开发环境)也可以为你提供帮助,只要你使用了 ` self ` 这一名称。
2626
2727> ** 针对 C++/Java/C# 程序员的提示**
2828>
29- > Python 中的 ` self ` 相当于 C++ 中的指针以及 Java 与 C# 中的 ` this ` 指针 。
29+ > Python 中的 ` self ` 相当于 C++ 中的 ` this ` 指针以及 Java 与 C# 中的 ` this ` 引用 。
3030
3131你一定会在想 Python 是如何给 ` self ` 赋值的,以及为什么你不必给它一个值。一个例子或许会让这些疑问得到解答。假设你有一个 ` MyClass ` 的类,这个类下有一个实例 ` myobject ` 。当你调用一个这个对象的方法,如 ` myobject.method(arg1, arg2) ` 时,Python 将会自动将其转换成 ` MyClass.method(myobject, arg1, arg2) ` ——这就是 ` self ` 的全部特殊之处所在。
3232
33- 这同时意味着,如果你有一个没有参数的功能 ,你依旧必须拥有一个参数——` self ` 。
33+ 这同时意味着,如果你有一个没有参数的方法 ,你依旧必须拥有一个参数——` self ` 。
3434
3535## 类 {#class}
3636
8080
8181** 它是如何工作的**
8282
83- 在本例中,我们定义 ` __init__ ` 方法用以接受 ` name ` 参数(与更普遍的 ` self ` 一道) 。在这里,我们创建了一个字段,同样称为 ` name ` 。要注意到尽管它们的名字都是“name”,但这是两个不相同的变量。虽说如此,但这并不会造成任何问题,因为点号 ` self.name ` 意味着这个叫作 “name”的东西是某个叫作“self”的对象的一部分,而另一个 ` name ` 则是一个局部变量。由于我们已经如上这般明确指出了我们所指的是哪一个名字,所以它不会引发混乱。
83+ 在本例中,我们定义一个接受 ` name ` 参数(当然还有 ` self ` 参数)的 ` __init__ ` 方法 。在这里,我们创建了一个字段,同样称为 ` name ` 。要注意到尽管它们的名字都是“name”,但这是两个不相同的变量。虽说如此,但这并不会造成任何问题,因为 ` self.name ` 中的点号意味着这个叫作 “name”的东西是某个叫作“self”的对象的一部分,而另一个 ` name ` 则是一个局部变量。由于我们已经如上这般明确指出了我们所指的是哪一个名字,所以它不会引发混乱。
8484
8585当我们在 ` Person ` 类下创建新的实例 ` p ` 时,我们采用的方法是先写下类的名称,后跟括在括号中的参数,形如:` p = Person('Swaroop') ` 。
8686
9393
9494我们已经讨论过了类与对象的功能部分(即方法),现在让我们来学习它们的数据部分。数据部分——也就是字段——只不过是_绑定(Bound)_ 到类与对象的** 命名空间(Namespace)** 的普通变量。这就代表着这些名称仅在这些类与对象所存在的上下文中有效。这就是它们被称作_ “命名空间”_ 的原因。
9595
96- _ 字段(Filed )_ 有两种类型——类变量与对象变量,它们根据究竟是类还是对象_拥有_这些变量来进行分类。
96+ _ 字段(Field )_ 有两种类型——类变量与对象变量,它们根据究竟是类还是对象_拥有_这些变量来进行分类。
9797
9898** 类变量(Class Variable)** 是共享的(Shared)——它们可以被属于该类的所有实例访问。该类变量只拥有一个副本,当任何一个对象对类变量作出改变时,发生的变动将在其它所有实例中都会得到体现。
9999
@@ -113,7 +113,7 @@ _字段(Filed)_有两种类型——类变量与对象变量,它们根据
113113
114114除了 ` Robot.popluation ` ,我们还可以使用 ` self.__class__.population ` ,因为每个对象都通过 ` self.__class__ ` 属性来引用它的类。
115115
116- ` how_many ` 实际上是一个属于类而非属于对象的方法。这就意味着我们可以将它定义为一个 ` classmethod(类方法) ` 或是一个 ` staticmethod(静态方法) ` ,这取决于我们是否知道我们需不需要知道我们属于哪个类 。由于我们已经引用了一个类变量,因此我们使用 ` classmethod(类方法) ` 。
116+ ` how_many ` 实际上是一个属于类而非属于对象的方法。这就意味着我们可以将它定义为一个 ` classmethod(类方法) ` 或是一个 ` staticmethod(静态方法) ` ,这取决于我们是否需要知道这一方法属于哪个类 。由于我们已经引用了一个类变量,因此我们使用 ` classmethod(类方法) ` 。
117117
118118我们使用[ 装饰器(Decorator)] ( ./18.more.md#decorator ) 将 ` how_many ` 方法标记为类方法。
119119
@@ -151,7 +151,7 @@ how_many = classmethod(how_many)
151151
152152这种方法有诸多优点。如果我们增加或修改了 ` SchoolMember ` 的任何功能,它将自动反映在子类型中。举个例子,你可以通过简单地向 SchoolMember 类进行操作,来为所有老师与学生添加一条新的 ID 卡字段。不过,对某一子类型作出的改动并不会影响到其它子类型。另一大优点是你可以将某一老师或学生对象看作 ` SchoolMember ` 的对象并加以引用,这在某些情况下会大为有用,例如清点学校中的成员数量。这被称作** 多态性(Polymorphism)** ,在任何情况下,如果父类型希望,子类型都可以被替换,也就是说,该对象可以被看作父类的实例。
153153
154- 同时还需要注意的是我们重用父类的代码,但我们不需要再其它类中重复它们 ,当我们使用独立类型时才会必要地重复这些代码。
154+ 同时还需要注意的是我们重用父类的代码,但我们不需要再在其它类中重复它们 ,当我们使用独立类型时才会必要地重复这些代码。
155155
156156在上文设想的情况中,` SchoolMember ` 类会被称作** 基类(Base Class)** [ ^ 4 ] 或是** 超类(Superclass)** 。` Teacher ` 和 ` Student ` 类会被称作** 派生类(Derived Classes)** [ ^ 5 ] 或是** 子类(Subclass)** 。
157157
0 commit comments