перегрузка метода в питоне - PullRequest
9 голосов
/ 15 марта 2012

Мне нужно вызвать непараметризованный метод first, но также параметризованный first, но он выдает ошибку.

>>> class A:
...     def first(self):
...             print 'first method'
...     def first(self,f):
...             print 'first met',f
...
>>> a=A()
>>> a.first()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: first() takes exactly 2 arguments (1 given) 

Возможно ли перегрузка методов в Python, как в Java?

Ответы [ 6 ]

11 голосов
/ 15 марта 2012

Ваш второй first метод переопределяет исходный first метод.В Python невозможно создать перегруженные методы так же, как в Java.

Однако вы можете создавать методы с необязательными и / или ключевыми аргументами и обрабатывать их соответствующим образом.Вот пример:

class A:
    def first(self, f=None):
        if f is not None:
            print 'first met', f
        else:
            print 'first method'

Использование:

a = A()
a.first()
a.first('something')
6 голосов
/ 28 июня 2015

Обычно вы можете определить только один метод в классе с заданным именем.В вашем примере метод first () с 2 аргументами переписал аргумент first () с 1 аргументом.Если вам нужны два метода с одним и тем же именем, в Python 3 вы должны использовать functools.singledispatch и сопоставить имя метода экземпляра с вашим диспетчером статических методов, Ой!

Тем не менее, мне действительно нравится неявная динамическая диспетчеризация в ОО-программировании, и я нахожу ее более чистой, чем написание логики ручной диспетчеризации в некоторой функции 'master' first (), которая является повторяющейся и хрупкой для расширения.

Задача: добавитьдругой метод, такой как A.first (A arg).

Возможно, вы многое узнаете о системе типов Python, если попытаетесь это сделать!

#!/opt/local/bin/python3.4

from functools import singledispatch;

class A(object):

    # default method handles dispatch for undefined types
    # note reversed positional args to match single dispatch functools
    @singledispatch
    def _first(self,arg):
        raise TypeError("no match for A._first(%s)" % type(arg));

    # adapter maps instance call to (reversed) static method call
    def first(self, arg = None): return A._first(arg, self);

    # def first()
    @_first.register(type(None))
    def _(self,none):
        print("A.first() called");

    # def first(float f)
    @_first.register(float)
    def _(self,f):
        print("A.first(float %s) called" % f);

a = A();
a.first();              # A.first() called
a.first(None);          # A.first() called
a.first(3.14);          # A.first(float 3.14) called

class B(object): pass;
b = B();                
try: a.first(b);        # no match for A._first(<class '__main__.B'>)
except TypeError as ex: print(ex);
6 голосов
/ 15 марта 2012

Python не выполняет перегрузку функций.Это является следствием того, что это язык со свободным шрифтом.Вместо этого вы можете указать неизвестное количество аргументов и разобраться с их интерпретацией в логике функции.

Есть несколько способов сделать это.Вы можете указать дополнительные необязательные аргументы:

def func1(arg1, arg2=None):
    if arg2 != None:
        print "%s %s" % (arg1, arg2)
    else:
        print "%s" % (arg1)

Вызывая его, мы получим:

>>> func1(1, 2)
1 2

Или вы можете указать неизвестное количество безымянных аргументов (т.е. аргументов, передаваемых в массиве):

def func2(arg1, *args):
    if args:
        for item in args:
            print item
    else:
        print arg1

Вызывая его, мы получаем:

>>> func2(1, 2, 3, 4, 5)
2
3
4
5

Или вы можете указать неизвестное количество именованных аргументов (т.е. аргументов, передаваемых в словаре):

def func3(arg1, **args):
    if args:
        for k, v in args.items():
            print "%s %s" % (k, v)
    else:
        print arg1

Вызывая его, мы получаем:

>>> func3(1, arg2=2, arg3=3)
arg2 2
arg3 3

Вы можете использовать эти конструкции для получения поведения, которое вы искали при перегрузке.

0 голосов
/ 24 декабря 2016

Проверьте этот код, если он полезен:

from math import pi

class Geometry:

    def area(self,length = None,breadth = None,side = None,radius = None):
        self.length = length
        self.breadth = breadth
        self.side = side
        self.radius = radius

        if length != None and breadth != None:
            return length * breadth
        elif side != None:
            return side * side
        else:
            return pi * radius * radius

obj1 = Geometry()
print('Area of rectangle is {0}.'.format(obj1.area(length=5,breadth=4)))
print('Area of square is {0}.'.format(obj1.area(side=5)))
print('Area of circle is {0:.6}.'.format(obj1.area(radius=10)))
0 голосов
/ 15 марта 2012

Хотя возможно создать систему, в которой используются перегруженные методы, она немного сложна и обычно не требуется.

Обычная идиома состоит в том, чтобы иметь по умолчанию ненужные параметры по умолчанию None, например:

class A:
    def first(self, f=None):
        if f is None:
            print 'first method'
        else:
            print 'first met',f

В вашем случае, когда вам нужно другое поведение в зависимости от того, является ли это первым вызовом этого метода, я бы сделал следующее:

class A:
    def first(self):
        print 'first method'
        self.first = self._first
    def _first(self, f):                   # '_' is convention for private name
        print 'first met',f

и пример вывода:

a = A()
a.first()
a.first(3)

печать:

first method
first met 3
0 голосов
/ 15 марта 2012

Python не является C ++ или Java;Вы не можете перегрузить методы одним и тем же способом.

Действительно, единственный способ сделать то, что вы хотите, это проверить наличие или отсутствие второго параметра:

class A:
   def first(self, f=None):
      if f is None:
         print 'first method'
      else:
         print 'first met',f

Выможет быть еще более изощренным и проверять тип f, но это может быть опасно и не всегда "питонно".(Тем не менее, следует отметить, что один из вариантов использования аннотаций функций в Python 3 - разрешить такого рода «общее программирование».)

...