Множественное наследование страдает от проблемы Diamond , которая еще не была (согласована с тем, как быть) в PHP. Таким образом, на PHP не существует множественного наследования.
BaseClass
/\
/ \
ClassA ClassB
\ /
\/
ClassC
Если оба ClassA
и ClassB
определили свой собственный метод foo()
, который вы бы назвали в ClassC
?
Вам рекомендуется либо использовать структуру объекта , либо интерфейсы (которые допускают множественное наследование), либо - если вы после повторного использования по горизонтали - посмотрите на Decorator или Strategy до тех пор, пока у нас не будут Черты (или Прививки или что бы они там ни назывались).
Некоторая ссылка:
Одинарная звезда *
распаковывает последовательность/коллекцию в позиционные аргументы, поэтому вы можете сделать следующее:
def sum(a, b):
return a + b
values = (1, 2)
s = sum(*values)
Это распакует кортеж так, что он фактически будет выполняться как:
s = sum(1, 2)
Двойная звезда **
делает то же самое, только использует словарь и, следовательно, именованные аргументы:
values = { 'a': 1, 'b': 2 }
s = sum(**values)
Вы также можете комбинировать:
def sum(a, b, c, d):
return a + b + c + d
values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)
будет выполняться как:
s = sum(1, 2, c=10, d=15)
Также смотрите раздел 4.7.4 - Распаковка списков аргументов документации по Python.
Дополнительно вы можете определить функции, принимающие *x
и **y
аргументы. Это позволяет функции принимать любое количество позиционных и/или именованных аргументов, которые не названы в объявлении.
Пример:
def sum(*values):
s = 0
for v in values:
s = s + v
return s
s = sum(1, 2, 3, 4, 5)
или с **
:
def get_a(**values):
return values['a']
s = get_a(a=1, b=2) # returns 1
это может позволить вам указать большое количество необязательных параметров без необходимости их объявления.
И опять же, вы можете комбинировать:
def sum(*values, **options):
s = 0
for i in values:
s = s + i
if "neg" in options:
if options["neg"]:
s = -s
return s
s = sum(1, 2, 3, 4, 5) # returns 15
s = sum(1, 2, 3, 4, 5, neg=True) # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
Одна маленькая деталь: это не операторы. Операторы используются в выражениях для создания новых значений из существующих значений (например, 1 + 2 становится 3. Символы * и ** здесь являются частью синтаксиса объявлений и вызовов функций.
Я считаю это особенно полезным, когда вы хотите «сохранить» вызов функции.
Например, предположим, что у меня есть несколько модульных тестов для функции add:
def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
print 'test: adding', test, '==', result, '---', add(*test) == result
Нет другого способа вызвать add, кроме ручного выполнения чего-то вроде add (test [0], test [1]), что уродливо. Кроме того, если есть переменное количество переменных, код может стать довольно уродливым со всеми необходимыми операторами if.
Еще одно место, где это полезно, - это определение объектов Factory (объектов, которые создают объекты за вас). Предположим, у вас есть класс Factory, который создает объекты Car и возвращает их. Вы можете сделать так, чтобы myFactory.make_car ('red', 'bmw', '335ix') создавал Car ('red', 'bmw', '335ix'), а затем возвращал его.
def make_car(*args):
return Car(*args)
Это также полезно, когда вы хотите вызвать конструктор суперкласса.
Он называется расширенным синтаксисом вызова. Из документации:
Если в вызове функции встречается синтаксис *выражение, то выражение должно оцениваться как последовательность. Элементы из этой последовательности рассматриваются как дополнительные позиционные аргументы; если есть позиционные аргументы x1, ..., xN, а выражение оценивается в последовательность y1, ..., yM, это эквивалентно вызову с M+N позиционными аргументами x1, ..., xN, y1, ..., yM.
и:
Если в вызове функции появляется синтаксис **выражение, то выражение должно оцениваться как отображение, содержимое которого рассматривается как дополнительные аргументы ключевого слова. В случае, когда ключевое слово встречается и в выражении, и в качестве явного аргумента ключевого слова, возникает исключение TypeError.
В вызове функции одна звездочка превращает список в отдельные аргументы (например, zip (* x)
то же самое, что zip (x1, x2, x3 )
if x = [x1, x2, x3]
) и двойная звездочка превращает словарь в отдельные аргументы ключевого слова (например, f (** k)
то же самое, что f (x = my_x, y = my_y)
if k = {'x': my_x, 'y': my_y}
.
В определении функции все наоборот вокруг: одиночная звездочка превращает произвольное количество аргументов в список, а двойное начало превращает произвольное количество аргументов ключевого слова в словарь. Например, def foo (* x)
означает «foo принимает произвольное число аргументов, и они будут доступны через список x (т.е. если пользователь вызовет foo (1,2,3)
, x
будет [1,2,3 ]
) "и def bar (** k)
означает, что" bar принимает произвольное количество аргументов ключевого слова, и они будут доступны через dic стационарный k (т. е. если пользователь вызывает bar (x = 42, y = 23)
, k
будет {'x': 42, 'y': 23}
) ".