الفرق بين المراجعتين ل"Python/tuples"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'{{DISPLAYTITLE:الصفوف Tuples في بايثون}} يتكوّن الصفّ من عدد من القيم المفصولة عن بعضها بفاصلة، مثل:<synta...')
 
ط
سطر 1: سطر 1:
{{DISPLAYTITLE:الصفوف Tuples في بايثون}}
+
<noinclude>{{DISPLAYTITLE:الصفوف Tuples في بايثون}}</noinclude>
 
 
 
يتكوّن الصفّ من عدد من القيم المفصولة عن بعضها بفاصلة، مثل:<syntaxhighlight lang="python3">
 
يتكوّن الصفّ من عدد من القيم المفصولة عن بعضها بفاصلة، مثل:<syntaxhighlight lang="python3">
 
>>>
 
>>>
 
 
>>> t = 12345, 54321, 'hello!'
 
>>> t = 12345, 54321, 'hello!'
 
 
>>> t[0]
 
>>> t[0]
 
 
12345
 
12345
 
 
>>> t
 
>>> t
 
 
(12345, 54321, 'hello!')
 
(12345, 54321, 'hello!')
 
 
>>> # يمكن للصفوف أن تكون متداخلة:‏
 
>>> # يمكن للصفوف أن تكون متداخلة:‏
 
 
... u = t, (1, 2, 3, 4, 5)
 
... u = t, (1, 2, 3, 4, 5)
 
 
>>> u
 
>>> u
 
 
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
 
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
 
 
>>> # الصفوف غير قابلة للتغيير
 
>>> # الصفوف غير قابلة للتغيير
 
 
... t[0] = 88888
 
... t[0] = 88888
 
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
 
  File "<stdin>", line 1, in <module>
 
  File "<stdin>", line 1, in <module>
 
 
TypeError: 'tuple' object does not support item assignment
 
TypeError: 'tuple' object does not support item assignment
 
 
>>> # ولكن يمكن أن تحتوي على كائنات قابلة للتغيير
 
>>> # ولكن يمكن أن تحتوي على كائنات قابلة للتغيير
 
 
... v = ([1, 2, 3], [3, 2, 1])
 
... v = ([1, 2, 3], [3, 2, 1])
 
 
>>> v
 
>>> v
 
 
([1, 2, 3], [3, 2, 1])
 
([1, 2, 3], [3, 2, 1])
 
 
</syntaxhighlight>إضافة إلى طرق التعريف السابقة، يمكن استخدام الدالة <code>tuple()‎</code> لإنشاء صف جديد:<syntaxhighlight lang="python3">
 
</syntaxhighlight>إضافة إلى طرق التعريف السابقة، يمكن استخدام الدالة <code>tuple()‎</code> لإنشاء صف جديد:<syntaxhighlight lang="python3">
 
>>>tuple('abc')
 
>>>tuple('abc')
 
 
('a', 'b', 'c')
 
('a', 'b', 'c')
 
 
>>>tuple([1,2,3])
 
>>>tuple([1,2,3])
 
 
(1, 2, 3)
 
(1, 2, 3)
 
</syntaxhighlight>
 
</syntaxhighlight>
سطر 64: سطر 41:
 
لإنشاء صف يحتوي على عنصر واحد فقط، يجب أن يكون العنصر الوحيد في الصف متبوعًا بفاصلة، ولا يكفي إحاطة القيمة بالأقواس فقط.<syntaxhighlight lang="python3">
 
لإنشاء صف يحتوي على عنصر واحد فقط، يجب أن يكون العنصر الوحيد في الصف متبوعًا بفاصلة، ولا يكفي إحاطة القيمة بالأقواس فقط.<syntaxhighlight lang="python3">
 
>>>
 
>>>
 
 
>>> empty = ()
 
>>> empty = ()
 
 
>>> singleton = 'hello',    # لاحظ الفاصلة في نهاية العبارة
 
>>> singleton = 'hello',    # لاحظ الفاصلة في نهاية العبارة
 
 
>>> len(empty)
 
>>> len(empty)
 
 
0
 
0
 
 
>>> len(singleton)
 
>>> len(singleton)
 
 
1
 
1
 
 
>>> singleton
 
>>> singleton
 
 
('hello',)
 
('hello',)
 
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 
 
العبارة <code>t = 12345, 54321, 'hello!'‎</code> هي مثال عن تحزيم الصف، إذ تحزّم القيم <code>12345</code>، و <code>54321</code> و <code>‎'hello!'</code>‎ جميعها في صفّ واحد.
 
العبارة <code>t = 12345, 54321, 'hello!'‎</code> هي مثال عن تحزيم الصف، إذ تحزّم القيم <code>12345</code>، و <code>54321</code> و <code>‎'hello!'</code>‎ جميعها في صفّ واحد.
  
 
يمكن أيضًا إجراء العملية العكسية:<syntaxhighlight lang="python3">
 
يمكن أيضًا إجراء العملية العكسية:<syntaxhighlight lang="python3">
 
>>>
 
>>>
 
 
>>> x, y, z = t
 
>>> x, y, z = t
 
 
 
</syntaxhighlight>تدعى هذه العملية بفك تحزيم التسلسل sequence unpacking ويمكن استخدام أي نوع من أنواع التسلسلات في الجانب الأيمن من عملية الإسناد. تتطلب عملية فك تحزيم التسلسل أن يكون عدد المتغيرات في الجانب الأيسر من عملية الإسناد مساويًا لعدد العناصر الموجودة في التسلسل.
 
</syntaxhighlight>تدعى هذه العملية بفك تحزيم التسلسل sequence unpacking ويمكن استخدام أي نوع من أنواع التسلسلات في الجانب الأيمن من عملية الإسناد. تتطلب عملية فك تحزيم التسلسل أن يكون عدد المتغيرات في الجانب الأيسر من عملية الإسناد مساويًا لعدد العناصر الموجودة في التسلسل.
  
سطر 120: سطر 83:
 
<syntaxhighlight lang="python3">
 
<syntaxhighlight lang="python3">
 
>>> Point = namedtuple('Point', ['x', 'y'])
 
>>> Point = namedtuple('Point', ['x', 'y'])
 
 
>>> p = Point(11, y=22)    # إنشاء نسخة باستخدام وسائط موقعية أو مفتاحية
 
>>> p = Point(11, y=22)    # إنشاء نسخة باستخدام وسائط موقعية أو مفتاحية
 
 
>>> p[0] + p[1]            # يمكن فهرستها مثل الصفوف العادية
 
>>> p[0] + p[1]            # يمكن فهرستها مثل الصفوف العادية
 
 
33
 
33
 
 
>>> x, y = p                # فك التحزيم مثل الصفوف العادية
 
>>> x, y = p                # فك التحزيم مثل الصفوف العادية
 
 
>>> x, y
 
>>> x, y
 
 
(11, 22)
 
(11, 22)
 
 
>>> p.x + p.y              # يمكن الوصول إلى الحقول عن طريق اسمائها
 
>>> p.x + p.y              # يمكن الوصول إلى الحقول عن طريق اسمائها
 
 
33
 
33
 
 
>>> p                      # تمثيل سهل القراءة
 
>>> p                      # تمثيل سهل القراءة
 
 
Point(x=11, y=22)
 
Point(x=11, y=22)
 
</syntaxhighlight>الصفوف المسمّاة مفيدة للغاية عند تعيين أسماء الحقول إلى صفوف معادة من وحدة [https://ar.wikipedia.org/wiki/%D8%A5%D8%B3_%D9%83%D9%8A%D9%88_%D9%84%D8%A7%D9%8A%D8%AA sqlite3] أو csv (القيم المفصولة بفاصلة):<syntaxhighlight lang="python3">
 
</syntaxhighlight>الصفوف المسمّاة مفيدة للغاية عند تعيين أسماء الحقول إلى صفوف معادة من وحدة [https://ar.wikipedia.org/wiki/%D8%A5%D8%B3_%D9%83%D9%8A%D9%88_%D9%84%D8%A7%D9%8A%D8%AA sqlite3] أو csv (القيم المفصولة بفاصلة):<syntaxhighlight lang="python3">
 
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
 
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
 
 
import csv
 
import csv
 
 
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
 
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
 
 
     print(emp.name, emp.title)
 
     print(emp.name, emp.title)
 
 
import sqlite3
 
import sqlite3
 
 
conn = sqlite3.connect('/companydata')
 
conn = sqlite3.connect('/companydata')
 
 
cursor = conn.cursor()
 
cursor = conn.cursor()
 
 
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
 
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
 
 
for emp in map(EmployeeRecord._make, cursor.fetchall()):
 
for emp in map(EmployeeRecord._make, cursor.fetchall()):
 
 
     print(emp.name, emp.title)
 
     print(emp.name, emp.title)
 
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== تغيير في الإصدار 3.1: ===
+
=== التغييرات في الإصدار 3.1 ===
 
* إضافة الوسيط rename.
 
* إضافة الوسيط rename.
  
=== تغيير في الإصدار 3.6: ===
+
=== التغييرات في الإصدار 3.6 ===
 
* أصبح الوسيطان verbose و rename وسيطين مفتاحيين فقط.
 
* أصبح الوسيطان verbose و rename وسيطين مفتاحيين فقط.
  

مراجعة 04:06، 24 فبراير 2018

يتكوّن الصفّ من عدد من القيم المفصولة عن بعضها بفاصلة، مثل:

>>>
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # يمكن للصفوف أن تكون متداخلة:‏
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # الصفوف غير قابلة للتغيير
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # ولكن يمكن أن تحتوي على كائنات قابلة للتغيير
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

إضافة إلى طرق التعريف السابقة، يمكن استخدام الدالة tuple()‎ لإنشاء صف جديد:

>>>tuple('abc')
('a', 'b', 'c')
>>>tuple([1,2,3])
(1, 2, 3)

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

لا يمكن إسناد قيم إلى عناصر الصف، ولكن يمكن إنشاء صفوف تتضمن كائنات قابلة للتغيير مثل القوائم.

قد تبدو الصفوف والقوائم متشابهة، ولكنّها غالبًا ما تستخدم في حالات مختلفة ولأغراض متباينة. 

الصفوف غير قابلة للتغيير، وتتضمّن عادة تسلسلًا غير متجانس من العناصر التي يمكن الوصول إليها من خلال فك التحزيم unpacking أو الفهرسة indexing أو حتى بواسطة الخاصية في حالة الصفوف المسمّاة named tuples (راجع الصفوف المسمّاة أدناه).

أما القوائم فقابلة للتغيير، وعادة ما تكون عناصرها متجانسة ويمكن الوصول إليها عن طريق المرور على القائمة.

يستخدم زوج من الأقواس الفارغة لإنشاء صفّ فارغ.

لإنشاء صف يحتوي على عنصر واحد فقط، يجب أن يكون العنصر الوحيد في الصف متبوعًا بفاصلة، ولا يكفي إحاطة القيمة بالأقواس فقط.

>>>
>>> empty = ()
>>> singleton = 'hello',    # لاحظ الفاصلة في نهاية العبارة
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

العبارة t = 12345, 54321, 'hello!'‎ هي مثال عن تحزيم الصف، إذ تحزّم القيم 12345، و 54321 و ‎'hello!'‎ جميعها في صفّ واحد.

يمكن أيضًا إجراء العملية العكسية:

>>>
>>> x, y, z = t

تدعى هذه العملية بفك تحزيم التسلسل sequence unpacking ويمكن استخدام أي نوع من أنواع التسلسلات في الجانب الأيمن من عملية الإسناد. تتطلب عملية فك تحزيم التسلسل أن يكون عدد المتغيرات في الجانب الأيسر من عملية الإسناد مساويًا لعدد العناصر الموجودة في التسلسل.

لاحظ أن عملية الإسناد المتعددة هي في الواقع دمج لعمليتي تحزيم الصف وفك تحزيم التسلسل.

الصفوف المسمّاة named tuples

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

تستخدم الدالة namedtuple()‎ لإنشاء الصفوف المسمّاة وصيغتها العامّة هي:

namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)

تعيد هذه الدالة صنفًا فرعيًا يحمل يحمل اسم typename. يُستخدم الصنف الفرعي الجديد في إنشاء كائنات شبيهة بالصفوف تمتلك حقولًا يمكن الوصول إليها عن طريق البحث في الخاصيات إضافة إلى إمكانية فهرسة هذه الحقول والمرور عليها. تمتلك نسخ الكائن الفرعي كذلك سلسلة توثيق نصية مفيدة (مع typename و field_names) وتابع ‎__repr__()‎ وظيفته سرد قائمة بمحتويات الصف على هيئة name=value.

field_names هي تسلسل من السلاسل النصية مثل ['x', 'y']، أو يمكن أن تكون سلسلة نصية مفردة تكون فيها أسماء الحقول مفصولة عن بعضها البعض بمسافة بيضاء و/أو فاصلة، مثل: 'x y' أو 'x, y'.

يمكن استخدام أي معرّف صالح في بايثون كاسمٍ للحقل باستثناء الأسماء التي تبدأ بالشرطة السفلية. تشمل المعرّفات الصالحة الحروف، والأرقام والشرطات السفلية، ولا تبدأ بالأرقام أو الشرطات السفلية ولا يمكن أن تكون إحدى الكلمات المفتاحية مثل class أو for أو return أو global أو pass أو raise.

إن أخذ الوسيط rename القيمة True فإنّ أسماء الحقول غير صالحة تبدّل بصورة تلقائية إلى أسماء موقعية. فمثلًا تحوّل ['abc', 'def', 'ghi', 'abc'] إلى ‎['abc', '_1', 'ghi', '_3']‎ حيث تحذف الكلمة المفتاحية def واسم الحقل المكرر abc.

إن أخذ الوسيط verbose القيمة True فإنّ تعريف الصنف يطبع بعد بنائه. هذا الوسيط مهمل الآن، ومن الأسهل طباعة الخاصية ‎_source بدلًا من ذلك.

إن تم تعريف الوسيط module فإنّ الخاصية ‎__module__‎ التابعة للصف المسمى تأخذ هذه القيمة.

لا تمتلك الصفوف المسمّاة قاموسًا لكل نسخة منها؛ ولهذا تستهلك الصفوف المسمّاة نفس مقدار الذاكرة الذي تستهلكه الصفوف العادية.

مثال

>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22)     # إنشاء نسخة باستخدام وسائط موقعية أو مفتاحية
>>> p[0] + p[1]             # يمكن فهرستها مثل الصفوف العادية
33
>>> x, y = p                # فك التحزيم مثل الصفوف العادية
>>> x, y
(11, 22)
>>> p.x + p.y               # يمكن الوصول إلى الحقول عن طريق اسمائها
33
>>> p                       # تمثيل سهل القراءة
Point(x=11, y=22)

الصفوف المسمّاة مفيدة للغاية عند تعيين أسماء الحقول إلى صفوف معادة من وحدة sqlite3 أو csv (القيم المفصولة بفاصلة):

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
    print(emp.name, emp.title)
import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
    print(emp.name, emp.title)

التغييرات في الإصدار 3.1

  • إضافة الوسيط rename.

التغييرات في الإصدار 3.6

  • أصبح الوسيطان verbose و rename وسيطين مفتاحيين فقط.
  • إضافة الوسيط module.

مصادر