1. 1. 引言
1. 类与实例
可以定义一个本身没有任何属性的类,而仅把它用做数据的名字空间,这样的类仅作为容器对象来共享名字空间。
示例如下:
class MyData(object):
pass
下面创建它的实例,它只使用类作为名称空间容器。
>>> mathObj = MyData()
>>> mathObj.x = 4
>>> mathObj.y = 5
>>> mathObj.x + mathObj.y
9
>>> mathObj.x * mathObj.y
20
我们当然也可以使用变量"x", "y"来完成同样的事情,
但在本例中,实例名字mathObj将mathObj.x和mathObj.y关联起来,这就是我们所说的使用类作为名字空间容器。
mathObj.x和mathObj.y是实例属性,因为它不是类MyData的属性,而是实例对象(mathObj)的独有属性。
2. 方法
在Python中,方法定义在类定义中,但只能被实例所调用。
也就是说,调用一个方法的最终途径必须是这样的:
(1) 定义类(和方法);
(2) 创建一个实例;
(3) 用这个实例调用方法。
例如:
class MyDataWithMethod(object): # 定义类
def printFoo(self): # 定义方法
print ‘You invoked printFoo()!'
实例化这个类,然后调用那个方法:
>>> myObj = MyDataWithMethod() # 创建实现
>>> myObj.printFoo() # 调用方法
You invoked printFoo()!
3. 创建一个类(类定义)
class AddrBookEntry():
def __init__(self, nm, ph): # 定义构造器
self.name = nm
self.phone = ph
print 'Created instance for : ’,self.name
def updatePhone(self, newph): # 定义方法
self.phone = newph
print 'Updated phoen # for:', self.name
在AddrBookEntry类的定义中,定义了两个方法: __init__()和updatePhone().
__ini__()在实例化时被调用,即,在AddrBookEntry()被调用时。
可以认为实例化是对__init__()的一种隐式调用,因为传给AddrBookEntry()的参数完全与__init__()接收到的参数一样。
4. 创建实例(实例化)
>>> john = AddrBookEntry('John Doe', '408-555-1212') # 为 John Doe创建实例
>>> jane = AddrBookEntry('Jane Doe', '650-555-1212') # 为 Jane Doe创建实例
这就是实例化调用,它会自动调用__init__()。self把实例对象自动传入__init__()。
另外,如果不存在默认的参数,那么传给__init__()的两个参数在实例化时是必须的。
5. 访问实例属性
>>> john
<__main__.AddrBookEntry instance at 80ee610>
>>> john.name
'John Doe'
>>> jane.phone
'650-555-1212'
6. 方法调用(通过实例)
>>> john.updatePhone('415-555-1212') # 更新 John Doe的电话
>>> john.phone
'415-555-1212'
7. 创建子类
靠继承来进行子类化是创建和定制新类类型的一种方式,
新的类的将保持已存在类的所有特性,会改动原来类的定义。
对于新类类型而言,这个子类可以定制只属于它的特定功能。
注意下面,子类声明中提到了父类:
class EmplAddrBookEntry(AddrBookEntry):
def __init__(self, nm, ph, id, em):
AddrBookEntry.__init__(self, nm, ph)
self.empid = id
self.email = em
def updateEmail(self.newem):
self.email = newem
print 'Updated e-mail address for :', self.name
如果需要,每个子类最好定义它自己的构造器,不然,基类的构造器会被调用。
然而,如果子类重写基类的构造器,基类的构造器就不会被自动调用了---这样,
基类的构造器就必须显式写出才会被执行,像上面那样。
注意、这里我们要显式传递self实例对象给基类构造器,
因为我们不是在该实例中而是在一个子类实例中调用那个方法
因为我们不是通过实例来调用它,这种未绑定的方法调用需要传递一个适当的实例(self)给方法。
8. 使用子类
>>> john = EmplAddrBookEntry('John Doe', '408-555-1212', 42, 'john@spam.doe')
Created instance for : John Doe
>>> john
<__main__. EmplAddrBookEntry object at 0x62030>
>>> john.name
'John Doe'
>>> john.updatePhone('415-555-1212')
Updated phone
>>> john.phone
'415-555-1212'
>>> john.updateEmail('john@doe.spam')
Updated e-mail address for: John Doe
>>> john.email
'john@doe.spam'
1.2 面向对象编程
1.3 类
类是一种数据结构,我们可以用它来定义对象,后者把数据值和行为特性融合在一起。
在Python中,类声明如下:
class ClassName(object):
class_suite
1.3.1 创建类
class ClassName(bases):
class_suite
1.3.2 声明与定义
对于Python来说,声明与定义是同时进行的。
请注意,Python并不支持纯虚函数或者抽象方法,
作为替代方法,可以在基类方法中引发NotImplementedError异常,这样可以获得类似的效果。
1.4 类属性
类属性仅与其被定义的类相绑定,
实例数据属性是将会一直用到的主要数据属性。
通常,Python中的所有方法都有一个限制: 在调用前,需要创建一个实例。
1.4.1 类的数据属性
数据属性仅仅是所定义的类的变量。它们可以像任何其他变量一样在类创建后被使用,
并且,要么是由类中的方法来更新,要么是在主程序其他什么地方被更新。
它即是OO中的静态变量,或者是静态数据。
它们表示这些数据是与它们所属的类对象绑定的,不依赖于任何类实例,
相当于Java或C++中的变量声明前加上了static.
静态成员通常仅用来跟踪与类相关的值。
大多数情况下,你会考虑实例属性,而不是类属性。
下面的例子,先看类数据属性:
>>> class C(object):
... foo = 100
>>> print C.foo
100
>>> C.foo = C.foo + 1
>>> print C.foo
101
上面的代码中,看不到任何类实例的引用。
1.4.2 Methods
1. 方法
方法,比如下面,类MyClass中的myNoActionMethon方法,
仅仅是一个作为类定义一部分定义的函数(这使得方法成为类属性)。
这表示myNoActionMethod仅应用在MyClass类型的对象(实例)上。
这里,,myNoActionMethod是通过句点属性标识法与它的实例绑定的。
>>> class MyClass(object):
def myNoActionMethod(self):
pass
>>> mc = MyClass()
>>> mc.myNoActionMethod()
任何像函数一样的对myNoActionMethod自身的调用都将失败。
甚至由类对象调用此方法也是会失败的。
2. 绑定
为与OOP惯例保持一致,Python严格要求,没有实例 ,方法是不能被调用 的。
这种限制即Python所描述的绑定概念(binding).在此,方法必须绑定到一个实例才能被直接被调用。
1.4.3 查看类的属性
要知道一个类有哪些属性,有两种方法:
使用dir()内建函数,
或访问类的字典属性 __dict__.
如对于类 MyClass
>>> dir(MyClass)
或
>>> MyClass.__dict__
1.4.4 特殊的类属性
对于任何类C, 下表显示了类C的所有特殊属性:
C.__name__ 类C的名字(字符串)
C.__doc__ 类C的文档字符串
C.__bases__ 类C的所有父类构成的元组
C.__dict__ 类C的属性
C.__module__ 类C定义所在的模块
C.__class__ 实例C对应的类
1.5 实例
类是一种数据结构的定义,实例则声明了这个类型的变量。
1.5.1 初始化:通过调用类对象来创建实例
实例化的实现,可以使用函数操作符,如下示:
>>> class MyClass(object): # 定义类
... pass
>>> mc = MyClass() # 初始化类
1.5.2 __init__()"构造器"方法
当类被调用, 实例化的第一步是创建实例对象。
一旦对象创建了,Python检查是否实现了__init__()方法。
默认情况下,如果没有定义(或覆盖)特殊方法__init__(),对实例不会施加任何特别的操作。
任何所需要的特定操作,都需要程序员实现__init__(), 覆盖它的默认行为。
如果__init__()没有实现,则返回它的对象,实例化过程完毕。
1.5.3 __del__()"解构器"方法
同样,有一个相应的特殊解构器方法名为__del__().
然而,由于Python具有垃圾对象回收机制(靠引用计数),这个函数要直到该实例对象所有的引用都被
清除掉后才会执行。
1.6 实例属性
实例仅拥有数据属性(方法严格来说是类属性),
这些值独立于其他实例或类,当一个实例被释放后,它的属性同时也被清除了。
1.6.1 “实例化”实例属性(或创建一个更好的构造器)
设置实例的属性可以在实例创建后任意时间进行,也可以在能够访问实例的代码中进行。
构造器__init__()是设置这些属性的关键点之一。
1. 在构造器中首先设置实例属性
2. 默认参数提供默认的实例安装
3. __init__()应当返回None
1.6.2 查看实例属性
内建函数dir()
或__dict__特殊属性。
1.6.3 实例属性VS类属性
类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的名字空间。
1. 访问类属性
类属性可以通过类或实例来访问。
类性能只能通过类来更新,不能通过实例来更新。
看下面的示例代码:
>>> class C(object): # 定义类
... version = 1.2 # 静态成员
...
>>> c = C() # 实例化
>>> C.version # 通过类来访问
1.2
>>> c.version # 通过实例来访问
1.2
>>> C.version += 0.1 # 通过类(只能这样)来更新
>>> C.version
1.3
>>> c.version
1.3
2. 从实例中只能访问类属性,不能更新
实际上这种更新是创建一个新的同名实例属性。
>>> class Foo(object):
... x = 1.5
>>> foo = Foo()
>>> foo.x
1.5
>>> foo.x = 1.7 # 想用实例来更新类属性
>>> foo.x # 访问是新建的实例属性
1.7
>>> Foo.x # 类属性没有变
1.5
>>> del foo.x # 删除实例属性后,被隐蔽的类属性就显示出来了
>>> foo.x # 类属性
1.5
>>> foo.x += .2 # 试着修改类属性
>>> foo.x
1.7
>>> Foo.x
1.5
3. 在类的方法中访问和修改实例的属性
>>> class Foo(object):
def updatex(self, value):
self.x = value
>>> foo = Foo()
>>> foo.x = 100
>>> foo.x
100
>>> foo.updatex(200)
>>> foo.x
200
从上面的示例代码看到,
在类的方法中可以访问或修改实例属性,它是通过'self'来实现的。
4. 类属性的修改会影响到所有实例
阅读(2182) | 评论(0) | 转发(0) |