سؤال

هذا السؤال لديه بالفعل إجابة هنا:

عندما تقوم بتمرير مجموعة مثل القائمة، أو الصفيف إلى وظيفة أخرى في بيثون، هل تقوم بعمل نسخة منها، أم أنها مجرد مؤشر؟

هل كانت مفيدة؟

المحلول

بايثون يمرر المراجع إلى الكائنات حسب القيمة.

يمر بيثون بالمراجع إلى الكائنات حسب القيمة (مثل Java) ، وكل شيء في Python هو كائن.هذا يبدو بسيطًا ، ولكن بعد ذلك ستلاحظ أن بعض أنواع البيانات يبدو أنها تظهر خصائص مرور على أساس القيمة ، في حين يبدو أن الآخرين يتصرفون مثل مرجع مرجعية ...ما هي الصفقة؟

من المهم أن نفهم الأشياء القابلة للتغيير وغير القابلة للتغيير.بعض الكائنات ، مثل الأوتار ، والأحزاب ، والأرقام ، غير قابلة للتغيير.سيؤدي تغييرها داخل وظيفة/طريقة إلى إنشاء مثيل جديد ولا يتم تغيير المثيل الأصلي خارج الوظيفة/الطريقة.الكائنات الأخرى ، مثل القوائم والقواميس قابلة للتغيير ، مما يعني أنه يمكنك تغيير الكائن في مكانه.لذلك ، سيؤدي تغيير كائن داخل وظيفة/طريقة أيضًا إلى تغيير الكائن الأصلي في الخارج.

نصائح أخرى

الشيء هو أن مفهوم المرجع/القيمة بالكامل لن يتناسب مع بيثون.ليس لدى بايثون "قيمة" للمتغير.لدى بايثون فقط الكائنات والأسماء التي تشير إلى الكائنات.

لذا، عندما تستدعي دالة وتضع "اسمًا" داخل القوسين، هكذا:

def func(x): # defines a function that takes an argument
    ... # do something here

func(myname) # calling the function

الكائن الفعلي الذي myname يتم تمرير الإشارة، وليس اسم myname بحد ذاتها.داخل الدالة أسم آخر (x) للإشارة إلى نفس الكائن الذي تم تمريره.

يمكنك تعديل الكائن داخل الوظيفة إذا كان قابلاً للتغيير، لكن يمكنك تعديله لا يمكن تغيير ما يشير إليه الاسم الخارجي.بالضبط نفس ما يحدث عندما تفعل

anothername = myname

ولذلك أستطيع أن أجيب على سؤالك بما يلي:

إنه "تمرير حسب القيمة" ولكن كل القيم هي مجرد مراجع للكائنات.

كانت الإجابات هنا مفيدة، لكنني أجد ضرورة لإظهار هذا التمييز الدقيق الذي لم أره مغطى، والذي أثبتته لنفسي من خلال تجربة CL اللاحقة:

  1. لا يمكن تغيير كائن غير قابل للتغيير بمفرده خلال استدعاء دالة. (الإجابات حتى الآن قالت ذلك كثيرًا ...)
  2. ولكن، يمكن إعادة تعيين كائن غير قابل للتغيير موجود داخل كائن قابل للتغيير ضمن استدعاء الأسلوب.

لا يتغير "num" هنا لأنه كائن رقم غير قابل للتغيير [يدعم نقطتي 1.]:

def incr_num(num):
    num += 1

num = 0

num
0

incr_num(num)

num
0

"list[0]" هنا كائن رقم غير قابل للتغيير أيضًا.

def incr_list(list):
    list[0] += 1

list = [0]

list[0]
0

incr_list(list)

list[0]
1

إذًا كيف تغيرت "list[0]"، كونها كائن رقم غير قابل للتغيير، (تدعم النقطة 2.) بينما لم يتغير كائن الرقم "num" في المثال أعلاه؟ كائن الرقم غير القابل للتغيير 'list[0]' موجود داخل كائن القائمة القابل للتغيير 'list'، في حين أن 'num' من المثال الأول هو مجرد كائن رقم غير قابل للتغيير.

على الرغم من حسن النية، أشعر @ ستيفن باب الإجابات الأعلى تقييمًا (المقتبسة أدناه)، وبعض الإجابات المشابهة الأخرى، لم تكن صحيحة تمامًا (وهذا ما دفعني إلى كتابة هذه الإجابة):

بعض الكائنات، مثل السلاسل والصفوف والأرقام، غير قابلة للتغيير.سيؤدي تغييرها داخل وظيفة/طريقة إلى إنشاء مثيل جديد ولا يتم تغيير المثيل الأصلي خارج الوظيفة/الطريقة.

تُظهر تجربة الكود الثانية أعلاه كائنًا رقميًا ("قائمة [0]") يتم تغييره داخل إحدى الطرق، ثم تم تغيير المثيل الأصلي خارج الوظيفة.

يتم تمرير مرجع، ولكن إذا كانت المعلمة كائنًا غير قابل للتغيير، فسيؤدي تعديلها داخل الطريقة إلى إنشاء مثيل جديد.

تم تمرير الكائن.ليست نسخة، بل إشارة إلى الكائن الأساسي.

وأود أيضا أن أوصي بالنظر إلى copy وحدة:

وثائق بايثون للنسخ

سيساعدك ذلك على فهم المشكلات الأساسية وكيفية استخدامها لأداء نسختك العميقة.

بالتزكية:

>>> x = [0,1,2,3]
>>> def foo(x_list):
    x_list[0] = 1


>>> foo(x)
>>> x
[1, 1, 2, 3]

واسمحوا لي أن أعطي مثالا متواضعا

def swap(a, b):
    x = a
    print id(x)
    print id(a)
    print id(b)
    a = b

    print id(a)
    b = x
    print id(b)
    a[0]= '20'




var1 = ['1','2','3','4']
var2 = ['5','6','7','8','9']
print id(var1)
print id(var2)

swap(var1, var2)

print id(var1)
print id(var2)
print var1
print var2

مما ينتج النتيجة التالية

28329344 VAR1 28331264 VAR2 28329344 X 28329344 A 28331264 B بعد A = B 28331264 A بعد B = X 28329344 B بعد الإرجاع 28329344 VAR1 28331264 VAR2 [1 '،' 2 '،' '6' ، '7' ، '8' ، '9'

تعين على عناوين الذاكرة 28329344 28331264 var1 var2 ab x بعد a = b a بعد b = x b بعد a [0] = '20' [0] = '20' بعد العودة ['1' ، '2' ، '3' ، "4 '] [' 20 '،' 6 '،' 7 '،' 8 '،' 9 '

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top