Փոփոխելի (mutable) սկզբնադիր (default) արգումենտներ
Եթե Python-ում խառնենք փոփոխելի և սկզբնադիր (default) արգումենտները, ապա սա կարող է հանգեցնել անսպասելի արդյունքների:
Եկեք սա բացատրենք պարզ օրինակով. ենթադրենք՝ դուք ուսուցիչ եք և ցանկանում եք ստեղծել մի ֆունկցիա՝ տարբեր առաջադրանքներից հետո աշակերտի միավորները գրանցելու համար: Ձեզ անհրաժեշտ է ցուցակ, որպեսզի գրանցեք միավորները և հետևեք դրանց: Այսպիսով, դուք կարող եք սկզբում գրել հետևյալը.
def record_score(new_score, score_list=[]):
score_list.append(new_score)
return score_list
print(record_score(95)) # [95]
print(record_score(85)) # [95, 85]
Սա կարծես թե լավ է աշխատում:
record_score
ֆունկցիան ընդունում է միավոր և ցուցակ: Եթե ցուցակը չի տրամադրվում, այն օգտագործում է դատարկ ցուցակ (ֆունկցիայի սահմանման մեջ score_list=[]
):Երբ կանչում եք
record_score(95)
, թվում է, թե ֆունկցիան ճիշտ է աշխատում. այն վերադարձնում է ցուցակ 95 միավորով: Բայց երբ այնուհետև կանչում եք record_score(85)
, ֆունկցիան վերադարձնում է ցուցակ՝ 95-ով և 85-ով: Այնպիսի տպավորություն է, որ ֆունկցիան հիշում է վերջին անգամ կանչած ցուցակը:Սա մտածելու տեղիք է տալիս: Ծրագրավորման լեզուներից շատերում, երբ ֆունկցիան ավարտվում է, դրա բոլոր local (տողային) փոփոխականները (ինչպես
score_list
-ը) ջնջվում են և մոռացվում: Հաջորդ անգամ, երբ ֆունկցիայի կանչ է լինում, այն նորից է սկսվում:Սակայն Python-ում պատկերն այլ է այն դեպքում, երբ փոփոխական օբյեկտն օգտագործվում է որպես սկզբնադիր (default) արգումենտ։ Ծրագիրը սկզբնադիր արգումենտը ստեղծում է միայն մեկ անգամ՝ ֆունկցիան սահմանելու ժամանակ: Այսպիսով, ամեն անգամ, երբ դուք կանչում եք
record_score
-ն՝ առանց ցուցակ տրամադրելու, Python-ն օգտագործում է այն նույն ցուցակը, որը ստեղծել էր առաջին անգամ ֆունկցիան սահմանելիս: Եթե փոփոխում եք այդ ցուցակը (ավելացնելով տարր), փոփոխությունը պահպանվում է:Այսպիսով, մեր ֆունկցիայում
score_list
-ը կիրառվում է բոլոր այն ֆունկցիայի կանչերի հետ, որտեղ մենք չենք տրամադրում մեր ցուցակը: Ահա թե ինչու մեր օրինակում միավորներն ավելանում են:Բայց սա այն չէ, ինչ մենք ուզում էինք ստանալ: Մեր նպատակն էր, որ յուրաքանչյուր
record_score
-ի կանչ սկսվեր դատարկ ցուցակով, եթե մեր սեփական ցուցակը չենք տրամադրում։Սրանից խուսափելու համար սովորաբար
None
-ը որպես սկզբնադիր (default) արժեք ենք կիրառում այն արգումենտների համար, որոնք կարող են փոփոխական լինել: Այնուհետև ֆունկցիայի ներսում կարող ենք ստեղծել նոր փոփոխվող օբյեկտ, եթե արգումենտը None
է: Ահա թե ինչպես կարող եք գրել record_score
ֆունկցիան՝ խնդրից խուսափելու համար.def record_score(new_score, score_list=None):
if score_list is None: # If no list was provided,
score_list = [] # create a new one
score_list.append(new_score)
return score_list
print(record_score(95)) # [95]
print(record_score(85)) # [85]
Այս շտկված տարբերակում
record_score
-ի յուրաքանչյուր կանչ, որը չի փոխանցում իր սեփական ցուցակը, ստանում է ամբողջովին նոր ցուցակ: Այսպիսով, տվյալները (scores) չեն կրկնվում ֆունկցիայի տարբեր կանչերի դեպքում:💡
Ամփոփենք.
Փոփոխական սկզբնադիր (default) արգումենտները Python-ում կարող են հանգեցնել անակնկալ վարքի, քանի որ դրանք ստեղծվում են միայն մեկ անգամ, և նույն օբյեկտն օգտագործվում է ամեն անգամ, երբ ֆունկցիայի կանչ է տեղի ունենում: Սակայն սա կարող է խնդիր առաջացնել, հատկապես երբ փոխում եք փոփոխվող օբյեկտը: Ուստի, սրանից խուսափելու համար կարող եք օգտագործել
None
-ը որպես սկզբնադիր (default) արժեք և անհրաժեշտության դեպքում ֆունկցիայում ստեղծել նոր օբյեկտ: