تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
مدخل الى الصفوف tuple في بيثون
#1
مدخل الى الصفوف tuple في بيثون
سنتحدث قليلا عن نوع آخر من المتتاليات يسمى الصفوف tuple

الصفوف قريبة جدا من القوائم list، حيث أنهما من المتتاليات sequences وبالتالي يمكننا تنفيذ عمليات مثل اختبار الانتماء الى الصفوف بواسطة in او الوصول الى مختلف عناصرها بواسطة المؤشرات بين قوسين مربعين [] أو القيام  بتقطيعها الى شرائح [a:b] هذا الى جانب كون الصفوف تجمع عناصر يمكن أن تكون من مختلف الانواع. الفرق الأساسي بين القوائم والصفوف هو أن الصفوف كائنات غير قابلة للتغيير بدون نسخ (immutable مثل السلاسل النصية) على عكس القوائم، هذا يعني أن الصف بعد انشائه لا يمكن تعديله (...). لنفتح مفسر بيثون حتى نرى الصفوف عمليا:

انشاء صف يتم ببساطة من خلال:

كود :
t = ()
type(t)
هنا أنشانا صفا فارغا، وباعتبار أن الصف غير قابل للتعديل بعد انشائه، لا يمكننا اضافة شيء الى هذا الصف الفارغ (لا يوجد append او extend أو insert) أما عملية الجمع فهي تنشء كائنا جديدا، وهكذا:

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

كود :
t = (4,)            # t references a new tuple
type(t)
t = (4)             # t references an int
type(t)
t = 12.5,           # new tuple
type(t)
لاحظ أننا كلما أشرنا الى كائن جديد بواسطة المتغير t نفقد السابق (تذكير: المتغير في بيثون هو مؤشر الى كائن وهذا الكائن يجب أن يكون له مؤشر لكي لا يقوم بيثون بتنظيفه من الذاكرة)

- انشاء صف يتكون من عدة عناصر: لاحظ هنا ايضا أن القوسين اختياريان لكن نضيفهما لمزيد الوضوح:

كود :
t = (True, 3.4, 18)
t                   # (True, 3.4, 18)
t = True, 3.4, 18
t                   # (True, 3.4, 18)
t = 4,
t                   # (4,)
قد يصبح القوسان ضروريين كما في المثال التالي (list comprehensions):

كود :
[(x, x**2) for x in range(6)]   # هذا صحيح
[x, x**2 for x in range(6)]     # invalid syntax
قلنا أعلاه أنه لا يمكننا تعديل صف بعد انشائه: هذا صحيح بالنسبة للصف ككل، لكن يمكن تعديل بعض عناصره اذا كانت تقبل التعديل (القوائم والقواميس خاصة):

كود :
v = [1, 2, 3]
t = (v,[4, 5])
print(t)            # ([1, 2, 3], [4, 5])
v.append('text')
print(v)            # [1, 2, 3, 'text']
print(t)            # ([1, 2, 3, 'text'], [4, 5])
t[1].append('new')
print(t)            # ([1, 2, 3, 'text'], [4, 5, 'new'])
t[0].pop(0)         # 1
print(t)            # ([2, 3, 'text'], [4, 5, 'new'])
print(v)            # [2, 3, 'text']
t[0] = [6, 7, 8]    # Error !! 'tuple' object does not support item assignment
بما أن الصفوف هي عبارة عن كائنات من صنف المتتاليات، يمكن تنفيذ العمليات الخاصة بالمتتاليات عليه:

كود :
t = True, 3.4, 18
3.4 in t            # True
for x in t:         # looping
   print(x)
t[2]                # 18
t[:2]               # (True, 3.4)
a = list(t)         # تحويل صف الى قائمة
a                   # [True, 3.4, 18]
a[0] = False        # هذا ممكن بالنسبة للقوائم لكن غير ممكن في الصفوف
a                   # [False, 3.4, 18]
t = tuple(a)        # تحويل قائمة الى صف جديد
t                   # (False, 3.4, 18)
تستخدم الصفوف بكثرة فيما يسمى tuple packing and unpacking

كود :
(a, b) = [3, 4]     # same as a, b = 3, 4
a                   # 3
b                   # 4
t = 1, 2, 3         # same as t = (1, 2, 3)
x, y, z = t         # x=1; y=2; z=3
a, b, c = 1, 2, 3   # same as a=1; b=2; c=3
x, y = 5, 7         # same as x=5; y=7
y, x = x, y         # swap: x=7 and y=5
a = tuple(range(10))# a = (0,1,2,3,4,5,6,7,8,9)
x, *y = a           # extended tuple unpacking
x                   # 0
y                   # [1,2,3,4,5,6,7,8,9]
*x, y = a           # extended tuple unpacking
x                   # [0,1,2,3,4,5,6,7,8]
y                   # 9
d = [1, 2, 3, 4, 5] # list or tuple
a, *b, c = d        # extended tuple unpacking
print("a={} b={} c={}".format(a, b, c)) # a=1 b=[2, 3, 4] c=5
تستخدم الصفوف ايضا كمفتاح في قاموس، سنعود لهذا ان شاء الله عند الحديث عن القواميس

بالعودة مرة للمقارنة مع القوائم، فالقائمة قابلة للتعديل بالاضافة (append - extend - insert) والحذف (del - remove - pop - clear) واعادة الترتيب (sort - reverse) لكن هذا غير ممكن بالنسبة للصفوف. لكن يمكن البحث عن عنصر او عدد العناصر باستخدام index - count - len - in - not in..

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



من فوائد الصفوف ايضا، استخدامها كمخرجات دالة.  على سبيل المثال سنفترض أننا نرغب في بناء دالة تعيد الينا مكان مؤشر الفارة. هذا يتطلب الحصول على قيمتين (x, y) :

كود :
def getMousePos():
   # processing ............
   return x, y     # (x, y)
#w عندما نرغب في استدعاء الدالة نستطيع أن نفعل كما يلي:
u, v = getMousePos()
عملية الجمع تنتج صفا جديدا:

كود :
t1 = (1, 2,)        # الفاصلة الاخير اختيارية كما القوسين
t2 = 3, 4,
t3 = t1 + t2        # t3 = (1, 2, 3, 4)
print(t3)
t1 = t1 + t2        # t1 = (1, 2, 3, 4)
print(t1)
t1 == t3            # True
t1 is t3            # False !
مثال عملي من استخدام extended unpacking

لدينا دالة data نعرف أنها تحتوي على بيانات شخصية غير معلومة العدد لكنها تبدأ بالاسم واللقب وهو ما نريد استخراجه:

كود :
data = [ 'Fulan', 'Fulani', '061234567', '12', 'green path street', '57000', 'METZ', ]
#u نستطيع استخدام اسم متغير _ للاشارة أننا لا نهتم بباقي البيانات
fname, lname, *_ = data
print("First name={} Last name={}".format(fname, lname))
مزيد التعمق

متغيرات عديدة في حلقة تكرار:

كود :
entries = [(1, 2), (3, 4), (5, 6)]
for a, b in entries:
   print("a={} b={}".format(a, b))
الدالة zip

سننطلق من افتراض أن لدينا قائمتين متساويتين في عدد العناصر: قائمة مدن وقائمة عدد سكان بحيث كل عنصر في القائمة الاولى يتوافق مع العنصر المقابل له في القائمة الثانية هكذا:

كود :
towns = ['Tunis', 'Alger', 'Caire']
populations = [2*10**6, 3*10**6, 9*10**6]
myList = list(zip(towns, populations))
print(myList)

for town, population in zip(towns, populations):
   print(population, "inhabitants of the city", town)
تنبيه: عندما نمرر للدالة zip قوائم باطوال مختلفة، ستكون النتيجة مبتورة وستعتمد الدالة أقصر طول لانهاء التكرار:

كود :
for units, *tens in zip([1, 2], [10, (20, 30,), 400]):
   print(units, tens)
الدالة enumerate

دالة مفيدة تمكننا من استخدام حلقة تكرار على قائمة بواسطة مؤشر القائمة:



كود :
for i, town in enumerate(towns):
   print(i, town)
استخدام الدالة enumerate يعطي كود ابسط واكثر مقروئية من استخدام المؤشرات او الدالة zip رغم اننا في النهاية نحصل على نفس النتيجة:

كود :
for in in range(len(towns)):
   print(i, towns[i])
   
for i, town in zip(range(len(towns)), towns):
   print(i, town)
الرد


التنقل السريع :


مستخدمين يتصفحوا هذا الموضوع: 1 ضيف