Python重载__init__

时间:2015-12-27 18:54:32

标签: python oop override

如何在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

3 个答案:

答案 0 :(得分:6)

在C ++中,您可以定义具有相同名称和不同签名的多个函数/方法。在Python中,每次定义一个与之前定义的函数名称相同的新函数时,都要替换它。

要实现您的目标,您必须使用可选参数和/或显式检查。

以下是一些可能的解决方案:

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)

顺便说一句,我不建议将-1用于“未指定”。我宁愿使用None

答案 1 :(得分:3)

PEP 443 单一调度通用函数 无法在您的案例中发挥作用吗?

有类似(非常基本的例子):

from functools import singledispatch

class Handle:
    def __init__(self, arg=None):
        self.pid = init_from_arg(arg)

    @singledispatch
    @staticmethod
    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)
    @staticmethod
    def _(arg):
        return arg

    # If the argument provided is a string (ie the procname)
    @init_from_arg.register(str)
    @staticmethod
    def _(arg):
        return get_pid_from_procname(arg)

根据评论中的建议,编辑将这些函数作为Handle类的一部分作为staticmethod

答案 2 :(得分:2)

使用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

然后稍后检查它是否为无:

  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或字符串所以你也应该检查它或你的程序会出错:

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