Pagpasa ng Sanggunian sa Python: Mga Kaso ng Mutable at Immutable

1. Pagkakaiba ng Pagpasa sa Halaga at Pagpasa sa Sanggunian

Sa Python, may dalawang paraan ng pagpasa ng mga argumento sa mga function: pass-by-value at pass-by-reference.

  • Pass-by-value : Isang paraan kung saan isang kopya ng halaga ang ipinapasa sa function bilang argumento; ang pagbabago ng parameter sa loob ng function ay hindi nakaaapekto sa orihinal na variable.
  • Pass-by-reference : Isang paraan kung saan isang sanggunian (address) sa variable ang ipinapasa sa function, kaya ang mga pagbabago sa loob ng function ay nasasalamin sa orihinal na variable.

Sa Python, ang pag-uugaling ito ay nag-iiba depende sa likas na katangian ng object. Ang “pass-by-reference” na pag-uugali ng Python ay partikular na naaangkop sa mga mutable na data type at maaaring malaki ang epekto sa kung paano gumagana ang code, kaya mahalagang maunawaan ito nang tama.

2. Katangian ng mga Object sa Python

Sa Python, lahat ng data ay itinuturing na mga object, at batay sa kanilang katangian ay kiniklasipika bilang immutable (hindi maaaring baguhin) o mutable (maaaring baguhin). Ang pagkakaibang ito ay nakaaapekto kung paano sila kumikilos kapag ipinasa bilang mga argumento sa mga function.

  • Immutable objects : mga object na hindi maaaring baguhin pagkatapos malikha. Halimbawa ay mga integer (int), floating‑point numbers (float), string (str), tuple (tuple). Dahil ang mga data type na ito ay hindi maaaring baguhin kapag nalikha na, ang mga operasyon sa kanila sa loob ng function ay hindi nakaaapekto sa tumatawag kahit na ipinasa sa pamamagitan ng sanggunian.
  • Mutable objects : mga object na maaaring baguhin pagkatapos malikha. Halimbawa ay mga list (list), dictionary (dict), set (set). Dahil ang mga pagbabago sa mga data type na ito sa loob ng function ay nasasalamin sa tumatawag, sila ay partikular na naaapektuhan ng pag‑pasang sanggunian ng Python.

年収訴求

3. Paano Nagpasa ng mga Argumento ang Python

Sa Python, kapag nagpasa ka ng mga argumento sa isang function, mga sanggunian sa mga object ang ipinapasa. Ang pag‑ugaling ito ay minsang tinatawag na “pass-by-object-reference.” Mula dito, tatalakayin natin ang mga konkretong halimbawa na naglalarawan ng pag‑ugali ng Python depende kung ang mga object ay immutable o mutable.

3.1 Immutable Objects

Kapag nagpasa ka ng immutable na object sa isang function, ang pag‑assign ng bagong halaga sa loob ng function ay lumilikha ng bagong object at hindi nakaaapekto sa orihinal na object.

Halimbawa: Pagpasa ng Immutable Integer

def modify_number(num):
    num = num * 2
    print("Number inside the function:", num)

original_num = 5
modify_number(original_num)
print("Number outside the function:", original_num)

Output:

Number inside the function: 10
Number outside the function: 5

Paliwanag

Sa loob ng function na modify_number, ang variable na num ay dinodoble, ngunit hindi ito nakaaapekto sa original_num sa labas ng function. Dahil ang mga integer ay immutable, isang bagong object ang nilikha kapag nag‑assign ng bagong halaga, at nananatiling hindi nagbago ang original_num.

3.2 Mutable Objects

Sa kabilang banda, kapag nagpasa ka ng mutable na object sa isang function, ang sanggunian nito ay ginagamit din sa loob ng function. Bilang resulta, ang mga pagbabagong ginawa sa loob ng function ay nasasalamin din sa orihinal na object.

Halimbawa: Pagpasa ng Mutable List

def add_item(my_list):
    my_list.append("Added element")
    print("List inside the function:", my_list)

original_list = ["Element 1", "Element 2"]
add_item(original_list)
print("List outside the function:", original_list)

Output:

List inside the function: ['Element 1', 'Element 2', 'Added element']
List outside the function: ['Element 1', 'Element 2', 'Added element']

Paliwanag

Dahil ang mga list ay mutable, ang mga pagbabagong ginawa sa loob ng function na add_item ay direktang nasasalamin sa original_list sa labas ng function. Sa ganitong paraan, ang mga mutable na object ay ibinabahagi sa loob at labas ng function, kaya ang mga pagbabago sa loob ng function ay nakaaapekto rin sa tumatawag.

4. Mga Babala at Hakbang para sa Pagpasa sa Sanggunian

Ang pagpapasa ng mga mutable na object sa mga function sa Python ay maaaring magdulot ng hindi inaasahang pag-uugali. Narito ang ilang hakbang upang maiwasan ang mga ganitong isyu.

4.1 Gumamit ng Kopya ng mga Object

Kung nais mong baguhin ang isang object sa loob ng isang function, maaari mong iwasang maapektuhan ang orihinal sa pamamagitan ng pagkopya nito bago gumawa ng mga pagbabago. Sa Python, maaari mong gamitin ang copy module upang lumikha ng mga shallow copy (copy.copy) o deep copy (copy.deepcopy).

Halimbawa: Paggamit ng Deep Copy upang Maiwasan ang mga Isyu sa Mutable na Object

import copy

def add_item(my_list):
    my_list_copy = copy.deepcopy(my_list)
    my_list_copy.append("Added element")
    print("List inside the function (copy):", my_list_copy)

original_list = ["Element 1", "Element 2"]
add_item(original_list)
print("List outside the function:", original_list)

Output:

List inside the function (copy): ['Element 1', 'Element 2', 'Added element']
List outside the function: ['Element 1', 'Element 2']

Paliwanag
Sa pamamagitan ng paggamit ng deepcopy, isang bagong object ang nilikha sa loob ng function, na hindi naaapektuhan ang orihinal na list. Pinapayagan nito ang mga independiyenteng pagbabago sa loob at labas ng function.

4.2 Gumamit ng None para sa Default na Argumento

Iwasan ang pag-set ng mga mutable na object bilang default na argumento ng function; inirerekomenda na gamitin ang None bilang default at lumikha ng bagong object sa loob ng function.

Halimbawa: Ligtas na Paraan upang Gawing None ang Default na Argumento

def add_item(my_list=None):
    if my_list is None:
        my_list = []
    my_list.append("New element")
    print("List inside the function:", my_list)
    return my_list

# When no list is passed
result = add_item()
print("Returned list:", result)

# When a list is passed
existing_list = ["Element 1", "Element 2"]
result = add_item(existing_list)
print("Returned list:", result)
print("Original list:", existing_list)

Output:

List inside the function: ['New element']
Returned list: ['New element']
List inside the function: ['Element 1', 'Element 2', 'New element']
Returned list: ['Element 1', 'Element 2', 'New element']
Original list: ['Element 1', 'Element 2', 'New element']

Paliwanag
Sa pamamagitan ng paggamit ng default na argumento na None at pagbuo ng bagong list sa loob ng function, maiiwasan mong mabago nang hindi sinasadya ang mga external na list. Ang pag-set ng None bilang default na argumento ay naglilinaw kung kailan dapat lumikha ng bagong list o gamitin ang ibinigay na list.

年収訴求

5. Praktikal na Halimbawa: Code upang Palalimin ang Pag-unawa sa Pass-by-Reference

Balikan natin ang mga tinalakay natin gamit ang isang praktikal na halimbawa.

Halimbawa: Pagbabago ng mga Susi at Halaga ng Dictionary

Ang mga dictionary ay mutable na mga object, kaya ang mga operasyon na ginawa sa loob ng isang function ay nakaaapekto sa dictionary sa labas ng function. Ipinapakita ng halimbawang nasa ibaba ang pag-uugali kapag binabago ang mga susi at halaga ng isang dictionary.

def modify_dict(my_dict):
    my_dict["new key"] = "new value"
    print("Dictionary inside the function:", my_dict)

original_dict = {"key1": "value1", "key2": "value2"}
modify_dict(original_dict)
print("Dictionary outside the function:", original_dict)

Output:

Dictionary inside the function: {'key1': 'value1', 'key2': 'value2', 'new key': 'new value'}
Dictionary outside the function: {'key1': 'value1', 'key2': 'value2', 'new key': 'new value'}

Paliwanag
Dahil ang mga dictionary ay mutable, ang mga karagdagang elemento na ginawa sa loob ng function ay nasasalamin din sa original_dict sa labas ng function. Katulad ng mga list, maaaring makaapekto ang mga dictionary sa tumatawag dahil ipinapasa ang mga ito sa pamamagitan ng reference.

6. Buod

Ang “pass-by-reference” ng Python ay kumikilos nang iba-iba depende sa katangian ng isang object, kaya mahalagang maunawaan ito upang mapabuti ang pagiging maaasahan ng iyong code. Lalo na, upang maiwasan ang hindi inaasahang pag-uugali mula sa pagpapasa ng mga reference sa mutable na mga object, inirerekomenda ang paggamit ng pagkopya at ang default na argumento na None.

Mga Punto ng Buod

  • Pagkakaiba ng pass-by-value at pass-by-reference : Sa Python, kung ang mga pagbabago sa loob ng isang function ay makakaapekto sa orihinal na variable ay nakadepende sa likas na katangian ng object.
  • Immutable vs. mutable : Ang mga immutable na object sa Python ay hindi nagrereflekta ng mga pagbabago na ginawa sa loob ng isang function, samantalang ang mga mutable na object ay ibinabahagi sa loob at labas ng function sa pamamagitan ng reference passing.
  • Mga estratehiya sa pag-iwas : Para sa mga mutable na object, mga pamamaraan tulad ng paggamit ng deepcopy mula sa copy module, o pagtatakda ng default na argumento sa None, ay epektibo upang maiwasan ang hindi inaasahang pag-uugali.

Sana ang artikulong ito ay nagpalalim ng iyong pag-unawa sa reference passing sa Python. Gamitin ang kaalamang ito upang lumikha ng epektibo at mas kaunting pagkakamaling code.

年収訴求