zoukankan      html  css  js  c++  java
  • python类学习以及mro--多继承属性查找机制

    还记得什么是新式类和旧式类吗?

    Python中,一个class继承于object,或其bases class里面任意一个继承于object,这个class都是new-style class。

    -----------------------------------------------

    在python中,类是可以多重继承的。python类中的所有成员变量都是类似java语言中的public的。

    ------------------------------类属性-----------------------------

    在python中,类中定义的函数也是对象。也可以修改赋值。

    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2. class A(object):  
    3.     def f(self):  
    4.         print "f"  
    5. def ff():  
    6.     print "ff"  
    7. a=A()  
    8. a.f()  
    9. xf=a.f  
    10. xf()  
    11. a.f=ff  
    12. a.f()  

    这个例子的输出结果如下:

    f

    ff

    ff

    通过上面的结果,可看出来,a.f=ff的时候,对象a中的函数已经被修改成ff函数了。

    另外,xf也是一个函数对象。

    ------------------------------------------------

    对于继承,python提供了两个函数:issubclass()和isinstance()

    看例子:

    >>> issubclass(bool,int)
    True
    >>>

    结果输出是True,说明bool是int的子类。

    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2. class A(object):  
    3.     def a(self):  
    4.         print "a"  
    5.   
    6. if __name__ == "__main__":  
    7.     a=A()  
    8.     print isinstance(a,A)  

    主要还是学习一下多重继承的概念。

    py中多重继承的语法如下:

    class Myclass(base1,base2,base3):

    ---------------------------------------------------

    mro即method resolution order,主要用于在多继承时判断调的属性的路径(来自于哪个类)。
    之前查看了很多资料,说mro是基于深度优先搜索算法的。但不完全正确在Python2.3之前是基于此算法,但从Python2.3起应用了新算法:C3算法。
    为什么采用C3算法
    C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。
    本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
    单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。
    ------------------------------新式类和旧式类中查找属性的顺序不同-------------------------------------
    在新式类中,查找一个要调用的函数或者属性的时候,是广度优先搜搜的。
    在旧式类当中,是深度优先搜索的。如下图所示:
    看下面的例子:
    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2.   
    3. class D(object):  
    4.     def foo(self):  
    5.         print "class D"  
    6.   
    7. class B(D):  
    8.     pass  
    9.   
    10. class C(D):  
    11.     def foo(self):  
    12.         print "class C"  
    13.   
    14. class A(B, C):  
    15.     pass  
    16.   
    17. f = A()  
    18. f.foo()  

    例子中定义D类的时候,D是新式类,所以D的所有子类都是新式类。
    A的实例对象f在调用foo函数的时候,根据广度优先搜索原则,调用的是C类里面的foo函数。
    上面的代码输出class C
    如果定义D类的时候直接class D,而不是class D(object),那么上述代码就该输出class D了。

    ---------------------------------------

    命名空间

    python中,不同命名空间中的内容可以重名。比如说在A模块中定义一个max函数,在B模块中也定义一个max函数,那么二者是不冲突的。在调用的时候,只需要在函数名字前面加上模块名字即可。

    在python中,一切都是对象。严格的说,在模块中,对名字的引用就是属性引用。在表达式modulename.functionname中,modulename是一个模块对象。function那么则是该对象的一个属性。

    属性分为只读的和可写的。如果是可写的属性,那么就可以使用del来删除了。比如说在一个类中删除一个属性的例子如下:

    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2.   
    3. class OOO(object):  
    4.     def __init__(self, value):  
    5.         self.value=value  
    6.       
    7. if __name__ == "__main__":  
    8.     a=OOO(100)  
    9.     print a.value  
    10.     del a.value  
    11.     print a.value  

    执行代码的结果:

    Traceback (most recent call last):
      File "C:Users aughtyworkspace ttcomd.py", line 15, in <module>
    100
        print a.value
    AttributeError: 'OOO' object has no attribute 'value'

    可以看到,属性value在删除之前是可以输出的。删除之后,再次输出就会抛出异常了。

    也可以删除引入的另外一个模块的内容:

    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2.   
    3. import data  
    4.   
    5. if __name__ == "__main__":  
    6.     print data.a  
    7.     print data.b  
    8.     del data.a  
    9.     print data.a  

    data模块如下:

    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2.   
    3. a = "aa"  
    4. b = "bb"  

    ---------------------------------------------

    既然涉及到了命名空间,那么有必要说一下global的使用。

    global的使用了是为了在一个代码块中声明一个变量是全局变量。

    [python] view plain copy
     
    1. # -*- coding:utf-8 -*-  
    2.   
    3. import data  
    4.   
    5. a="global a!"  
    6.   
    7. def modify():  
    8.     global a  
    9.     a="inner a!"  
    10.     print a  
    11.   
    12.   
    13. if __name__ == "__main__":  
    14.     print a  
    15.     modify()  
    16.     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!

     
     
  • 相关阅读:
    动态规划之背包问题
    Python中import导入上一级目录模块及循环import问题的解决
    Anaconda介绍、安装及使用教程
    负载均衡基础知识
    TCP和UDP的区别(转)
    microsoft visual c++ 14.0 is required问题解决办法
    python使用requests时报错requests.exceptions.SSLError: HTTPSConnectionPool
    解决Anaconda无法更新的问题
    彻底的理解TCP协议的三次握手和四次分手
    android调试工具 adb命令学习
  • 原文地址:https://www.cnblogs.com/paranoia/p/6164382.html
Copyright © 2011-2022 走看看