为什么父类要在Python中使用子类的实例?

时间:2014-10-31 18:33:05

标签: python class inheritance

多处理包中process.py的源代码使用以下模式;请注意Process_MainProcess_current_process之间的关系。

class Process(object):                                                                                                                                                                                                                                                     
    '''                                                                                                                                                                                                                                                                    
    Process objects represent activity that is run in a separate process                                                                                                                                                                                                   

    The class is analagous to `threading.Thread`                                                                                                                                                                                                                           
    '''                                                                                                                                                                                                                                                                    
    _Popen = None                                                                                                                                                                                                                                                          

    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):                                                                                                                                                                                            
        assert group is None, 'group argument must be None for now'                                                                                                                                                                                                        
        count = _current_process._counter.next()                                                                                                                                                                                                                           
        self._identity = _current_process._identity + (count,)   

其中_current_process稍后定义为:

class _MainProcess(Process):                                                                                                                                                                                                                                               

    def __init__(self):                                                                                                                                                                                                                                                    
        self._identity = ()                                                                                                                                                                                                                                                
        self._daemonic = False                                                                                                                                                                                                                                             
        self._name = 'MainProcess'                                                                                                                                                                                                                                         
        self._parent_pid = None                                                                                                                                                                                                                                            
        self._popen = None                                                                                                                                                                                                                                                 
        self._counter = itertools.count(1)                                                                                                                                                                                                                                 
        self._children = set()                                                                                                                                                                                                                                             
        self._authkey = AuthenticationString(os.urandom(32))                                                                                                                                                                                                               
        self._tempdir = None                                                                                                                                                                                                                                               

_current_process = _MainProcess()                                                                                                                                                                                                                                          
del _MainProcess     

我不明白的是_current_process_MainProcess类的唯一实例,它是Process的子类,在其中使用{{1} }}。这对我来说似乎是循环的。

  1. 我怀疑这能用C ++或JAVA编译; Python如何处理这个问题?
  2. 此外,这对我来说似乎是一种不寻常的模式;它的用途是什么?
  3. 上面的代码在以下示例中进行了简化,该示例运行正常并打印42.

    _current_process

3 个答案:

答案 0 :(得分:1)

在C / C ++中,您可以使用前向声明获得类似的结果。在Java中,它并非不可能,但你可能需要反思才能让它发挥作用。

这里的事情是从对象调用方法,因此存在变量。它是定义它的子类还是父类是无关紧要的。一切都在运行时完成,所以在此之前不需要num存在。

使用您的示例:

a = A()
a.print_num()

Traceback (most recent call last):
  File "test.py", line 18, in <module>
    a.print_num()
  File "test.py", line 9, in print_num
    print b.num
NameError: global name 'b' is not defined

或者甚至是陌生人(从C ++ / Java的角度来看)版本:

class A(object):

    def print_num(self):
        print self.num


class B(A):

    def __init__(self, num):
        self.num = num

b = B(42)
b.print_num()

答案 1 :(得分:0)

_current_process变量始终设置为当前正在运行的进程的Process对象。它是全球性的,但它的价值实际上是在几个地方设定的。一个是你最初指出的那个,它发生在模块的顶层:

_current_process = _MainProcess()
del _MainProcess

这意味着当您直接或间接导入process模块时,_current_process会自动设置为特殊情况MainProcess实例,该实例代表一个顶级进程。使用multiprocessing的脚本。

但是,它也设置在Process._bootstrap内部,在分叉或生成后立即在新进程内调用:

def _bootstrap(self):
    from . import util
    global _current_process

    try:
        ...
        _current_process = self
        ...

因此,新创建的Process设置了_current_process,而不是MainProcess实例。

现在,当您在任何给定进程中调用p = Process(...)时,新创建的Process实例的属性应基于当前进程'上下文的属性,无论如何那可能。因此:

class Process(object):
    ...   
    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
        assert group is None, 'group argument must be None for now'
        count = _current_process._counter.next()
        self._identity = _current_process._identity + (count,)
        self._authkey = _current_process._authkey
        self._daemonic = _current_process._daemonic
        self._tempdir = _current_process._tempdir

这就是为什么如果您有父,子,和孙子Process个实例,他们的名字是:

家长:<_MainProcess(MainProcess, started)>

儿童:<Process(Process-1, started)>

孙子:<Process(Process-1:1, started)>

孙子的名字是基于孩子的名字,而不是父母的名字。

这种模式在Python中是允许的,因为它使用后期绑定;变量名称和方法直到运行时才绑定到对象。因此,self._authkey = _current_process._authkey行仅在实际调用Process.__init__时进行评估,这将始终在导入process.py后进行评估,这意味着将_current_process定义。

答案 2 :(得分:0)

这是简化代码的C ++版本。 您需要两个类的前向声明。

class A {
public:
    void print_other_class_member();

};

class B:A {
public:
    int num;
    B();

};

然后声明一个B类的实例,并在A类方法的定义中使用它。

#include <stdio.h>
#include "forward.h"

class B;

B b;

B::B(){
    num = 42;
}

void A::print_other_class_member(){
    printf("%d\n",b.num);
}

int main(){
    A a;
    a.print_other_class_member();
}

这在C ++中运行得很好。与Python的唯一区别是你需要一个前向声明。