Что означает звездный оператор? [Дубликат]

Множественное наследование страдает от проблемы Diamond , которая еще не была (согласована с тем, как быть) в PHP. Таким образом, на PHP не существует множественного наследования.

    BaseClass
       /\
      /  \
 ClassA  ClassB
      \  /
       \/
     ClassC

Если оба ClassA и ClassB определили свой собственный метод foo(), который вы бы назвали в ClassC?

Вам рекомендуется либо использовать структуру объекта , либо интерфейсы (которые допускают множественное наследование), либо - если вы после повторного использования по горизонтали - посмотрите на Decorator или Strategy до тех пор, пока у нас не будут Черты (или Прививки или что бы они там ни назывались).

Некоторая ссылка:

533
задан ShadowRanger 22 March 2019 в 20:35
поделиться

5 ответов

Одинарная звезда * распаковывает последовательность/коллекцию в позиционные аргументы, поэтому вы можете сделать следующее:

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
858
ответ дан 22 November 2019 в 22:16
поделиться

Одна маленькая деталь: это не операторы. Операторы используются в выражениях для создания новых значений из существующих значений (например, 1 + 2 становится 3. Символы * и ** здесь являются частью синтаксиса объявлений и вызовов функций.

40
ответ дан 22 November 2019 в 22:16
поделиться

Я считаю это особенно полезным, когда вы хотите «сохранить» вызов функции.

Например, предположим, что у меня есть несколько модульных тестов для функции 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)

Это также полезно, когда вы хотите вызвать конструктор суперкласса.

17
ответ дан 22 November 2019 в 22:16
поделиться

Он называется расширенным синтаксисом вызова. Из документации:

Если в вызове функции встречается синтаксис *выражение, то выражение должно оцениваться как последовательность. Элементы из этой последовательности рассматриваются как дополнительные позиционные аргументы; если есть позиционные аргументы x1, ..., xN, а выражение оценивается в последовательность y1, ..., yM, это эквивалентно вызову с M+N позиционными аргументами x1, ..., xN, y1, ..., yM.

и:

Если в вызове функции появляется синтаксис **выражение, то выражение должно оцениваться как отображение, содержимое которого рассматривается как дополнительные аргументы ключевого слова. В случае, когда ключевое слово встречается и в выражении, и в качестве явного аргумента ключевого слова, возникает исключение TypeError.

16
ответ дан 22 November 2019 в 22:16
поделиться

В вызове функции одна звездочка превращает список в отдельные аргументы (например, 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} ) ".

14
ответ дан 22 November 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: