Что такое синтаксическая функция вложенного определения в Python? - PullRequest
0 голосов
/ 05 июля 2018

Ниже приведена модель, заданная модулем.

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

Я никогда не видел этого раньше.

Как это работает?

def load(filepath, shape_only=False):
  def readpca(f, nv):
    nc,nd  = struct.unpack('<II', f.read(8))
    assert(nd == 3*nv)
    funcs  = [[struct.unpack('<d', f.read(8))[0] for d in range(nd)]
              for c in range(nc)]
    (nm,)  = struct.unpack('<I', f.read(4))
    assert(nm == 3*nv)
    # fyi: elements are ordered x1,y1,z1,x2,y2,z2,...xnv,ynv,znv.
    vmean  = [struct.unpack('<d', f.read(8))[0] for i in range(nm)]
    (ne,)  = struct.unpack('<I', f.read(4))
    values = [struct.unpack('<d', f.read(8))[0] for i in range(ne)]
    return PCAModel(vmean, funcs, values)

  with open(filepath, 'rb') as f:
    nv,nt = struct.unpack('<II', f.read(8))
    # fyi: faces is a list of tuples (each tuple contains 3 vertex indices).
    faces = [struct.unpack('<III', f.read(12)) for i in range(nt)]
    shape = readpca(f, nv)
    try:
      textr = None if shape_only else readpca(f, nv)
    except Exception:
      print('No texture data. Returning shape-only model.')
      textr = None

  return MorphModel(faces, shape, textr)

1 Ответ

0 голосов
/ 05 июля 2018

Определение функции в Python:

def foo():
    pass

и присвоение переменной:

foo = 17

полностью идентичны, за исключением того, что одно связывает с переменной (foo) значение функции, а другое - нефункциональное значение (и тот факт, что Python решил сделать их дико отличными друг от друга, синтаксически).

Итак, давайте посмотрим, в чем будет разница между следующими двумя?

foo = 17
def bar():
    print(foo)

def bar():
    foo = 17
    print(foo)

В первом область действия переменной foo шире, чем функция bar; во втором foo является локальным по отношению к bar.

Почти то же самое в вашем случае. Для функции load требуется вспомогательная функция readpca, но она не заинтересована в том, чтобы она была доступна вне load, поэтому она определяет ее как локальную для функции.

На самом деле, с функциями это немного сложнее из-за концепции замыкания: tl; dr заключается в том, что функция будет иметь доступ к переменным среды, в которой она определена. Она здесь вообще не используется, но readpca будет иметь доступ к переменным filepath и readonly, если захочет; если readpca было определено за пределами load, они должны были бы быть переданы через дополнительные параметры, если бы readpca интересовалось ими. Этот эффект закрытия является еще одной причиной, по которой функция может быть определена внутри другой функции.

...