Методы с тем же именем в одном классе в python?
Как объявить несколько методов с тем же именем, но с различным количеством параметров или разных типов в одном классе?
Что мне нужно изменить в этом классе:
class MyClass:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
def my_method(self,parameter_A_that_Must_Be_String):
print parameter_A_that_Must_Be_String
def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
print parameter_A_that_Must_Be_String
print parameter_B_that_Must_Be_String
def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int
Ответы
Ответ 1
У вас может быть функция, которая принимает переменное количество аргументов.
def my_method(*args, **kwds):
# do something
# when you call the method
my_method(a1, a2, k1=a3, k2=a4)
# you get:
args = (a1, a2)
kwds = {'k1':a3, 'k2':a4}
Итак, вы можете изменить свою функцию следующим образом:
def my_method(*args):
if len(args) == 1 and isinstance(args[0], str):
# case 1
elif len(args) == 2 and isinstance(args[1], int):
# case 2
elif len(args) == 2 and isinstance(args[1], str):
# case 3
Ответ 2
Вы не можете. Не существует перегрузок или мультиметодов или подобных вещей. Одно имя относится к одной вещи. Что касается языка в любом случае, вы всегда можете имитировать их самостоятельно... Вы можете проверять типы с помощью isinstance
(но, пожалуйста, сделайте это правильно - например, в Python 2, используйте basestring
для обнаружения как строк, так и unicode), но он уродливый, обычно обескураженный и редко полезный. Если методы делают разные вещи, дайте им разные имена. Рассмотрим также полиморфизм.
Ответ 3
Короткий ответ: вы не можете (посмотреть предыдущее обсуждение). Как правило, вы должны использовать что-то вроде (вы можете добавить больше проверки типов и изменить порядок):
def my_method(self,parameter_A, parameter_B=None):
if isinstance(parameter_B, int):
print parameter_A * parameter_B
else:
print parameter_A
if parameter_B is not None:
print parameter_B
Ответ 4
Вы можете попробовать мультиметоды в Python:
http://www.artima.com/weblogs/viewpost.jsp?thread=101605
Но я не считаю, что мультиметод - это путь. Скорее объекты, которые вы передаете методу, должны иметь общий интерфейс. Вы пытаетесь добиться перегрузки метода, аналогичной той, что и на С++, но это очень редко требуется в python. Один из способов сделать это - каскад ifs
с помощью isinstance
, но этот уродливый.
Ответ 5
Python не похож на Java.
На самом деле нет типов, просто объектов с методами.
Есть способ проверить, прошел ли переданный объект из класса, но в основном это неправильная практика.
Однако код, который вы хотите создать для двух первых методов, должен быть чем-то вроде
class MyClass(object):
def my_method(self, str1, str2=None):
print str1
if str2: print str2
Для третьего, ну... Используйте другое имя...
Ответ 6
Вероятно, вам нужен шаблон, похожий на следующий:
Обратите внимание, что добавление '_' в начало имени метода является условным обозначением частного метода.
class MyClass:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
def my_method(self,parameter_A_that_Must_Be_String, param2=None):
if type(param2) == str:
return self._my_method_extra_string_version(parameter_A_that_Must_Be_String, param2)
elif type(param2) == int:
return self._my_method_extra_int_version(parameter_A_that_Must_Be_String, param2)
else:
pass # use the default behavior in this function
print parameter_A_that_Must_Be_String
def _my_method_extra_string_version(self,parameter_A_that_Must_Be_String, parameter_B_that_Must_Be_String):
print parameter_A_that_Must_Be_String
print parameter_B_that_Must_Be_String
def _my_method_extra_int_version(self,parameter_A_that_Must_Be_String, parameter_A_that_Must_Be_Int):
print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int
Ответ 7
class MyClass:
def __init__(this, foo_str, bar_int):
this.__foo = foo_str
this.__bar = bar_int
def foo(this, new=None):
if new != None:
try:
this.__foo = str(new)
except ValueError:
print("Illegal value. foo unchanged.")
return this.__foo
def bar(this, new=None):
if new != None:
try:
this.__bar = int(new)
except ValueError:
print("Illegal value. bar unchanged.")
return this.__bar
obj = MyClass("test", 42)
print(obj.foo(), obj.bar())
print(obj.foo("tset"), obj.bar(24))
print(obj.foo(42), obj.bar("test"))
Output:
test 42
tset 24
Illegal value. bar unchanged.
42 24
Ответ 8
Я думаю, что один очень простой пример отсутствует во всех ответах, а именно: что делать, когда единственная разница между вариациями метода - это количество аргументов. Ответ по-прежнему заключается в использовании метода с переменным числом аргументов.
Скажем, вы начинаете с метода, который требует использования двух аргументов
def method(int_a, str_b):
print("Got arguments: '{0}' and '{1}'".format(int_a, str_b)
тогда вам нужно добавить вариант только с помощью второго аргумента (скажем, потому что целое является избыточным), решение очень просто:
def _method_2_param(int_a, str_b):
print("Got arguments: '{0}' and '{1}'".format(int_a, str_b))
def _method_1_param(str_b):
print("Got argument: '{0}'".format(str_b))
def method(*args, **kwargs):
if len(args) + len(kwargs) == 2:
return _method_2_param(args, kwargs)
elif len(args) + len(kwargs) == 1:
return _method_1_param(args, kwargs)
else:
raise TypeError("Method requires one or two arguments")
Самое приятное в этом решении заключается в том, что независимо от того, использовали ли вызывающий код ключевые аргументы или позиционные аргументы, он все равно будет продолжать работать.
Ответ 9
Это не может работать. Независимо от того, сколько аргументов у вас есть, имя m
будет переопределено вторым методом m
.
class C:
def m(self):
print('m first')
def m(self, x):
print(f'm second {x}')
ci=C();
#ci.m() # will not work TypeError: m() missing 1 required positional argument: 'x'
ci.m(1) # works
Результат будет простым:
m second 1