2022年 11月 4日

25.Python中的函数重载 (Function Overloading)

《Python编程的术与道:Python语言进阶》视频课程
《Python编程的术与道:Python语言进阶》视频课程链接:https://edu.csdn.net/course/detail/28618

函数重载 (Function Overloading)

函数重载是具有相同名称但实现多个不同的功能的能力。 调用重载函数时,运行时首先评估传递给函数调用的参数,并以此判断调用相应的实现。

# First product method. 
# Takes two argument and print their 
# product 
def product(a, b): 
    p = a * b 
    print(p) 
    
# Second product method 
# Takes three argument and print their 
# product 
def product(a, b, c): 
    p = a * b * c 
    print(p) 

# Uncommenting the below line shows an error
product(4, 5) 
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-1-d670b5358166> in <module>
     14 
     15 # Uncommenting the below line shows an error
---> 16 product(4, 5)


TypeError: product() missing 1 required positional argument: 'c'
# This line will call the second product method 
product(4, 5, 5) 
100

Python不支持自定义函数的重载。 当我们用相同的名称定义多个函数时,后一个函数始终会覆盖前一个函数,因此,在命名空间中,每个函数名始终只有一个entry。 通过调用函数locals()和globals()分别返回本地和全局命名空间,我们可以看到Python命名空间中存在的内容。

def area(radius):
    return 3.14 * radius ** 2
locals()
{'__name__': '__main__',
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__package__': None,
 '__loader__': None,
 '__spec__': None,
 '__builtin__': <module 'builtins' (built-in)>,
 '__builtins__': <module 'builtins' (built-in)>,
 '_ih': ['',
  '# First product method. \n# Takes two argument and print their \n# product \ndef product(a, b): \n    p = a * b \n    print(p) \n    \n# Second product method \n# Takes three argument and print their \n# product \ndef product(a, b, c): \n    p = a * b * c \n    print(p) \n\n# Uncommenting the below line shows an error\nproduct(4, 5) ',
  '# This line will call the second product method \nproduct(4, 5, 5) ',
  'def area(radius):\n    return 3.14 * radius ** 2',
  'locals()'],
 '_oh': {},
 '_dh': ['D:\\PythonCourses\\learn-python'],
 'In': ['',
  '# First product method. \n# Takes two argument and print their \n# product \ndef product(a, b): \n    p = a * b \n    print(p) \n    \n# Second product method \n# Takes three argument and print their \n# product \ndef product(a, b, c): \n    p = a * b * c \n    print(p) \n\n# Uncommenting the below line shows an error\nproduct(4, 5) ',
  '# This line will call the second product method \nproduct(4, 5, 5) ',
  'def area(radius):\n    return 3.14 * radius ** 2',
  'locals()'],
 'Out': {},
 'get_ipython': <function IPython.core.getipython.get_ipython()>,
 'exit': <IPython.core.autocall.ZMQExitAutocall at 0x29e9d5f88c8>,
 'quit': <IPython.core.autocall.ZMQExitAutocall at 0x29e9d5f88c8>,
 '_': '',
 '__': '',
 '___': '',
 'json': <module 'json' from 'C:\\ProgramData\\Anaconda3\\lib\\json\\__init__.py'>,
 'getsizeof': <function sys.getsizeof>,
 'NamespaceMagics': IPython.core.magics.namespace.NamespaceMagics,
 '_nms': <IPython.core.magics.namespace.NamespaceMagics at 0x29e9eabe588>,
 '_Jupyter': <ipykernel.zmqshell.ZMQInteractiveShell at 0x29e9d5bea88>,
 'np': <module 'numpy' from 'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\numpy\\__init__.py'>,
 '_getsizeof': <function __main__._getsizeof(x)>,
 '_getshapeof': <function __main__._getshapeof(x)>,
 'var_dic_list': <function __main__.var_dic_list()>,
 '_i': 'def area(radius):\n    return 3.14 * radius ** 2',
 '_ii': '# This line will call the second product method \nproduct(4, 5, 5) ',
 '_iii': '# First product method. \n# Takes two argument and print their \n# product \ndef product(a, b): \n    p = a * b \n    print(p) \n    \n# Second product method \n# Takes three argument and print their \n# product \ndef product(a, b, c): \n    p = a * b * c \n    print(p) \n\n# Uncommenting the below line shows an error\nproduct(4, 5) ',
 '_i1': '# First product method. \n# Takes two argument and print their \n# product \ndef product(a, b): \n    p = a * b \n    print(p) \n    \n# Second product method \n# Takes three argument and print their \n# product \ndef product(a, b, c): \n    p = a * b * c \n    print(p) \n\n# Uncommenting the below line shows an error\nproduct(4, 5) ',
 'product': <function __main__.product(a, b, c)>,
 '_i2': '# This line will call the second product method \nproduct(4, 5, 5) ',
 '_i3': 'def area(radius):\n    return 3.14 * radius ** 2',
 'area': <function __main__.area(radius)>,
 '_i4': 'locals()'}

可以看到:

{ ... 'area': 'area': <function __main__.area(radius)>, ... }

定义一个函数后调用函数locals(),我们看到它返回了本地命名空间中定义的所有变量的字典。 字典的键是变量的名称,值是该变量的引用/值。 当运行时遇到具有相同名称的另一个函数时,它会更新本地名称空间中的entry,从而消除了两个函数共存的可能性。 因此,python不支持函数重载。 这是在创建语言时做出的设计决定,但这并不能阻止实现它。

但是在python中根据参数的不同可以使同一函数的工作方式不同(多态):

# Function to take multiple arguments 
def add(datatype, *args): 

    # if datatype is int 
    # initialize answer as 0 
    if datatype =='int': 
        answer = 0
        
    # if datatype is str 
    # initialize answer as '' 
    if datatype =='str': 
        answer ='' 

    # Traverse through the arguments 
    for x in args: 

        # This will do addition if the 
        # arguments are int. Or concatenation 
        # if the arguments are str 
        answer = answer + x 

    print(answer) 
# Integer 
add('int', 5, 6) 
11
# String 
add('str', 'Hi ', 'Bob') 
Hi Bob