как вызывается функция в Python, просто набрав имя функции и не используя скобки - PullRequest
0 голосов
/ 06 октября 2018

Прежде всего, чтобы найти «lcm» из двух чисел, я сделал функцию lcm(a, b).Затем я подумал о том, чтобы найти «hcf», поэтому я создал декоратор decor и определил в нем функцию hcf(a, b).А потом я вернул эту функцию, просто набрав имя функции, и я не поставил с ней скобки, но она все еще работает.Я не могу понять, почему эта функция работает, хотя я не использовал скобки.

def decor(lcm_arg):        # just to practice decorators
    def hcf(a, b):
        if a > b:
            a, b = b, a
        while True:
            if b % a == 0:
                print("hcf is", a)
                break
            else:
                a, b = b % a, a
        return lcm_arg(a, b)
    return hcf              # how hcf function is working without using brackets

@decor
def lcm(a, b):
    if a > b:
        a, b = b, a
    for x in range(b, a*b+1, b):
        if x % a == 0:
            print("lcm is", x)
            break


lcm(2, 4)

Вывод:

hcf is 2
lcm is 4

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

return hcf не вызывает функцию, потому что, как вы заметили, круглых скобок нет.Функция decor используется в качестве декоратора, который переназначает имя lcm для ссылки на возвращаемую функцию.Под этим я подразумеваю, что

@decor
def lcm(a, b):
    // ...

эквивалентно

def lcm(a, b):
    // ...

lcm = decor(lcm)

. После этого lcm относится к функции hcf.Таким образом, вызов lcm(2, 4) теперь выполняет код в hcf.Я думаю, что ключом здесь является понимание того, что в строке lcm(2, 4), lcm и hcf - это два имени, которые относятся к одной и той же функции.

0 голосов
/ 06 октября 2018

Не думаю, что вы понимаете декораторов.Давайте сделаем минимальный пример.

def my_decorator(some_function):        
    def new_function(*args, **kwargs):
        'announces the result of some_function, returns None'
        result = some_function(*args, **kwargs)
        print('{} produced {}'.format(some_function.__name__, result))
    return new_function # NO FUNCTION CALL HERE!

@my_decorator
def my_function(a, b):
    return a + b

my_function(1, 2) # will print "my_function produced 3"

У нас есть простая функция my_function, которая возвращает сумму двух своих аргументов, и декоратор, который просто распечатает результат любой функции, которую он украшает.

Обратите внимание, что

@my_decorator
def my_function(a, b):
    return a + b

эквивалентно

def my_function(a, b):
    return a + b

my_function = my_decorator(my_function)

Поскольку my_decorator принимает функцию в качестве аргумента (здесь мы даем ее my_function) и возвращает новая функция new_function (без вызова!), Мы фактически переопределяем my_function, потому что мы переназначаем имя на то, что возвращает my_decorator.

В действии:

>>> my_function(1, 2)
my_function produced 3

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

  1. my_decorator(my_function) вызывается и возвращаемое значение переназначается на имя my_function.Это происходит либо через синтаксис @, либо более явно в эквивалентном фрагменте кода. Вызывается
  2. my_function(1, 2).На этом этапе my_function - это new_function, полученный декоратором.Проанализируйте его как new_function(1, 2).
  3. Внутри тела new_function аргумент, который мы дали my_decorator, называется (result = some_function(*args, **kwargs)), что является значением my_function до переназначения, которое произошло в шаге 1 .
  4. print.

Если вы хотите понять, как new_function удерживает some_functionнесмотря на то, что my_decorator уже вернулся с вызова, я предлагаю изучить темы свободные переменные и замыкания .

...