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!

     
     
  • 相关阅读:
    PAT (Advanced Level) Practice 1100 Mars Numbers (20分)
    PAT (Advanced Level) Practice 1107 Social Clusters (30分) (并查集)
    PAT (Advanced Level) Practice 1105 Spiral Matrix (25分)
    PAT (Advanced Level) Practice 1104 Sum of Number Segments (20分)
    PAT (Advanced Level) Practice 1111 Online Map (30分) (两次迪杰斯特拉混合)
    PAT (Advanced Level) Practice 1110 Complete Binary Tree (25分) (完全二叉树的判断+分享致命婴幼儿错误)
    PAT (Advanced Level) Practice 1109 Group Photo (25分)
    PAT (Advanced Level) Practice 1108 Finding Average (20分)
    P6225 [eJOI2019]异或橙子 树状数组 异或 位运算
    P4124 [CQOI2016]手机号码 数位DP
  • 原文地址:https://www.cnblogs.com/paranoia/p/6164382.html
Copyright © 2011-2022 走看看