多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
### 7.2.2 对象的创建 一旦定义了类,就可以创建类的实例,也就是该类的一个对象②。类是抽象的,而对象 则是具体的,就好比“人”是抽象概念,而“张三”是个具体的人。一个类可以创建任意多 个实例(对象),所有实例都具有相同的行为(这是由类中定义的方法决定的),但各自的数 据值可以不同。创建类的实例采用如下形式: ``` <变量> = <类名>(<参数>) ``` 这里将类名当成一个函数来用,称为类的构造器(constructor,或称构造函数)。构造器返回 一个新对象,通常需要定义&lt;变量&gt;来引用这个新对象。注意,虽然&lt;变量&gt;只是对新对象的引 用,但习惯上我们也常说&lt;变量&gt;就是新对象本身,这一般不会产生混淆。 如果希望创建对象时将对象定制成特定的初始状态,则可以在类中定义特殊的 \_\_init\_\_ 方法③。创建新对象时,Python 自动调用 \_\_init\_\_,实现对新对象的初始化,比如为该对象所 拥有的数据进行赋值。 \_\_init\_\_ 方法可以用参数(至少有一个 self 参数)来传递初始化所需的信息,调用 \_\_init\_\_ 时必须提供相应的实参。但由于 \_\_init\_\_ 不是直接调用的,无法直接将实 参传递给它,所以我们将所需实参传递给构造器,再由构造器自动传递给 \_\_init\_\_ 。不过,\_\_init\_\_ 的特殊参数 self 是一个例外,传递给 self 的实参是新创建的对象(更准确地说是对新 建对象的引用)。 > ① 如 Pascal 语言中的 record 和 C 语言中的 struct 类型。 > ② 本书中混用“实例”和“对象”这两个术语,视之为相同的概念。 > ③ 也可以说 init ()才是类的构造器,不过不能直接调用,而是通过类名来隐含地调用。 例如,下面的语句先导入 Person 类,然后创建一个 Person 对象,并使变量 p1 引用该对象: ``` >>> from person import Person >>> p1 = Person("Lucy",2005) ``` 创建对象时自动调用 init__方法,该方法所需的三个参数 self、n、y 分别用实参 p1、"Lucy"和 2005 代入,这相当于函数调用 ``` __init__ (p1,"Lucy",2005) ``` 从而导致执行 \_\_init\_\_的函数体,为新对象进行初始化: ``` p1.name = "Lucy" p1.year = 2005 ``` 图 7.6 给出了上述利用 Person 构造器创建对象 p1 并调用 \_\_init\_\_进行初始化的过程。 ![](https://box.kancloud.cn/2016-02-22_56cafce3f204c.png) 图 7.6 对象创建与初始化 注意, init 方法中对变量 name 和 year 所赋的值"Lucy"和 2005,是专属于新实例 p1 的,它们与同一个类的其他实例(例如下面将创建的 p2)没有关系。这两个变量都属于实例 变量(instance variable),意即它们的值是随实例的不同而不同的。下面再创建一个 Person 对象,并使变量 p2 引用这个新对象: ``` >>> p2 = Person("Tom",1990) ``` 同样地,Python 自动调用 init 方法,只不过这次传递给该方法的参数是 p2、"Tom"和 1990, 即相当于函数调用 ``` __init__ (p2,"Tom",1990) ``` 从而导致执行 \_\_init\_\_的函数体,为新对象 p2 进行初始化: ``` p2.name = "Tom" p2.year = 1990 ``` 这里,对实例变量 name 和 year 所赋的值"Tom"和 1990 是专属于新实例 p2 的,与前面创建的实例 p1 没有关系。创建同一个类的多个实例的过程可参见图 7.7。 ![](https://box.kancloud.cn/2016-02-22_56cafce40ec05.png) 图 7.7 创建同一个类的多个实例 从图 7.7 可见,类与实例的关系就像模具与产品的关系,用同一个模具可以制造出大量 的产品,这些产品总体上是相似的,但可能各有不同的细节。p1 与 p2 是属于同一类的对象, 总体上非常相似,例如都有数据 name 和 year,但各有不同的数据值。