Python语法本身不支持方法重载,但可以通过变通的方式来实现类似方法重载的效果。也就是说,按正常的方式不支持,但你想让他支持,那就支持。
假设你有一个函数connect,它有一个参数address,这个参数可能是一个字符串,也可能是一个元组。例如:
connect('127.0.0.1:8080')
connect(('127.0.0.1', 8080))
如果你想在代码里面兼容这两种写法,代码可以这么写:
def connect(address):
if instance(address, str):
ip, port = address.split(":")
print(f"参数为字符串, IP是:{ip},端口号是:{port}")
elif instance(address, tuple):
ip, port = address
print(f"参数为字符串, IP是:{ip},端口号是:{port}")
else:
print("地址不正确。")
这种写法简单直接,但是如果参数的类型更多,那么你就需要写很长的 if-elif-elif-...-else
。代码看起来就非常不美观。
学习过 Java 的,应该对函数重载比较熟悉,可以定义几个名字相同的函数,但是他们的参数类型或者数量不同,从而实现不同的代码逻辑。
在 Python 里面,参数的数量不同可以使用默认参数来解决,不需要定义多个函数。那如果参数类型不同就实现不同的逻辑,除了上面的 if-else外,我们还可以使用functools
模块里面的singledispatch
装饰器实现函数重载。
import sys
from functools import singledispatch
@singledispatch
def connection(address):
print(f"传输参数类型为:{type(address)},不是有效类型")
if sys.version_info <= (3, 6):
@connection.register(str)
def _(address):
ip, port = address.split(":")
print(f"参数为字符串, IP是:{ip},端口号是:{port}")
@connection.register(tuple)
def _(address):
ip, port = address
print(f"参数为元组,IP是:{ip},端口号是:{port}")
if sys.version_info >= (3, 7):
# 3.7+后新特性
@connection.register
def _(address: str):
ip, port = address.split(":")
print(f"参数为字符串, IP是:{ip},端口号是:{port}")
@connection.register
def _(address: tuple):
ip, port = address
print(f"参数为元组,IP是:{ip},端口号是:{port}")
connection("192.168.0.1:8000")
connection(("192.168.0.1",8001),)
connection(123)
调用的函数,始终都是connect,但是由于传入参数的类型不同,它运行的结果也不一样。
基于Nginx+Supervisord+uWSGI+Django1.11.1+Python3.6.5构建