Python 2.7 类(一)


Python的类机制提供了面向对象编程的所有标准特性:

  • 多重继承
  • 子类重写基类的方法
  • 方法可以通过相同的名称调用基类方法
  • 对象可以包含任意数量与类型的数据

与模块相同,类同样具有Python的动态特性:运行时创建并且可以在创建后修改。

通常类成员都是公共成员,所有的成员函数都是虚函数。
在成员方法中引用对象成员没有简便的写法:成员方法声明时显式使用第一个参数代表对象,调用时这个参数被隐式提供。
类也是对象,可以引入与重命名。
内置类型可以作为基类被用于扩展。
大多数内置操作符可以被类实例重定义。

1 名称与对象

同一个对象可以绑定多个名称。
这一类似于别名的机制有时可以看作指针。

2 Python 范围与命名空间

命名空间是名称与对象的映射。
现在大多数命名空间作为Python字典实现。
一些命名空间示例:内置名称集合、模块的全局名称、方法声明中的本地名称。
不同命名空间中的名称没有关系。

严格地说,模块中名称的引用就是属性引用。
eg:modname.funcname中,modname是模块对象,funcname是模块对象的属性。
模块的属性与定义在模块中的全局名称共享相同的命名空间。

属性可以为只读,也可以为可写。
模块的属性是可写的。
可写属性可以被del语句删除。

不同时刻创建的命名空间具有不同的生命周期。
当Python解释器启动时,包含内置名称的命名空间将会被创建,并且不会被删除。
当模块定义被读取时,模块的全局命名空间将被创建。
通常情况下,模块的命名空间将会存活到解释器退出。
通过解释器的高级调用(无论是读取脚本文件或交互)执行的语句将会被认为是模块__main__的一部分,所以它们具有自己独有的全局命名空间。(内置名称实际上也存活于模块中,此模块被称为__builtin__)。

当一个函数被调用时,函数的本地命名空间将会被创建,并且当函数返回或提出一个没有被函数处理的异常时,此命名空间将会被删除。
递归的调用,每一层递归都有属于自己的本地命名空间。

范围是Python程序的文本区域,在范围中可以直接访问命名空间。
在执行期间,至少由三个内嵌范围可以被命名空间直接访问:

  • 被首先搜索的最内层范围包含本地名称
  • 从最内层封闭范围开始搜索的封闭函数的范围包括非局部,非全局的名称
  • 倒数第二个范围包含当前模块的全局名称
  • 被最后搜索的最外层范围是包含内置名称的命名空间

在最内存范围之外的命名空间中找到的变量是只读的,试图写入一个外部变量将会导致在内部范围创建一个新的本地变量。

通常情况下,本地范围引用当前函数的的本地名称。在函数的外部,本地范围引用与全局范围相同的命名空间,模块的命名空间。
类定义在本地范围中放置另一个命名空间。

范围由文本决定。
模块中定义的函数的全局范围是模块的命名空间。
实际上,对名称的搜索是在运行是动态完成的,然而,对名称的解析是静态的。

如果全局语句没有生效,对名称的赋值将会进入最内层范围。
赋值没有赋值数据,只是为对象绑定名称。

实际上,所有引入新名称的操作都使用本地范围。
特别是,import语句与函数定义将模块名或函数名绑定进本地范围。

3 类简介
3.1 类定义语法
# 定义类
class Ccc:
	pass

类定义,与函数定义类似,必须在使用前被执行。
实际上,类定义中的语句通常为函数定义.
类中定义的函数通常有特定的形式,这由方法调用约定决定。

当进入一个类定义之后,将会创建一个新的命名空间,用作局部范围,因此,对本地变量的所有赋值操作都会进入这个新的命名空间。特别是,函数定义绑定新的函数的名称。

当离开一个类定义之后,一个类对象将会被创建。类对象将类定义创建的命名空间中的内容包装起来。原始本地范围将会被恢复,并且这个类对象将会与类定义首部中给定的类名称绑定。

3.2 类对象

类对象支持两种操作:属性引用与实例化。

# 类定义
class Ccc:
    "a simple example"
    
    i = 1321

    def ff(self, arg):
        print arg

    def __init__(self, x, y):
        self.x = x
        self.y = y

# 引用属性
Ccc.i

# 引用方法对象
Ccc.ff

# 修改类属性
Ccc.i = 666

# 获取类的文档字符串
Ccc.__doc

# 实例化类
x = Ccc(123, 456)

# 访问实例对象属性
x.x
x.y
3.3 实例对象

实例对象唯一理解的操作是属性引用。
实例对象中存在两种有效属性,数据属性与方法。
数据属性不需要被声明,就像本地变量,它们会在第一次被赋值时存在。
方法是属于对象的函数。方法对象与类函数不同,方法对象不是一个函数对象。

# 类定义
class dd:
    pass

# 实例化
x = dd()

# 添加属性
x.counter = 1

# 删除属性
del x.counter
3.4 方法对象
# 定义类
class dd:
    def ff(self):
        print "cccc"

# 实例化
x = dd()

# 调用方法
x.ff()

# 存储方法对象
gg = x.ff
gg()

当一个实例的非数据属性被引用时,实例的类将会被搜索。如果属性名称是一个函数对象的有效类属性,一个方法对象将会通过包装实例对象与方法对象被创建。当一个方法对象通过一个参数列表调用时,一个新的参数列表将会通过实例对象与参数列表创建出来,函数对象将会通过这个新的参数列表进行调用。

3.5 类变量与实例变量

通常来说,实例变量用于每个实例唯一的数据,类变量用于所有类实例共享的属性与方法。

# 类定义
class d:
    kind = "dog"

    def __init__(self, name):
        self.name = name
        self.ttt = []

    tricks = []
    def add_trick(self, trick):
        self.tricks.append(trick)

    def add_ttt(self, ttt):
        self.ttt.append(ttt)

# 实例化
dd = d('Fido')
ee = d("Buddy")

# 访问属性
print dd.kind
print ee.kind
print dd.name
print ee.name

# 修改可变对象(一个实例修改,所有实例全部受到影响)
dd.add_trick('iii')
ee.add_trick('ppp')

# 修改可变对象(实力修改只会影响自身)
dd.add_ttt('iii')
ee.add_ttt('ppp')
4 注意事项

数据属性可以重写具有相同名称的方法属性,为了避免命名冲突,一般采用一些命名约定最小化冲突的可能。

数据属性可以被方法引用,换句话说,类不能被实现为纯抽象数据类型。实际上,Python不能强制实现数据隐藏,数据隐藏一般通过约定完成。(另一方面,C编写的Python可以完全隐藏实现细节并且控制对对象的访问,这可以用于基于C编写的Python扩展。)

客户端要小心使用数据属性,因为客户端可能会通过标记数据属性破坏方法维护的不变性。

在方法中引用数据属性与其他方法时没有缩写形式。

方法的第一个参数常常称为self。不过这只是一个约定,名称self对于Python来说并没有特别的含义。

类的函数对象定义了类对应实例的方法对象。将函数定义以文本形式包含在类定义中并不是必要的,将函数对象复制给类对象也可以。

def ff(self, x, y):
    print 'ccc'
    
class C:
    f = ff
    def g(self):
        print 'hhh'
    h = g

方法可以通过self参数调用其他方法。

方法引用全局名称的方法与普通函数相同。关联方法的全局范围是包含方法定义的模块。
引入全局范围的函数与模块可以被方法使用,就像函数与类定义在其中一样。通常情况下,包含方法的类其本身就定义在全局范围内。

由于所有值都是对象,因此每一个值都有类型。它存储在object. __class__之中。


详细教程:Python 2.7 tutorial

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值