acess class attribute in another file

前端 未结 4 1541
旧巷少年郎
旧巷少年郎 2021-01-24 21:18

I\'m new to python.

I have a question about accessing attribute in class

t1.py

#!/usr/bin/python
import t2

class A:
        flag = False

if __n         


        
相关标签:
4条回答
  • 2021-01-24 21:45

    You can find this out yourself:

    t1.py

    #!/usr/bin/python
    import logging
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)
    logger.debug('t1 has started')
    logger.debug('t2 is being imported')
    import t2
    
    logger.debug('A is being "compiled"')
    class A:
        flag = False
    logger.debug('ID A: %r', id(A))
    logger.debug('ID A.flag %r', id(A.flag))
    
    logger.debug('What is __name__? %r', __name__)
    if __name__ == "__main__":
        logger.debug('__name__ was "__main__"')
        logger.debug('Calling t2.f()')
        t2.f()
        logger.debug('t2.f() was called')
        logger.debug('ID A.flag: %r', id(A.flag))
        print(A.flag)
    

    t2.py

    #!/usr/bin/python
    import logging
    logger = logging.getLogger(__name__)
    logger.debug('t2 is being imported')
    
    logger.debug('t2 is now importing t1')
    import t1
    
    def f():
        logger.debug('f is being called')
        t1.A.flag = True
        logger.debug('ID t1: %r', id(t1))
        logger.debug('ID t1.A: %r', id(t1.A))
        logger.debug('ID t1.A.flag: %r', id(t1.A.flag))
        print(t1.A.flag)
    

    My output

    I'm splitting this up with comments

    DEBUG:__main__:t1 has started
    DEBUG:__main__:t2 is being imported
    DEBUG:t2:t2 is being imported
    DEBUG:t2:t2 is now importing t1
    

    As you can see, the first time around (as others have mentioned) t1 actually has the name of __main__. It tries importing t2, but immediately t2 tries importing t1.

    DEBUG:t1:t1 has started
    DEBUG:t1:t2 is being imported
    

    You can see that none of the t2 logging statements run. That's because Python caches imported modules, so it first looks in the cache for t2 and says, "Ahah! I've already imported this guy, I just need to return it. Here you go, then!"

    DEBUG:t1:A is being "compiled"
    DEBUG:t1:ID A: 140377934341704
    DEBUG:t1:ID A.flag 4312040768
    DEBUG:t1:What is __name__? 't1'
    

    So, you'll notice that now it has made its way through importing t1. And t2

    DEBUG:t2:t2 is done being imported
    

    Execution continues back in the __main__ t1

    DEBUG:__main__:A is being "compiled"
    DEBUG:__main__:ID A: 140377934344360
    DEBUG:__main__:ID A.flag 4312040768
    

    Notice that the id for this A and A.flag are different!

    DEBUG:__main__:What is __name__? '__main__'
    DEBUG:__main__:__name__ was "__main__"
    DEBUG:__main__:Calling t2.f()
    DEBUG:t2:f is being called
    DEBUG:t2:ID t1: 4317998840
    DEBUG:t2:ID t1.A: 140377934341704
    DEBUG:t2:ID t1.A.flag: 4312040736
    

    Notice again, that these ids match t1.A's, and not __main__.As.

    True
    DEBUG:__main__:t2.f() was called
    DEBUG:__main__:ID A.flag: 4312040768
    False
    
    0 讨论(0)
  • 2021-01-24 21:51

    When you do

    ./t1.py
    

    you're executing the t1.py file, but it's not executed as the t1 module. It's considered to be the __main__ module. (This is what that if __name__ == '__main__' line checks for.) That means that when this line:

    import t1
    

    in t2.py tries to import t1, Python starts executing the t1.py file again to create the t1 module. You end up with two versions of the A class, one being __main__.A and one being t1.A. The modification to t1.A doesn't do anything to __main__.A, because even though they came from the same code in the same file, they're not the same class.

    0 讨论(0)
  • 2021-01-24 22:00

    Yeah, I can see how this can be a little confusing but it is basically a question of namespaces along with the distinction that the __main__ namespace is not considered as part of the list of imported modules. This allows the file that is the point of execution (and thus occupying the __main__ namespace) to also be imported as a module. On the other hand, if the same module is imported more than once, the interpreter will simply let all the different imports point to the same memory location

    Because of this, in the code you are showing above, you actually have two distinct versions of A: you have __main__.A and you have __main__.t2.t1.A. The second one comes about because __main__is importing t2 which in turn is importing t1 as a module.

    When you are running t2.f(), you are setting __main__.t2.t1.A.flag = True and then printing it. Subsequently, when you call print(A.flag), you are printing the value in __main__.A.flag, which was never changed.

    I hope that makes at least a little sense.

    A friend of mine always said that computer science is an experimental science. Let's invoke the debugger.

    I add a pdb.set_trace() to the execution and t1.py now looks like this:

    #!/usr/bin/python
    import t2
    
    class A:
            flag = False
    
    if __name__ == "__main__":
        import pdb; pdb.set_trace()
        t2.f()
        print(A.flag)
    

    And this is what we get:

    $ python t1.py
    > /Users/martin/git/temp/t1.py(9)<module>()
    -> t2.f()
    (Pdb) A
    <class __main__.A at 0x10ec9ba78>
    (Pdb) t2.t1.A
    <class t1.A at 0x10ec9ba10>
    (Pdb) 
    

    Please note that the A have separate memory locations associated.

    0 讨论(0)
  • 2021-01-24 22:05

    They are indeed two different objects (explained very well in user2357112's answer). If you want t2 to use the same object, you need to tell Python that you are actually importing the same module that is importing t2. To do that, import __main__ instead:

    import __main__
    
    def f():
        __main__.A.flag = True
        print(__main__.A.flag)
    
    0 讨论(0)
提交回复
热议问题