目录

if __name__ == ‘__main__’: 究竟起什么作用

if __name__ == ‘__main__’: 的作用是:让一个文件既可以作为可以导入的模块,也可以作为独立的程序直接运行。当这个文件被直接执行时,if __name__ == ‘__main__’后面的代码会被执行;但如果该文件是被导入的,if __name__ == ‘__main__’后面的代码则不会被执行。

一、if __name__ == ‘__main__’: 究竟起什么作用

一个python文件通常有两种使用方法,名列前茅是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if __name__ == ‘__main__’: 的作用就是控制这两种情况执行代码的过程,在 if __name__ == ‘__main__’: 下的代码只有在名列前茅种情况下(即文件作为脚本直接执行)才会被执行,而 import 到其他脚本中是不会被执行的。

作为脚本直接执行

假设我们有个叫做 demo.py 的 Python 文件,其中包含了一些函数定义和变量声明。在 demo.py 文件末尾加入如下代码:

if __name__ == '__main__':
    print('这个文件正在被直接执行!')

当我们在命令行中输入 python demo.py 并运行时,会输出”这个文件正在被直接执行!”。

作为模块导入

假设我们有另一个叫做 test.py 的 Python 文件,想要调用 demo.py 中的某些函数。在 test.py 中导入 demo.py,并调用其中的函数:

import demo
result = demo.add(1, 2)
print(result)

如果 demo.py 不包含 if __name__ == ‘__main__’ 语句,当我们运行 test.py 时会先输出”这个文件正在被直接执行!”,然后才输出 add 函数的调用结果,这并不是我们所期望的。而如果在 demo.py 中加入 if __name__ == ‘__main__’ 语句,它只会在 demo.py 直接被执行时输出”这个文件正在被直接执行!” ,当 demo.py 被 test.py 导入时则不会输出。这样可以避免在调用模块时不必要的代码重复执行,使代码更加简洁和高效。

二、python中其他的特殊变量

除了 __name__ 之外,Python 中还有一些类似的特殊变量,它们也以双下划线开头和结尾。以下是一些比较常用的类似的特殊变量:

1、__all__

python模块中的__all__,可用于模块导入时限制,如:

from module import *

此时被导入模块若定义了__all__属性,则只有__all__内指定的属性、方法、类可被导入。若没定义,则导入模块内的所有公有属性,方法和类。

在别的模块中,导入该模块时,只能导入__all__中的变量,方法和类:

__all__ = ('A', 'func') 
class A():
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
class B():
    def __init__(self, name, id):
        self.name = name
        self.id = id
 
def func():
    print('func() is called!')
 
def func1():
    print('func1() is called!')

test.py中定义了__all__属性,只能导入__all__中定义的属性,方法和类:

from test import * 
a=A('python','24') 
print(a.name,a.age) 
func() 
#func1() #NameError: name 'func1' is not defined 
#b=B('python',123456) #NameError: name 'B' is not defined 

2、__slots__

Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性范围:

class P(object):
    __slots__ = ("name", "age")
    pass

3、__init__()

构造函数,创建实例的时候,可以调用init方法做一些初始化的工作,如果子类重写了init,实例化子类时,则只会调用子类的init,此时如果想使用父类的init,可以使用super函数,如下:

class P(object):
    def __init__(self, name, score):
        self.name = name
        self.score = name
 
 
class C(P):
    def __init__(self, name, score, age):
        super(C, self).__init__(name, score)
        self.age = age

4、__new__()

注意:__init__是实例创建之后调用的名列前茅个方法,而__new__更像构造函数,它在__init__之前被调用。另外,__new__方法是一个静态方法,名列前茅参数是cls,__new__方法必须返回创建出来的实例。

例如,用__new__实现单例模式:

class Singleton(object):
    def __new__(cls):
        # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance
  
obj1 = Singleton()
obj2 = Singleton()
  
obj1.attr1 = 'value1'
print(obj1.attr1, obj2.attr1)
print(obj1 is obj2)

5、__repr__()

是给机器用的,在Python解释器里面直接敲对象名在回车后调用的方法。(用于调试)

# test.py
class P(object):
    def __str__(self):
        return "__str__ called"
 
    def __repr__(self):
        return "__repr__ called"
 
p = P()

__str__和__repr__的区别:

>>> from test import p
>>> p
__repr__ called
>>> print p
__str__ called

6、__exit__

这两个方法是用于支持with语句的上下文管理器。例如让文件句柄支持with语法的实现:

class File(object):
    def __init__(self, file_name, method):
        self.file_obj = open(file_name, method)
    def __enter__(self):
        return self.file_obj
    def __exit__(self, type, value, traceback):
        self.file_obj.close()
 
with File('demo.txt', 'w') as opened_file:
    opened_file.write('Hola!')

延伸阅读1:python的内置函数有哪些

  • 类型转换函数:int()、float()、str()、bool()、list()、tuple()、set()、dict()、bytes()、bytearray()、memoryview()等。
  • 数字运算函数:abs()、round()、pow()、min()、max()等。
  • 列表和元组操作函数:len()、sorted()、reversed()、sum()、zip()、enumerate()、map()、filter()等。
  • 字符串操作函数:strip()、split()、join()、replace()、format()、find()、index()等。
  • 文件和目录操作函数:open()、read()、write()、close()、os.mkdir()、os.path.join()等。
  • 其他函数:print()、input()、range()、dir()、type()、id()、help()、isinstance()、callable()等。
一站式研发项目管理平台 PingCode

一站式研发项目管理平台 PingCode

支持敏捷\瀑布、知识库、迭代计划&跟踪、需求、缺陷、测试管理,同时满足非研发团队的流程规划、项目管理和在线办公需要。