Variable Scope

variable scope គឺ​ជា​ទី​កន្លែង​ផ្សេង​ៗ​នៅ​ក្នុង​សតិ​របស់​កំព្យូទ័រ ដែល​មាន​ព្រុំដែន​ច្បាស់​លាស់​។

ដែល​ហៅ​ថា global scope គឺ​ជា​ទីកន្លែង​នៅ​ខាង​ក្រៅ function ។ ដើម្បី​បង្កើត​វត្ថុ​ផ្សេង​ៗ​នៅ​ក្នុង​ global scope យើង​ត្រូវ​ធ្វើ​ដូច​ខាង​ក្រោម​នេះ៖

money_list = [2000, 1500]

def get_profit(sale=0, buy=0):
    profit = sale - buy
    print('The profit is', profit)

get_profit(*money_list)
The profit is 500

ដែល​ហៅ​ថា local scope គឺ​ជា​ទីន្លែង​នៅ​ក្នុង​ function ។ ដើម្បី​បង្កើត​វត្ថុ​ផ្សេង​ៗ​នៅ​ក្នុង local scope យើង​ត្រូវ​ធ្វើ​ដូច​ខាង​ក្រោម​នេះ៖

def get_profit(sale=0, buy=0):
    money_list = [2000, 1500]
    sale = money_list[0]
    buy = money_list[1]
    profit = sale - buy
    print('The profit is', profit)

get_profit()
The profit is 500

គ្រប់​វត្ថុ​នៅ​ក្នុង local scope ត្រូវ​បង្កើត​ឡើង​នៅ​ពេល function ត្រូវ​បាន​ call និង​ត្រូវ​លុប​ចោល​ទៅ​វិញ នៅ​ពេល​ដែល​ function ត្រូវ​បាន​ប្រើ​រួច​ហើយ​។ ជាក់ស្តែង នៅ​ក្នុង​កម្មវិធី​ខាង​លើ​នេះ variable ឈ្មោះ money_list ត្រូវ​បាន​បង្កើត​ឡើង​នៅ​ក្នុង local scope នៅ​ពេល​ដែល function ឈ្មោះ get_profit() ត្រូវ​បាន​ call តែ variable នេះ​ត្រូវ​បាន​លុប​ចោល​ទៅ​វិញ នៅ​ពេល​ដែល block នៃ statement នៅ​ក្នុង function នោះ​ត្រូវ​បាន​អនុវត្ត​ចប់​សព្វគ្រប់​។

មួយវិញទៀត នៅ​ពេល​ដែល​ function មួយ​ត្រូវ​បាន​បង្កើត​ឡើង​នៅ​ក្នុង function មួយ​ទៀត ទីកន្លែង​របស់ function នៅ​ខាង​ក្នុង​ត្រូវ​ហៅ​ថា nested scope និង​ទី​កន្លែង​របស់​ function នៅ​ខាង​ក្រៅ​ត្រូវ​ហៅ​ថា enclosing scope ។ ដើម្បី​បង្កើត​វត្ថុ​ផ្សេង​ៗ​នៅ​ក្នុង nested scope និង enclosing scope យើង​ត្រូវ​ធ្វើ​ដូច​ខាង​ក្រោម​នេះ៖

def enclose_func():
    money_list = [2000, 1500]
    print('The object created in enclosing scope is', money_list)

    def nested_func():
        money_dict = {'sale': 2000, 'buy': 1500}
        print('The object created in nested scope is', money_dict)

    nested_func()

enclose_func()
The object created in enclosing scope is [2000, 1500]
The object created in nested scope is {'sale': 2000, 'buy': 1500}

វត្ថុ​នៅ​ក្នុង​ nested scope និង​វត្ថុ​នៅ​ក្នុង​ enclosing scope ក៏​ដូច​ជា​វត្ថុ​នៅ​ក្នុង local scope ដែរ គឺ​វា​ត្រូវ​បាន​បង្កើត​ឡើង​នៅ​ពេល​ដែល function ត្រូវ​បាន​ call និង​ត្រូវ​លុប​ចោល​វិញ នៅ​ពេល​ដែល​ function ត្រូវ​បាន​ call រួច​ហើយ​។ ក៏ប៉ុន្តែ បើ​សិន​ជា​វត្ថុ​ទាំងនោះ​ត្រូវ​បាន​បញ្ជូន​ចេញ​ទៅ​កាន់​ global scope វត្ថុ​ទាំងនោះ​នឹង​មិន​ត្រូវ​បាន​លុប​ចោល​ឡើយ នៅ​ពេល​ដែល​ function ត្រូវ​បាន​ call រួច​ហើយ​នោះ​។ ពិនិត្យ​កម្មវិធី​ខាង​ក្រោម​នេះ៖

def get_profit():
    sale = 1000
    buy = 900
    profit = sale - buy
    return profit

money = get_profit()
print(money)
100

ដែល​ហៅ​ថា built-in scope គឹ​ជា​ទីកន្លែង​មួយ​នៅ​ក្នុង​សតិ​របស់​កំព្យូទ័រ ដែល​វត្ថុ​មួយ​ចំនួន​ត្រូវ​បាន​បង្កើត​ឡើង​រួច​ជា​ស្រេច​ទុក​នៅ​ក្នុង​នោះ​។ វត្ថុ​ទាំងនោះ​ត្រូវ​ហៅ​ថា built-in object ដែល​អាច​ត្រូវ​យក​ទៅ​ប្រើ​នៅ​ក្នុង scope ណា​ក៏​បាន​ដែរ​។


នៅ​ក្នុង​ភាសា Python នៅ​ពេល​ដែល​យើង​យក​វត្ថុ​ណា​មួយ​មក​ប្រើ ការស្វែង​រក​វត្ថុ​នោះ ត្រូវ​ធ្វើ​ឡើង​តាម​គំនូស​បំព្រួញ​ដូច​ខាង​ក្រោម​នេះ៖

បាន​ន័យ​ថា ការស្វែង​រក​វត្ថុ​ត្រូវ​ធ្វើ​ឡើង ដោយ​ចាប់​ផ្តើម​នៅ​ក្នុង​ scope ដែល​ទីនោះ​វត្ថុ​ត្រូវ​បាន​យក​ទៅ​ប្រើ រួច​បាន​បន្ត​ទៅ​ scope ផ្សេង​ៗ​ទៀត តាម​សញ្ញា​ព្រួញ​ដូច​នៅ​ក្នុង​រូប​ខាង​លើ​នេះ រហូត​ដល់​អស់ scope បើ​នៅ​តែ​រក​មិន​ឃើញ​។ ពិនិត្យ​កម្មវិធី​ខាង​ក្រោម​នេះ៖

global_str = 'global scope.'

def enclosing_func():
    enclosing_str = 'local scope or enclosing scope.'

    def nested_func():
        nested_str = 'nested scope.'
        print('global_str is found in', global_str)
        print('enclosing_str is found in', enclosing_str)
        print('nested_str is found in', nested_str)

    nested_func()

enclosing_func()
global_str is found in global scope.
enclosing_str is found in local scope or enclosing scope.
nested_str is found in nested scope.

ដោយ​ការស្វែង​រក​វត្ថុ​ផ្សេង​ៗ​ត្រូវ​ប្រព្រឹត្ត​ទៅ​ដូច​នៅ​ក្នុង​គំនូស​បំព្រួញ​ខាង​លើ ដូចនេះ​យើង​មិន​អាចយក​វត្ថុ​នៅ​ក្នុង​ scope ផ្នែក​ខាង​ក្រោម ទៅ​ប្រើ​នៅ​ក្នុង scope នៅ​ខាង​លើ​បាន​ឡើយ​។ ពិនិត្យ​កម្មវិធី​ខាង​ក្រោម​នេះ៖

global_str = 'global scope.'

def enclosing_func():
    enclosing_str = 'local scope or enclosing scope.'

    def nested_func():
        nested_str = 'nested scope.'

    nested_func()

enclosing_func()
print(enclosing_str)
Traceback (most recent call last):
  File "C:/pythonProject/main.py", line 12, in <module>
    print(enclosing_str)
NameError: name 'enclosing_str' is not defined

វត្ថុ​នៅ​ក្នុង​ scope ខុស​ៗ​គ្នា គឺ​ជា​វត្ថុ​ខុស​ៗ​គ្នា ទោះ​បី​ជា​វត្ថុ​ទាំងនោះ​មាន​ឈ្មោះ​ដូច​គ្នា​ក៏​ដោយ​។ ពិនិត្យ​កម្មវិធី​ខាង​ក្រោម​នេះ៖

object = 1000
print('In global scope, object is', object)

def enclosing_func():
    object = True
    print('In enclosing scope, object is', object)

    def nested_func():
        object = 'sentence'
        print('In nested scope, object is', object)

    nested_func()

enclosing_func()
In global scope, object is 1000
In enclosing scope, object is True
In nested scope, object is sentence

យើង​អាច​យក​វត្ថុ​នៅ​ក្នុង​ global scope មក​ប្រើ​ក្នុង local scope និង​ឬ nested scope បាន​មែន តែ​យើង​មិន​អាច​យក​ឈ្មោះ​របស់​វត្ថុ​ទាំងនោះ​ទៅ​ភ្ជាប់​នឹង​វត្ថុ​ណា​ផ្សេង​ទៀត​បាន​ឡើយ​។ ការប៉ុនប៉ង​យក​ឈ្មោះ​របស់​វត្ថុ​ទាំងនោះ​ទៅ​ភ្ជាប់​នឹង​វត្ថុ​ផ្សេង​ទៀត គឺ​ជា​ការបង្កើត​វត្ថុ​ថ្មី​មាន​ឈ្មោះ​ដូច​គ្នា នៅ​ក្នុង​បណ្តា scope ទាំងនោះ​។ ក៏ប៉ុន្តែ បើ​យើង​ពិត​ជា​ចង់​យក​ឈ្មោះ​របស់​វត្ថុ​នៅ​ក្នុង global scope ទៅ​ភ្ជាប់​នឹង​វត្ថុ​ផ្សេង​ទៀត នៅ​ក្នុង​ local scope និង​ឬ nested scope យើង​ត្រូវ​ប្រើប្រាស់ statement global ដោយ​ធ្វើ​ដូច​ខាង​ក្រោម​នេះ៖

object = 1000
object_list = [210, False, 'profit']

def enclosing_func():
    global object
    object = True

    def nested_func():
        global object_list
        object_list = 'Sentence'

    nested_func()

enclosing_func()
print('The new "object" is', object)
print('The new "object_list" is', object_list)
The new "object" is True
The new "object_list" is Sentence

ចំពោះ​វត្ថុ​ដែលមាន​លក្ខណៈ mutable និង​ដែល​ស្ថិត​នៅ​ក្នុង global scope យើង​អាច​យក​វា​មក​ដោះដូរ element នៅ​ក្នុង local scope និង​ឬ nested scope បាន​ជា​ធម្មតា ដោយ​មិន​ចាំបាច់​ប្រើប្រាស់ statement global ឡើយ​។ ដោយ​ហេតុថា ការដោះដូរ element នៅ​ក្នុង​វត្ថុ​ដែល​ជា container មិន​មែន​ជា​ការយក​ឈ្មោះ​របស់​វត្ថុ​ដែល​ជា container ទៅ​ភ្ជាប់​នឹង​វត្ថុ​ផ្សេងទៀត​ឡើយ​។ ពិនិត្យ​កម្មវិធី​ខាង​ក្រោម​នេះ៖

object_list = [210, False, 'profit']

def enclosing_func():
    object_list[0] = True

    def nested_func():
        object_list[1] = 'Sentence'

    nested_func()

enclosing_func()
print('The new "object_list" is', object_list)
The new "object_list" is [True, 'Sentence', 'profit']

យ៉ាងណាម៉ិញ យើង​អាច​យក​វត្ថុ​នៅ​ក្នុង local/enclosing scope មក​ប្រើ​នៅ​ក្នុង​ nested scope បាន​មែន តែ​យើង​មិន​អាច​យក​ឈ្មោះ​របស់​វត្ថុ​ទាំងនោះ​ទៅ​ភ្ជាប់​នឹង​វត្ថុ​ផ្សេង​ទៀត​បាន​ឡើយ​។ ការប៉ុនប៉ង​យក​ឈ្មោះ​របស់​វត្ថុ​ទាំងនោះ ទៅ​ភ្ជាប់​នឹង​វត្ថុ​ផ្សេង គឺ​ជា​ការបង្កើត​វត្ថុ​មាន​ឈ្មោះ​ដូច​គ្នា នៅ​ក្នុង scope ចុង​ក្រោយ​នេះ​។ ក៏ប៉ុន្តែ បើ​យើង​ពិត​ជា​ចង់​យក​ឈ្មោះ​របស់​វត្ថុ​នៅ​ក្នុង local/enclosing scope ទៅ​ភ្ជាប់​នឹង​វត្ថុ​នៅ​ក្នុង​ nested scope មែន យើង​ចាំបាច់​ត្រូវ​ប្រើប្រាស់ statement nonlocal ដោយ​ធ្វើ​ដូច​ខាងក្រោម​នេះ៖

def enclosing_func():
    object = 1000

    def nested_func():
        nonlocal object
        object = 'Sentence'

    nested_func()
    print('The new "object" is', object)

enclosing_func()
The new "object" is Sentence

យ៉ាងណាម៉ិញ ចំពោះ​វត្ថុ​ដែល​ស្ថិត​នៅ​ក្នុង local scope ដែល​ជា​ function ខុស​ៗ​គ្នា គឺ​ជា​វត្ថុ​ខុស​ៗ​គ្នា ទោះបី​ជា​វត្ថុ​ទាំងនោះ​មាន​ឈ្មោះ​ដូច​គ្នា​ក៏​ដោយ​។ ដោយហេតុថា function និមួយ​ៗ​គឺ​ជា​ scope ដោយ​ឡែក​ពី​គ្នា​។ ពិនិត្យ​កម្មវិធី​ខាង​ក្រោម​នេះ៖

def get_profit(sale, buy):
    profit = sale - buy
    return profit

def sum_profit(sale, buy):
    money = sale + buy + get_profit(sale=sale, buy=buy)
    print(money)

sum_profit(1000, 900)
2000

សរុប​មក ឈ្មោះ​របស់​វត្ថុ​នៅ​ក្នុង​ភាសា Python ក៏​ដូច​ជា​ឈ្មោះ​របស់​មនុស្ស​យើង​ដែរ​។ ពោល​គឺ​មនុស្ស​ឈ្មោះ វុធ នៅ​ក្នុង​គ្រួសារ​មួយ ខុស​ពី​មនុស្ស​ឈ្មោះ វុធ នៅ​ក្នុង​គ្រួសារ​មួយទៀត ទោះបី​ជា​មនុស្ស​ទាំង​ពីរ​នោះ​មាន​ឈ្មោះ​ដូច​គ្នា​ក៏ដោយ​៕