Затварање Питхона: Како га користити и зашто?

У овом упутству ћете научити о затварању Питхона, како дефинисати затварање и разлозима због којих бисте га требали користити.

Нелокална променљива у угнежђеној функцији

Пре него што уђемо у закључак, прво морамо да схватимо шта је угнежђена функција и нелокална променљива.

Функција дефинисана унутар друге функције назива се угнежђена функција. Угњежђене функције могу приступити променљивим опсега који обухвата.

У Питхону су ове не-локалне променљиве подразумевано само за читање и морамо их експлицитно прогласити не-локалним (користећи нелокалну кључну реч) да бисмо их модификовали.

Следи пример угнежђене функције која приступа не-локалној променљивој.

 def print_msg(msg): # This is the outer enclosing function def printer(): # This is the nested function print(msg) printer() # We execute the function # Output: Hello print_msg("Hello")

Оутпут

 Здраво

Видимо да је угнежђена printer()функција била у могућности да приступи не-локалној променљивој мсг функције која обухвата.

Дефинисање функције затварања

У горњем примеру, шта би се догодило ако последњи ред функције print_msg()врати printer()функцију уместо да је позове? То значи да је функција дефинисана на следећи начин:

 def print_msg(msg): # This is the outer enclosing function def printer(): # This is the nested function print(msg) return printer # returns the nested function # Now let's try calling this function. # Output: Hello another = print_msg("Hello") another()

Оутпут

 Здраво

То је необично.

print_msg()Функција је назван са низом "Hello"и вратила функција је обавезан да на име другог. По позиву another(), порука се и даље памтила, иако смо већ завршили извршавање print_msg()функције.

Ова техника помоћу које се неки подаци ( "Helloу овом случају) везују за код назива се затварање у Питхону .

Ова вредност у опсегу који се затвара памти се чак и када променљива излази из опсега или се сама функција уклони из тренутног простора имена.

Покушајте да покренете следеће у Питхон љусци да бисте видели излаз.

 >>> del print_msg >>> another() Hello >>> print_msg("Hello") Traceback (most recent call last):… NameError: name 'print_msg' is not defined

Овде враћена функција и даље ради чак и када је оригинална функција избрисана.

Када имамо затварања?

Као што се види из горњег примера, имамо затварање у Питхону када се угнежђена функција позива на вредност у свом опсегу затварања.

Критеријуми који морају бити испуњени да би се створило затварање у Питхону сумирани су у следећим тачкама.

  • Морамо имати угнежђену функцију (функцију унутар функције).
  • Угњежђена функција мора се односити на вредност дефинисану у приложеној функцији.
  • Функција затварања мора вратити угнијежђену функцију.

Када користити затвараче?

Па чему служе затварања?

Затварање може да избегне употребу глобалних вредности и пружа неки облик скривања података. Такође може пружити објектно оријентисано решење проблема.

Када постоји неколико метода (у већини случајева једна метода) које треба применити у класи, затварања могу пружити алтернативно и елегантније решење. Али када се број атрибута и метода повећа, боље је применити класу.

Ево једноставног примера где би затварање могло бити пожељније од дефинисања класе и израде објеката. Али преференција је твоја.

 def make_multiplier_of(n): def multiplier(x): return x * n return multiplier # Multiplier of 3 times3 = make_multiplier_of(3) # Multiplier of 5 times5 = make_multiplier_of(5) # Output: 27 print(times3(9)) # Output: 15 print(times5(3)) # Output: 30 print(times5(times3(2)))

Оутпут

 27 15 30

Питхон Децораторс такође широко користе затвараче.

На крају, добро је истаћи да се вредности које су затворене у функцији затварања могу сазнати.

Сви функционални објекти имају __closure__атрибут који враћа скуп ћелијских објеката ако је функција затварања. Позивајући се на горњи пример, знамо times3и times5јесу функције затварања.

 >>> make_multiplier_of.__closure__ >>> times3.__closure__ (,)

Објекат ћелије има атрибут целл_цонтентс који чува затворену вредност.

 >>> times3.__closure__(0).cell_contents 3 >>> times5.__closure__(0).cell_contents 5

Занимљиви Чланци...