Python 过载 __init__
Python overload __init__
如何在 Python 中重载 __init__()
?我习惯了 C/C++,编译器可以看到数据类型的差异,但是由于 Python 中没有数据类型,我如何确保调用第三个方法而不是调用第二,当我给出一个字符串而不是一个 int 作为参数时?
class Handle:
def __init__(self):
self.pid = -1
def __init__(self, pid):
self.pid = pid
def __init__(self, procname):
print(procname)
self.pid = -1 # find pid by name
使用isinstance
检查类型:
class Handle:
def __init__(self, arg):
if isinstance(arg, str):
self.pid = arg
else:
self.pid = -1
如果您想执行一个或另一个操作,您最好将 arg 设置为 None 并根据是否设置来使用它:
class Handle:
def __init__(self, by_name=None):
self.by_name = by_name
那以后再看看是不是None:
if self.by_name is not None:
# find by name
else:
# by pid
如果您希望用户可以选择传递 pid 或名称:
class Handle:
def __init__(self, by_name=None,by_pid=None):
self.by_name = by_name
self.by_pid = by_pid
最简单的解决方案是采用单个 arg 并将逻辑移动到您调用它的任何地方,只是因为某些东西不是 None
不会使它成为 int 或 string,因此您还应该检查它或你的程序会出错:
class Handle:
def __init__(self, proc):
self.proc = proc
if not isinstance(self.proc, (int,str)):
raise ValueError("Must be process name or pid.")
def find_proc(self):
if isinstance(self.proc, str):
# find by name
else:
# by pid
在 C++ 中,您可以定义多个具有相同名称和不同签名的 functions/methods。在 Python 中,每次您定义一个与先前定义的函数同名的新函数时,您都在替换它。
要实现您想要的效果,您必须使用可选参数and/or 显式检查。
以下是一些可能的解决方案:
class Handle:
def __init__(self, pid=-1):
if isinstance(pid, str):
self.procname = pid
self.pid = -1
else:
self.procname = None
self.pid = pid
class Handle:
# Both pid and procname may be specified at the same time.
def __init__(self, pid=-1, procname=None):
self.procname = procname
self.pid = pid
class Handle:
# Either pid or procname, not both, may be specified.
def __init__(self, pid=-1, procname=None):
if pid >= 0 and procname is not None:
raise ValueError('you can specify either pid or procname, not both')
self.procname = procname
self.pid = pid
class Handle:
def __init__(self, pid=-1):
self.pid = pid
# A separate constructor, with a different name,
# because "explicit is better than implicit" and
# "sparse is better than dense" (cit. The Zen of
# Python).
# In my opinion, this is the most Pythonic solution.
@classmethod
def from_process_name(cls, procname):
pid = get_pid(procname)
return cls(pid)
顺便说一下,我不建议对 "not specified" 使用 -1
。我宁愿使用 None
.
难道 PEP 443 : 单分派通用函数 对你的情况有用吗?
类似的东西(非常基本的例子):
from functools import singledispatch
class Handle:
def __init__(self, arg=None):
self.pid = init_from_arg(arg)
@singledispatch
def init_from_arg(arg):
# If None or neither an integer nor a string, return None
return None
# If the argument is an integer (ie the pid)
@init_from_arg.register(int)
def _(arg):
return arg
# If the argument provided is a string (ie the procname)
@init_from_arg.register(str)
def _(arg):
return get_pid_from_procname(arg)
编辑:按照评论中的建议,这些函数可能会成为静态方法,尽管我在使用它们时遇到了麻烦,所以我恢复了原始答案的代码(如果需要,请参阅编辑历史)
如何在 Python 中重载 __init__()
?我习惯了 C/C++,编译器可以看到数据类型的差异,但是由于 Python 中没有数据类型,我如何确保调用第三个方法而不是调用第二,当我给出一个字符串而不是一个 int 作为参数时?
class Handle:
def __init__(self):
self.pid = -1
def __init__(self, pid):
self.pid = pid
def __init__(self, procname):
print(procname)
self.pid = -1 # find pid by name
使用isinstance
检查类型:
class Handle:
def __init__(self, arg):
if isinstance(arg, str):
self.pid = arg
else:
self.pid = -1
如果您想执行一个或另一个操作,您最好将 arg 设置为 None 并根据是否设置来使用它:
class Handle:
def __init__(self, by_name=None):
self.by_name = by_name
那以后再看看是不是None:
if self.by_name is not None:
# find by name
else:
# by pid
如果您希望用户可以选择传递 pid 或名称:
class Handle:
def __init__(self, by_name=None,by_pid=None):
self.by_name = by_name
self.by_pid = by_pid
最简单的解决方案是采用单个 arg 并将逻辑移动到您调用它的任何地方,只是因为某些东西不是 None
不会使它成为 int 或 string,因此您还应该检查它或你的程序会出错:
class Handle:
def __init__(self, proc):
self.proc = proc
if not isinstance(self.proc, (int,str)):
raise ValueError("Must be process name or pid.")
def find_proc(self):
if isinstance(self.proc, str):
# find by name
else:
# by pid
在 C++ 中,您可以定义多个具有相同名称和不同签名的 functions/methods。在 Python 中,每次您定义一个与先前定义的函数同名的新函数时,您都在替换它。
要实现您想要的效果,您必须使用可选参数and/or 显式检查。
以下是一些可能的解决方案:
class Handle:
def __init__(self, pid=-1):
if isinstance(pid, str):
self.procname = pid
self.pid = -1
else:
self.procname = None
self.pid = pid
class Handle:
# Both pid and procname may be specified at the same time.
def __init__(self, pid=-1, procname=None):
self.procname = procname
self.pid = pid
class Handle:
# Either pid or procname, not both, may be specified.
def __init__(self, pid=-1, procname=None):
if pid >= 0 and procname is not None:
raise ValueError('you can specify either pid or procname, not both')
self.procname = procname
self.pid = pid
class Handle:
def __init__(self, pid=-1):
self.pid = pid
# A separate constructor, with a different name,
# because "explicit is better than implicit" and
# "sparse is better than dense" (cit. The Zen of
# Python).
# In my opinion, this is the most Pythonic solution.
@classmethod
def from_process_name(cls, procname):
pid = get_pid(procname)
return cls(pid)
顺便说一下,我不建议对 "not specified" 使用 -1
。我宁愿使用 None
.
难道 PEP 443 : 单分派通用函数 对你的情况有用吗?
类似的东西(非常基本的例子):
from functools import singledispatch
class Handle:
def __init__(self, arg=None):
self.pid = init_from_arg(arg)
@singledispatch
def init_from_arg(arg):
# If None or neither an integer nor a string, return None
return None
# If the argument is an integer (ie the pid)
@init_from_arg.register(int)
def _(arg):
return arg
# If the argument provided is a string (ie the procname)
@init_from_arg.register(str)
def _(arg):
return get_pid_from_procname(arg)
编辑:按照评论中的建议,这些函数可能会成为静态方法,尽管我在使用它们时遇到了麻烦,所以我恢复了原始答案的代码(如果需要,请参阅编辑历史)