if __name__ == "__main__":

公与善必先利器

环境:Python3.6 + win10
目录结构:
    test             # 目录
      |-- t1.py      # py文件
      |-- t2.py      # py文件

让模块如脚本一样运行

在Python中,可以说,每一个py文件都可以说是一个模块,那么每一个模块不仅仅能被调用,也要负责本身的逻辑,如我们在模块t1中定义了一个登录函数并实现登录逻辑:

# t1.py
def login(user, pwd):
    if user == '张开' and pwd == '666':
        return 'login successful'
    return 'login error'


user, pwd = input('user: ').strip(), input('pwd: ').strip()
print(login(user, pwd))
t1.py

那么,这个模块在自己使用的时候,肯定没有问题。但是有一天,这个牛逼的模块被别人使用了,在t2中调用了t1的注册功能:

# t1.py
def register():
    user, pwd = input('user: ').strip(), input('pwd: ').strip()
    if user == '张开' and pwd == '666':
        return 1
    return 0


def login(user, pwd):
    if user == '张开' and pwd == '666':
        return 'login successful'
    return 'login error'


user, pwd = input('user: ').strip(), input('pwd: ').strip()
print(login(user, pwd))
被t2.py 调用了的t1.py
# t2.py
import t1
def register():
    if t1.register():
        return 'register successful'
    return 'register error'
print(register())

'''
user: a
pwd: a
login error
user: a
pwd: a
register error
'''
t2.py

那么,在t2模块内部要实现注册的时候,想到t1不是实现了一个注册的功能了吗?我们就要避免重复造轮子,就直接调过来用了,但是问题来了,当我们在调用一个模块的时候,该模块内的代码会先执行一遍,也就是t2模块示例代码最后展示的交互结果。当t2模块内的代码执行到import t1的时候,触发了原本t1模块的执行,t1模块内部代码从上往下执行,就执行到了登录逻辑。等登录逻辑执行完毕,程序回到t2模块继续往下执行。也就执行到了t2内部的注册函数的执行。而t2的注册函数此时又调用了t1模块的注册的函数的执行,等注册逻辑执行完毕,程序往下继续执行——没有代码,程序结束。

由上述示例可以见到,我们在t2模块调用t1模块的时候,只想调用注册函数,并不想触发t1登录逻辑的执行,那么,该怎么办呢?

if __name__ == "__main__":

我们首先看一下模块内自带都有哪些属性:

# t1.py
print(dir())
'''
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
'''

在上述的打印列表内,此时,__name__属性在这里对我们有帮助,那么我们来研究一个__name__属性是什么鬼?

我们先在各自模块内部打印一下__name__属性。

# t1.py
print('module t1.__name__:', __name__, type(__name__))
'''
module t1.__name__: __main__ <class 'str'>
'''
# t2.py
# import t1
print('module t2.__name__: ', __name__, type(__name__))
'''
module t2.__name__:  __main__ <class 'str'>
'''

通过上例可以看到,各模块各自运行的结果一致,__name__属性都返回了一个str类型的__main__结果,你可能说,这没啥啊,扯半天淡就这看这个了?别急,我们放开t2模块的import t1注释再看:

# t1.py
print('module t1.__name__:', __name__, type(__name__))
'''
module t1.__name__: __main__ <class 'str'>
'''
# t2.py
import t1
print('module t2.__name__: ', __name__, type(__name__))
'''
module t1.__name__: t1 <class 'str'>
module t2.__name__:  __main__ <class 'str'>
'''

通过执行t2模块,发现一个有趣的现象,在导入t1的时候,触发了t1模块的执行,但是,看看此时t1的打印是什么,没错,是t1的模块名!而单独运行t1的时候,结果仍不变,还是__main__。

那么,由此可以做些手脚了,我们通过__name__返回不同的字符串(自己调用返回__main__,被调用时返回自己的模块名),来解决上面那个登录逻辑被执行的问题。那么,我们就在t1中加上一句话:

# t1.py
def register():
    user, pwd = input('user: ').strip(), input('pwd: ').strip()
    if user == '张开' and pwd == '666':
        return 1
    return 0


def login(user, pwd):
    if user == '张开' and pwd == '666':
        return 'login successful'
    return 'login error'


if __name__ == '__main__':
    user, pwd = input('user: ').strip(), input('pwd: ').strip()
    print(login(user, pwd))
t1.py
# t2.py
import t1
def register():
    if t1.register():
        return 'register successful'
    return 'register error'
print(register())
'''
user: 张开
pwd: 666
register successful
'''
t2.py

在t1模块中,当__name__属性返回是字符串__main__的时候,这说明是此次执行是t1模块自己被自己调用,那么我们就把想要实现的逻辑放到该if语句内,表明自己调用时执行。

而当别的模块如t2调用t1的时候,__name__属性返回了t1的模块名,那么t1不等于__main__,t1模块内部的if语句也就不会执行。这样就解决了上例中登录的问题。 


that's all

猜你喜欢

转载自www.cnblogs.com/Neeo/p/9504779.html