Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7919004
  • 博文数量: 701
  • 博客积分: 2150
  • 博客等级: 上尉
  • 技术积分: 13233
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:28
个人简介

天行健,君子以自强不息!

文章分类

全部博文(701)

文章存档

2019年(2)

2018年(12)

2017年(76)

2016年(120)

2015年(178)

2014年(129)

2013年(123)

2012年(61)

分类: Python/Ruby

2014-09-19 18:05:50

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) |
给主人留下些什么吧!~~