如果说类是一种数据结构定义类型,那么实例则声明了一个这种类型的变量。#实例是那些主要用在运行期时的对象,类被实例化得到实例,该实例的类型就是这个被实例化的类。## 4.1 初始化:通过调用类对象来创建实例#实例化的实现,可以使用函数操作符:#class c1(object):# def showName(self,name):# print('name is:',name)#c3=c1()## 4.2 __init__() "构造器"方法#当类被调用,实例化的第一步是创建实例对象。一旦对象创建了,Py
thon 检查是否实现了__init__()方法。#默认情况下,如果没有定义(或覆盖)特殊方法__init__(),对实例不会施加任何特别的操作.任何所需的特定操作,#都需要程序员实现__init__(),覆盖它的默认行为。如果__init__()没有实现,则返回它的对象,实例化过程完毕。##然而,如果__init__()已经被实现,那么它将被调用,实例对象作为第一个参数(self)被传递#进去,像标准方法调用一样。调用类时,传进的任何参数都交给了__init__()。实际中,你可以想#像成这样:把创建实例的调用当成是对构造器的调用。#__init__()是很多为类定义的特殊方法之一。其中一些特殊方法是预定义的,缺省情况下,不#进行任何操作,比如__init__(),要定制,就必须对它进行重载,还有些方法,可能要按需要去实现.## 4.3 __new__() “构造器”方法#与__init__()相比,__new__()方法更像一个真正的构造器。Python 用户可以对内建类型进行派生,#因此,需要一种途径来实例化不可变对象,比如,派生字符串,数字,等等#在这种情况下,解释器则调用类的__new__()方法,一个静态方法,并且传入的参数是在类实例#化操作时生成的。__new__()会调用父类的__new__()来创建对象(向上代理)。#__new__()必须返回一个合法的实例,这样解释器在调用__init__()时,就可以把这个实例作为self 传给它。调用父类的__new__()#来创建对象,正像其它语言中使用new 关键字一样。__new__()和__init__()在类创建时,都传入了(相同)参数。## 4.4 __del__() "解构器"方法#由于Python 具有垃圾对象回收机制(靠引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才会执行。#Python 中的解构器是在实例释放前提供特殊处理功能的方法,它们通常没有被实现,因为实例很少被显式释放。#核心笔记:跟踪实例#Python 没有提供任何内部机制来跟踪一个类有多少个实例被创建了,或者记录这些实例是些什#么东西。如果需要这些功能,你可以显式加入一些代码到类定义或者__init__()和__del__()中去。#最好的方式是使用一个静态成员来记录实例的个数。靠保存它们的引用来跟踪实例对象是很危险的,#因为你必须合理管理这些引用,不然,你的引用可能没办法释放(因为还有其它的引用)!看下面一个例子:#class InstCt(object):# count = 0 # count is class attr count 是一个类属性# def __init__(self): # increment count 增加count# InstCt.count += 1# def __del__(self): # decrement count 减少count# InstCt.count -= 1# def howMany(self): # return count 返回count# print(InstCt.count) ##c1=InstCt()#c2=InstCt()##c1.howMany()#c2.howMany()#c1.__del__()#c2.howMany()#-->#2#2#1#*********** Part 5:
实例属性 ***********************#实例仅拥有数据属性(方法严格来说是类属性),后者只是与某个类的实例相关联的数据值,并#且可以通过句点属性标识法来访问。这些值独立于其它实例或类。当一个实例被释放后,它的属性同时也被清除了。## 5.1 “实例化”实例属性(或创建一个更好的构造器)#设置实例的属性可以在实例创建后任意时间进行,也可以在能够访问实例的代码中进行。构造器__init()__是设置这些属性的关键点之一。####在构造器中首先设置实例属性#构造器是最早可以设置实例属性的地方,因为__init__()是实例创建后第一个被调用的方法。#再没有比这更早的可以设置实例属性的机会了。一旦__init__()执行完毕,返回实例对象,即完成了实例化过程。####默认参数提供默认的实例安装#在实际应用中,带默认参数的__init__()提供一个有效的方式来初始化实例。在很多情况下,#默认值表示设置实例属性的最常见的情况,如果提供了默认值,我们就没必要显式给构造器传值了。#需要明白一点,默认参数应当是不变的对象;像列表(list)和字典(dictionary)这样的可变对象可以扮演静态数据,#然后在每个方法调用中来维护它们的内容。#class c1(object):# def __init__(self,name,sex='man'):# print('name:%s,sex:%s' %(name,sex))#c2=c1('dave')#-->name:dave,sex:man#注意:__init__()应当返回None#你也知道,采用函数操作符调用类对象会创建一个类实例,也就是说这样一种调用过程返回的对象就是实例。#如果定义了构造器,它不应当返回任何对象,因为实例对象是自动在实例化调用后返回的。相#应地,__init__()就不应当返回任何对象(应当为None);否则,就可能出现冲突,因为只能返回实例。#class c1(object):# def __init__(self,name,sex='man'):# print('name:%s,sex:%s' %(name,sex))# return 1#c2=c1('dave')#-->TypeError: __init__() should return None, not 'int'## 5.2 查看实例属性#可是使用dir() 或者类的__dict__属性查看。 这个在3.3 节有示例。## 5.3 特殊的实例属性#实例仅有两个特殊属性。对于任意对象I:# I.__class__ 实例化I 的类# I.__dict__ I 的属性#class C(object): # define class 定义类# pass##c = C() # create instance 创建实例#print(dir(c)) # instance has no attributes 实例还没有属性#print(c.__dict__) # yep, definitely no attributes 也没有属性#print(c.__class__) # class that instantiated us 实例化c 的类#-->#[]#{}##c 现在还没有数据属性,添加一些再来检查__dict__属性,看是否添加成功了:#c.foo = 1#c.bar = 'SPAM'#print(c.__dict__)#-->#{'foo': 1, 'bar': 'SPAM'}#dict__属性由一个字典组成,包含一个实例的所有属性。键是属性名,
值是属性相应的数据值。字典中仅有实例属性,没有类属性或特殊属性。## 5.4 内建类型属性#内建类型也是类,对内建类型也可以使用dir(),与任何其它对象一样,可以得到一个包含它属性名字的列表:#x = 3+0.14j#print(x.__class__)#-->#print(dir(x))#-->['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', # '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', # '__hash__', '__init__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', # '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', # '__rfloordiv__', '__rmod__', '__rmul__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', # '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', 'conjugate', 'imag', 'real']#print(x.imag)#-->0.14#在内建类型中,不存在__dict__属性:#print(x.__dict__)#-->AttributeError: 'complex' object has no attribute '__dict__'## 5.5 实例属性 vs 类属性#类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关。这些值像静态成员那样被引用,即使在多次实例化中调用类,#它们的值都保持不变。不管如何,静态成员不会因为实例而改变它们的值,除非实例中显式改变它#们的值。(实例属性与类属性的比较,类似于自动变量和静态变量,但这只是笼统的类推。#类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的。###访问类属性#类属性可通过类或实例来访问.###从实例中访问类属性须谨慎#与通常Python 变量一样,任何对实例属性的赋值都会创建一个实例属性(如果不存在的话)并#且对其赋值。如果类属性中存在同名的属性,有趣的副作用即产生。###类属性持久性#静态成员,如其名所言,任凭整个实例(及其属性)的如何进展,它都不理不采(因此独立于#实例)。同时,当一个实例在类属性被修改后才创建,那么更新的值就将生效。类属性的修改会影响#到所有的实例