【问题标题】:Understanding "def main" and "overloading" in Python [closed]理解 Python 中的“def main”和“重载”[关闭]
【发布时间】:2013-03-24 16:47:36
【问题描述】:

我经常看到一些带有

的代码
def main(A,B)
    some steps

被描述为“主函数的重载”,在阅读了有关 Python 的更具体的内容后,我知道这不是真的,因为:

  • Python 是一种无损类型语言
  • Python 中的函数/方法甚至不知道给定参数的类型,python 也不关心

我也不确定实例和“静态方法”或“类方法”之间是否有真正的区别,可能它们是相同的,唯一的区别是使用装饰器,但这可能是与我在 C/C++ 上花了这么多时间后第一次接触函数式语言有关。

更重要的是,在 Python 中,第一个缩进级别用作入口点(就像 C/C++ 中的 main() 一样),所以我不明白为什么你应该在不同于以下的缩进级别定义 main真正的第一个。

我对 Python 关键字的一般想法是,关键字具有特殊的语义值而不是真正定义的语法(可能是因为 C++ 不太“惯用”,我真的不知道如何解释),它们被用作某些东西的占位符,它们为应用它们的部分赋予了特殊的含义。还有像 __name__ 这样的特殊变量,它们只是用来存储特殊信息而已。

在我的大脑中存储了所有这些小信息之后,我仍然不明白第一个代码示例的真正含义:

  • main() 函数有什么特别之处?
  • 如果它不是真正的“main”,那么定义类似“main”函数的意义何在
  • 如果没有输入,Python 如何决定调用哪个函数?
  • 解释器读取__init__.py文件和其他文件的方式有区别吗?

【问题讨论】:

  • 您在这里有几个不同的问题,最好将它们分成单独的问题。另外,您在哪里看到过这种称为“重载 main 函数”的情况?
  • @BrenBarn 我经常在各种关于脚本和在提供 Python API 的应用程序中创建小程序的资源中找到它。如果你想要一个具体的例子,我需要挖掘它,因为我倾向于丢弃这些东西,但看到这种情况真的很常见。
  • @BrenBarn 如果从不同的角度基本相同,我怎么能把这个问题变成 4?

标签: python functional-programming overloading


【解决方案1】:

回答您的问题:

main()函数

没有什么特别之处。您必须自己调用它,方法是:

def main():
    print "This is main"

if __name__ == "__main__":
    main()

为什么要使用main()

您可能会这样做的原因是为了以一种方便的方式将您的主要入口点代码放在一起。例如,如果你在main() 中创建了一些变量,它们就不是全局变量,这样可以避免污染全局命名空间。如果您从另一个模块导入模块(而不是直接作为脚本运行),它还会阻止运行 main() 函数。如果您不想在导入时进行一些初始化(例如,打印消息),但您确实想在作为独立脚本运行时进行初始化,这会很有用。

Python 如何决定调用哪个函数

Python 不支持这种意义上的“重载”。在给定的命名空间中只能有一个具有给定名称的函数。如果你创建了第二个同名的函数(或同一个类中同名的第二个方法),你会完全覆盖第一个。

__init__.py

这个问题与您的其他问题没有真正的关系。但不,它不会以不同的方式处理它们。它在不同的时间处理它们(当您导入包时,而不是包中的模块时),但它们中的代码与任何其他 Python 文件中的代码运行相同。

【讨论】:

  • 所以 main 真的和其他函数一样吗?
  • @pictr:是的,就像其他人一样。
【解决方案2】:

main() 在 python 中只是一个函数名。常用成语

if __name__ == '__main__':
    #do something

是找出这个文件中的代码是作为程序运行而不是作为模块导入的快捷方式。

由于 python 旨在实现无类型,因此社区非常重视约定和最佳实践。这不能提供与编译器相同级别的可预测性,但它有助于避免混乱。可读性是 Python 的核心价值,像这样的习语提供了有价值的结构。

Python 不像其他语言那样支持函数重载。在强类型语言中,您可能会编写同一个函数的多个版本,但名称相同但输入参数不同:

void DoSomething (int a) {};
void DoSomething (float f) {};
void DoSomething (string s){};

在 python 中没有等价的成语。在大多数情况下,它是不需要的:对于数字运算,您并不真正关心传入的数字是浮点数、整数还是其他数字——只要它们支持正确的运算符即可。这就是“鸭子打字”的蟒蛇咒语的用武之地 - 如果它像鸭子一样走路并且像鸭子一样嘎嘎叫,那么它就是一只鸭子。所以python函数惯用look for functions or operators on incoming arguments rather than checking their types

对于实例与静态方法: 在 python 中,每个实例方法都会隐式获取拥有的实例作为函数的第一个参数:

class Test(object):
    def __init__(self, arg):
        self.variable = arg
    def example(self):
        print self.variable

fred = Test(999)  # note: no 'self' passed here
fred.example()
>>> 999
joe = Test(-1)
joe.example()
>>> -1

类方法获取类类型,而不是实例,作为隐式的第一个参数。类方法可以看到类级别的变量,这些变量是在类范围内而不是在实例范围内定义的——但它们对特定实例一无所知。

class TestCls (Test)
   CLASS_VARIABLE = "hello"
   # other behavior inherited from Test

   @classmethod
   def class_example(cls):
       print cls.CLASS_VARIABLE


barney = TestCls(123)
barney.example()
>>> 123
barney.class_example() # again, no explicit class passed in
>>> 'hello'

静态方法根本没有隐式参数:

class TestStatic (TestCls):
    CLASS_VARIABLE = 'goodbye'
    # inherited stuff again
    @staticmethod
    def static_test():
        print "behold, I have no implicit argument"

静态和类方法也不需要调用实例:

wilma = TestStatic(123)
wilma.static_test()  # you can call from an instance
>>> behold, I have no implicit argument
# or not:
TestStatic.static_test()
>>> behold, I have no implicit argument 
TestStatic.class_example()
>>> goodbye # the method is inherited, but the class variable come from this class

【讨论】:

    猜你喜欢
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 2022-01-07
    相关资源
    最近更新 更多