原文地址:http://blog.csdn.net/imzoer/article/details/8737642
还记得什么是新式类和旧式类吗?Python 中,一个class
继承于object
,或其 bases class 里面任意一个继承于object
,这个class
都是 new-style class。
- 在 Python 中,类是可以多重继承的。Python 类中的所有成员变量都是类似 Java 语言中的
public
的。 - 在 Python 中,类中定义的函数也是对象。也可以修改赋值。
# -*- coding:utf-8 -*-
class A(object):
def f(self):
print "f"
def ff():
print "ff"
a=A()
a.f()
xf=a.f
xf()
a.f=ff
a.f()
这个例子的输出结果如下:
f
f
ff
通过上面的结果,可看出来,a.f=ff
的时候,对象a
中的函数已经被修改成ff
函数了。另外,xf
也是一个函数对象。
对于继承,Python 提供了两个函数:issubclass(
)和isinstance()
看例子:
>>> issubclass(bool,int)
True
>>>
结果输出是True
,说明bool
是int
的子类。
# -*- coding:utf-8 -*-
class A(object):
def a(self):
print "a"
if __name__ == "__main__":
a=A()
print isinstance(a,A)
主要还是学习一下多重继承的概念。Python 中多重继承的语法如下:
class Myclass(base1,base2,base3):
MRO
MRO 即 Method Resolution Order,主要用于在多继承时判断调的属性的路径(来自于哪个类)。
之前查看了很多资料,说 MRO 是基于深度优先
搜索算法的。但不完全正确。在 Python2.3 之前是基于此算法,但从 Python2.3 起应用了新算法:C3
算法。
为什么采用 C3 算法
C3 算法最早被提出是用于 Lisp 的,应用在 Python 中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。
- 本地优先级:指声明时父类的顺序,比如
C(A, B)
,如果访问C
类对象属性时,应该根据声明顺序,优先查找A
类,然后再查找B
类。 - 单调性:如果在
C
的解析顺序中,A
排在B
的前面,那么在C
的所有子类里,也必须满足这个顺序。
在新式类中,查找一个要调用的函数或者属性的时候,是广度优先
搜搜的。在旧式类当中,是深度优先
搜索的。如下图所示:
看下面的例子:
# -*- coding:utf-8 -*-
# 最好在 2.X 中测试
class D(object):
def foo(self):
print "class D"
class B(D):
pass
class C(D):
def foo(self):
print "class C"
class A(B, C):
pass
f = A()
f.foo()
例子中定义D
类的时候,D
是新式类,所以D
的所有子类都是新式类。A
的实例对象f
在调用foo
函数的时候,根据广度优先搜索原则,调用的是C
类里面的foo
函数。上面的代码输出class C
;如果定义D
类的时候直接class D
,而不是class D(object)
,那么上述代码就该输出class D
了。
需要说明的是,在 3.X 中运行代码时class D:
和class D(object)
的返回结果都是class C
,说明完全不再有深度优先支持;但在 2.X 中,class D:
的结果是class D
,说明 2.X 还是支持深度优先的。返回的结果是class C
命名空间、作用域
Python 中,不同命名空间中的内容可以重名。比如说在A
模块中定义一个max
函数,在B
模块中也定义一个max
函数,那么二者是不冲突的。在调用的时候,只需要在函数名字前面加上模块名字即可。
在 Python 中,一切都是对象。严格的说,在模块中,对名字的引用就是属性引用。在表达式modulename.functionname
中,modulename
是一个模块对象。function
则是该对象的一个属性。
属性分为只读
的和可写
的。如果是可写
的属性,那么就可以使用del
来删除了。比如说在一个类中删除一个属性的例子如下:
# -*- coding:utf-8 -*-
class OOO(object):
def __init__(self, value):
self.value=value
if __name__ == "__main__":
a=OOO(100)
print a.value
del a.value
print a.value
执行代码的结果:
Traceback (most recent call last):
File "C:\Users\naughty\workspace\ttt\com\d.py", line 15, in <module>
100
print a.value
AttributeError: 'OOO' object has no attribute 'value'
可以看到,属性value
在删除之前是可以输出的。删除之后,再次输出就会抛出异常了。
也可以删除引入的另外一个模块的内容:
# -*- coding:utf-8 -*-
import data
if __name__ == "__main__":
print data.a
print data.b
del data.a
print data.a
data
模块如下:
# -*- coding:utf-8 -*-
a = "aa"
b = "bb"
既然涉及到了命名空间,那么有必要说一下global
的使用。global
的使用了是为了在一个代码块中声明一个变量是全局变量。
# -*- coding:utf-8 -*-
import data
a="global a!"
def modify():
global a
a="inner a!"
print a
if __name__ == "__main__":
print a
modify()
print a
在上面这个例子中,modify
函数中使用了global
,然后修改了a
的值,并打印。在代码最后也打印了a
的值。执行代码输出如下:
global a!
inner a!
inner a! # 这里的值被修改了
这说明,global
确实起到作用了。如果这里不使用global
的话,那么根据 Python 对变量赋值的原则,这里会在modify
这个函数的局部空间中修改变量a
,并不会反映到全局。删除global a
之后,再次执行,输出如下:
global a!
inner a!
global a!