是"自我"以某种方式保护方法的论点?

时间:2017-07-14 23:50:26

标签: python multithreading self

编辑:

我的困惑已被清除,谢谢。
我只是说出我的困惑的根源,以及对它的简单回答,而不是翻新我对一个隐藏在线程和多进程复杂性中的一个非常简单的概念的混淆。  我认为: self是由__init__()创建的,因此自我位于__init__()范围内。
实际上self是在调用__init__()之前创建的,并且是在父母'中创建的。范围__init__()。因此,self实际上是传递给__init__()的变量。总之,self不受保护,无论如何都不是特别的。

我在下面发布的代码是一个关于变量作用域的研究,涉及由另一个进程运行的线程。虽然它与问题无关,但它确实挑战了你对self=10 # comment out this assignment and see what happensdef thread_WITHOUT_SelfPassedToIt():部分的python范围的理解。再次感谢。

import threading
import multiprocessing
from time import sleep

class exe_classBased(multiprocessing.Process):
    def __init__(self):
        super().__init__()
        self.aaa = 'aaa'

        self = 10


    def run(self):

        print(
            '===================================================\n'
            '<Round 0> self is NOT alterred in the scope of run()\n'
            '==================================================='
        )

        print('self in the start of run() ==>',type(self))

        def thread_WITHOUT_SelfPassedToIt():
            try:
                print('in a thread WITHOUT self passed to it, self==>', type(self))
            except Exception as e:
                print(e)
            try:
                print('self.aaa==',self.aaa)
            except Exception as e:
                print(e)

            self=10 # comment out this assignment and see what happens


        def thread_WITH_SelfPassedToIt(self):
            print('in a thread WITH self passed to it, self==>', type(self))
            try:
                print('self.aaa==',self.aaa)
            except Exception as e:
                print(e)

        t = threading.Thread(
            target=thread_WITHOUT_SelfPassedToIt,
            daemon=1,
        )
        t.start()

        t = threading.Thread(
            target=thread_WITH_SelfPassedToIt,
            args=(self,),
            daemon=1,
        )
        t.start()

        print(
            '===================================================\n'
            '<Round 1> self is ALTERRED in the scope of run()\n'
            '==================================================='
        )

        self=10


        print('in the immidiate start of run() after self=10, self==>', type(self))

        def thread_WITHOUT_SelfPassedToIt1():
            nonlocal self
            try:
                print('in a thread WITHOUT self passed to it, self==>', type(self))
            except Exception as e:
                print(e)

            self=11

        def thread_WITH_SelfPassedToIt1(self):
            print('in a thread WITH self passed to it, self==', self)
            try:
                print('self.aaa==', self.aaa)
            except Exception as e:
                print(e)

        t = threading.Thread(
            target=thread_WITHOUT_SelfPassedToIt1,
            daemon=1,
        )
        t.start()

        sleep(1)
        # give the thread_WITHOUT_SelfPassedToIt enough time to have self=11 excecuted

        t = threading.Thread(
            target=thread_WITH_SelfPassedToIt1,
            args=(self,),
            daemon=1,
        )
        t.start()

        sleep(5)

if __name__ == '__main__':
    multiprocessing.freeze_support()
    e = exe_classBased()
    e.daemon = 1
    e.start()
    sleep(5)

'''
output:
===================================================
<Round 0> self is NOT alterred in the scope of run()
===================================================
self in the start of run() ==> <class '__mp_main__.exe_classBased'>
local variable 'self' referenced before assignment
local variable 'self' referenced before assignment
in a thread WITH self passed to it, self==> <class '__mp_main__.exe_classBased'>
self.aaa== aaa
===================================================
<Round 1> self is ALTERRED in the scope of run()
===================================================
in the immidiate start of run() after self=10, self==> <class 'int'>
in a thread WITHOUT self passed to it, self==> <class 'int'>
in a thread WITH self passed to it, self== 11
'int' object has no attribute 'aaa'
'''

3 个答案:

答案 0 :(得分:3)

self是该函数中的局部变量。重新分配它对程序的其余部分没有任何影响。它与在某些其他函数中分配参数变量没有什么不同,例如

def add1(x):
    y = x + 1
    x = 10
    return y

foo = 3
bar = add1(foo)
print(foo)

这将打印3,而不是10,因为作业是add1的本地作业。

答案 1 :(得分:3)

使用self = 10,您只需将当前类实例的本地指针重新调整为其他内容。基本上你放弃了对自己&#34;的引用,但只是那个。

要改变self,您需要更改其中的一些属性:

self.foo = bar

这会修改作为参数传递的同一个对象self

答案 2 :(得分:2)

self变量在用作受让人时不会指向类对象本身。相反,它将重写局部变量self

尝试改为:

class B: # We create a class B
 b = None

b = B() # We instantiate B

class A:
 def __init__(self):
  self.__class__ = b.__class__ # Ugly but works

a = A() # We instantiate A
type(a) # What is it exactly?
<class '__main__.B'> # Magic!