سلاسل بايثون

تحتوي بايثون على فئة سلسلة مضمنة اسمها "str" مع العديد من الميزات المفيدة (هناك وحدة قديمة تسمى "string" يجب عدم استخدامها). يمكن وضع الأحرف الحرفية للسلسلة إما بين علامتي اقتباس مزدوجتين أو مفردة، على الرغم من استخدام علامات الاقتباس المفردة بشكل أكثر شيوعًا. تعمل علامات الشرطة المائلة للخلف بالطريقة المعتادة داخل كلّ من القيمتَين المفردة والمزدوجة بين علامات الاقتباس، على سبيل المثال \n \" \". ويمكن أن تحتوي السلسلة الحرفية ذات علامات الاقتباس المزدوجة على علامات اقتباس مفردة بدون أي تأخير (على سبيل المثال، "لم أفعل ذلك")، وبالمثل، يمكن أن تحتوي السلسلة ذات علامات الاقتباس المفردة على علامات اقتباس مزدوجة. يمكن أن تمتد السلسلة الحرفية إلى عدة أسطر، ولكن يجب أن تكون هناك شرطة مائلة للخلف \ في نهاية كل سطر لتجنب الخروج من السطر الجديد. يمكن أن تمتد القيم الحرفية للسلسلة داخل علامات الاقتباس الثلاثية، """ أو ''، إلى عدة أسطر من النص.

سلاسل بايثون "غير قابلة للتغيير"، مما يعني أنه لا يمكن تغييرها بعد إنشائها (تستخدم سلاسل Java هذا النمط غير القابل للتغيير). وبما أنّه لا يمكن تغيير السلاسل، ننشئ سلاسل *جديدة* أثناء تمثيل القيم المحسوبة. لذلك على سبيل المثال، يأخذ التعبير ('hello' + 'there') السلسلتين 'hello' و 'there'، وينشئ سلسلة جديدة 'hellothere'.

يمكن الوصول إلى الأحرف في سلسلة ما باستخدام بناء الجملة القياسي [ ]، ومثل Java وC++ ، تستخدم بايثون فهرسة قائمة على الصفر، لذلك إذا كانت s هي 'hello' s[1] هي 'e'. إذا كان الفهرس خارج حدود السلسلة، تقدم بايثون خطأ. أسلوب بايثون (على عكس Perl) هو التوقف إذا لم يتمكن من معرفة ما يجب فعله، بدلاً من مجرد تكوين قيمة افتراضية. يعمل بناء جملة "شريحة" المفيد (أدناه) أيضًا على استخراج أي سلسلة فرعية من سلسلة. تعرض الدالة len(string) طول السلسلة. يعمل بناء الجملة [ ] والدالة len() على أي نوع تسلسل - السلاسل والقوائم وما إلى ذلك. تحاول لغة بايثون جعل عملياتها تعمل بشكل متسق عبر أنواع مختلفة. مبتدئ في لغة بايثون: لا تستخدم "len" كاسم متغير لتجنب حظر الدالة len(). يمكن للعامل "+" إجراء تسلسل لسلسلتين. لاحظ في التعليمة البرمجية أدناه أن المتغيرات لم يتم الإعلان عنها مسبقًا -- فقط قم بتعيينها لها وانطلق.

  s = 'hi'
  print(s[1])          ## i
  print(len(s))        ## 2
  print(s + ' there')  ## hi there

على عكس Java، لا تؤدي علامة "+" إلى تحويل الأرقام أو الأنواع الأخرى تلقائيًا إلى شكل سلسلة. تقوم الدالة str() بتحويل القيم إلى شكل سلسلة بحيث يمكن دمجها مع سلاسل أخرى.

  pi = 3.14
  ##text = 'The value of pi is ' + pi      ## NO, does not work
  text = 'The value of pi is '  + str(pi)  ## yes

بالنسبة للأرقام، تعمل العوامل القياسية، +، /، * بالطريقة المعتادة. لا يوجد عامل تشغيل ++، ولكن +=، -=، وما إلى ذلك. إذا كنت تريد قسمة عدد صحيح، استخدم شرطتين مائلة -- مثال: 6 // 5 هو 1

تطبع دالة "print" عادةً عنصر بايثون واحد أو أكثر متبوعًا بسطر جديد. تكون السلسلة الحرفية "raw" مسبوقة بحرف "r" وتمرر كل الأحرف بدون معالجة خاصة للشرطات المائلة للخلف، لذلك يتم تقييم r'x\nx' إلى السلسلة-4- 'x\nx'. قد تستغرق السمة "print" العديد من الوسيطات لتغيير الطريقة التي تطبع بها الأشياء (راجع تعريف دالة الطباعة في python.org) مثل تعيين "end" على "" لعدم طباعة سطر جديد بعد انتهاء طباعة جميع العناصر.

  raw = r'this\t\n and that'

  # this\t\n and that
  print(raw)

  multi = """It was the best of times.
  It was the worst of times."""

  # It was the best of times.
  #   It was the worst of times.
  print(multi)

طرق السلسلة

إليك بعض طرق السلسلة الأكثر شيوعًا. تشبه الطريقة الدالة، ولكنها تُشغل "on" الكائن. إذا كان المتغير s عبارة عن سلسلة، فإن التعليمة البرمجية s.lower() تشغّل طريقة أقل() على كائن السلسلة هذا وتعرض النتيجة (هذه الفكرة عن الطريقة التي يتم تشغيلها على كائن هي إحدى الأفكار الأساسية التي تشكل البرمجة الموجّهة للكائنات (OOP). إليك بعض طُرق السلسلة الأكثر شيوعًا:

  • s.lower(), s.upper() -- لعرض إصدار الأحرف الصغيرة أو الكبيرة من السلسلة
  • s.strip() -- يتم إرجاع سلسلة مع إزالة المسافة البيضاء من البداية والنهاية.
  • s.isalpha()/s.isdigital()/s.isspace()... -- لاختبار ما إذا كانت جميع أحرف السلسلة موجودة في فئات الأحرف المختلفة
  • s.startswith('other'), s.endswith('other') -- لاختبار ما إذا كانت السلسلة تبدأ أو تنتهي بالسلسلة الأخرى المعيّنة
  • s.find('other') -- للبحث عن سلسلة معيّنة أخرى (ليس تعبيرًا عاديًا) داخل s، ويعرض الفهرس الأول حيث يبدأ أو -1 إذا لم يتم العثور عليه
  • s.replace('old', 'new') -- تعرض سلسلة يتم فيها استبدال جميع مواضع ورود 'old' بـ 'new'
  • s.split('delim') -- يعرض قائمة من السلاسل الفرعية يفصل بينها المُحدِّد المحدد. المحدد ليس تعبيرًا عاديًا، إنه نص فقط. 'aaa,bbb,ccc'.split(',') -> ['aaa', 'bbb', 'ccc']. عند استخدام حالة خاصة ملائمة، يتم تقسيم s.split() (بدون وسيطات) على جميع أحرف المسافات البيضاء.
  • s.join(list) -- مقابل split()، يربط العناصر في القائمة المحددة معًا باستخدام السلسلة كمُحدِّد. على سبيل المثال، '---'.join(['aaa', 'bbb', 'ccc']) -> aaa---bbb---ccc

سينقلك البحث على Google عن "python str" إلى طرق سلسلة python.org الرسمية التي تسرد جميع طرق str.

ليس لدى بايثون نوع حرف منفصل. بدلاً من ذلك، يُرجع تعبير مثل s[8] سلسلة-length-1 تحتوي على الحرف. باستخدام سلسلة-length-1 تلك، تعمل العوامل ==, <=, ... كلها كما هو متوقع، لذلك لا تحتاج في الغالب إلى معرفة أن بايثون ليس لديها نوع "char" قياسي منفصل.

شرائح السلاسل

بناء جملة "شريحة" هو طريقة سهلة للإشارة إلى الأجزاء الفرعية من التسلسلات - عادةً السلاسل والقوائم. الشريحة s[start:end] هي العناصر التي تبدأ في البداية وتمتد حتى النهاية ولكن لا تشملها. لنفترض أن لدينا s = "مرحبًا"

السلسلة &quot;hello&quot; مع فهارس الأحرف 0 1 2 3 4

  • s[1:4] هو 'ell' -- أحرف تبدأ من الفهرس 1 ويمتد حتى الفهرس 4 ولكن لا يشملها
  • s[1:] هو 'ello' -- حذف أي من القيم التلقائية للفهرس إلى بداية السلسلة أو نهايتها
  • s[:] هي "مرحبًا" -- يؤدي حذف كليهما دائمًا إلى تقديم نسخة من كل شيء (هذه هي الطريقة باستخدام لغة بايثونية لنسخ تسلسل مثل سلسلة أو قائمة)
  • s[1:100] هو 'ello' -- يتم اقتطاع الفهرس الكبير جدًا إلى طول السلسلة

تتيح أرقام الفهرس القياسية المستندة إلى الصفر وصولاً سهلاً إلى الأحرف بالقرب من بداية السلسلة. كبديل، تستخدم بايثون أرقامًا سالبة لتسهيل الوصول إلى الأحرف الموجودة في نهاية السلسلة: s[-1] هو آخر حرف 'o'، وs[-2] هو 'l' الحرف التالي إلى الأخير، وهكذا. يتم احتساب أرقام الفهرس السالبة من نهاية السلسلة:

  • s[-1] هو 'o' -- الحرف الأخير (الأول من النهاية)
  • s[-4] هو "e" -- الرابع من النهاية
  • s[:-3] هي "H" -- يرتفع حتى آخر 3 أحرف ولكن لا يشملها.
  • s[-3:] هو "llo" -- بدءًا من الحرف الثالث من النهاية وتمتد حتى نهاية السلسلة.

وهي فكرة واضحة عن الشرائح التي يمكن استخدامها لأي فهرس n، أي s[:n] + s[n:] == s. وينجح هذا حتى مع عدد n من الأرقام السالبة أو خارج الحدود. أو ضع طريقة أخرى: s[:n] وs[n:] دائمًا تقسِّم السلسلة إلى جزأين من السلسلة، مع الاحتفاظ بجميع الأحرف. وكما سنرى في قسم القائمة لاحقًا، تعمل الشرائح مع القوائم أيضًا.

تنسيق السلسلة

أحد الأشياء الأنيقة التي يمكن أن تفعلها بايثون هو تحويل الكائنات تلقائيًا إلى سلسلة مناسبة للطباعة. والطريقتان المدمجتان للقيام بذلك هما الحرفان المكتوبان على سلسلة منسقة، تسمى أيضًا "f-strings"، واستدعاء str.format().

القيم الحرفية للسلسلة المنسّقة

سترى غالبًا القيم الحرفية للسلسلة المنسّقة مستخدَمة في مواقف مثل:

  value = 2.791514
  print(f'approximate value = {value:.2f}')  # approximate value = 2.79

  car = {'tires':4, 'doors':2}
  print(f'car = {car}') # car = {'tires': 4, 'doors': 2}

تبدأ السلسلة الحرفية المنسّقة بالحرف "f" (مثل البادئة "r" المستخدَمة للسلاسل الأولية). تتم طباعة أي نص خارج الأقواس المعقوفة '{}' مباشرة. تتم طباعة التعبيرات الموجودة في '{}' باستخدام مواصفات التنسيق الموضحة في مواصفات التنسيق. هناك الكثير من الأشياء المفيدة التي يمكنك فعلها باستخدام التنسيق بما في ذلك الاقتطاع والتحويل إلى الترميز العلمي والمحاذاة لليسار/اليمين/المنتصف.

تُعد سلاسل f مفيدة جدًا عندما ترغب في طباعة جدول كائنات وترغب في محاذاة الأعمدة التي تمثل سمات كائنات مختلفة

  address_book = [{'name':'N.X.', 'addr':'15 Jones St', 'bonus': 70},
      {'name':'J.P.', 'addr':'1005 5th St', 'bonus': 400},
      {'name':'A.A.', 'addr':'200001 Bdwy', 'bonus': 5},]

  for person in address_book:
    print(f'{person["name"]:8} || {person["addr"]:20} || {person["bonus"]:>5}')

  # N.X.     || 15 Jones St          ||    70
  # J.P.     || 1005 5th St          ||   400
  # A.A.     || 200001 Bdwy          ||     5

النسبة المئوية للسلسلة

تمتلك بايثون أيضًا أداة قديمة تشبه printf() لتجميع سلسلة. يستخدم عامل التشغيل % سلسلة تنسيق من نوع printf-type على اليسار (%d int، سلسلة %s، نقطة عائمة %f/%g)، والقيم المطابقة في صف على اليمين (يتكون الصف من قيم مفصولة بفواصل، عادة ما يتم تجميعها داخل أقواس):

  # % operator
  text = "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down." % (3, 'huff', 'puff', 'house')

السطر أعلاه طويل بعض الشيء -- لنفترض أنك تريد تقسيمه إلى أسطر منفصلة. ولا يمكنك تقسيم السطر بعد "%" كما هو الحال في اللغات الأخرى، حيث تتعامل بايثون بشكل افتراضي مع كل سطر كعبارة منفصلة (على جانب علامة الجمع، ولهذا السبب لا نحتاج إلى كتابة الفواصل المنقوطة على كل سطر). لحل هذه المشكلة، ضمِّن التعبير بالكامل في مجموعة خارجية من الأقواس، وبعد ذلك يُسمح للتعبير بأن يمتد إلى عدة أسطر. يعمل أسلوب عبر الأسطر المتقاطعة هذا مع تركيبات التجميع المختلفة والمفصلة أدناه: ( )، [ ]، { }.

  # Add parentheses to make the long line work:
  text = (
    "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

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

  # Split the line into chunks, which are concatenated automatically by Python
  text = (
    "%d little pigs come out, "
    "or I'll %s, and I'll %s, "
    "and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

السلاسل (يونيكود مقابل بايت)

سلاسل بايثون العادية هي بترميز يونيكود.

تدعم بايثون أيضًا السلاسل المكونة من بايت عادي (يُشار إليها بالبادئة "b" أمام السلسلة الحرفية) مثل:

> byte_string = b'A byte string'
> byte_string
  b'A byte string'

سلسلة يونيكود هي نوع مختلف من الكائنات عن سلسلة بايت، لكن المكتبات المختلفة مثل التعبيرات العادية تعمل بشكل صحيح إذا تم تمرير أي من نوعي السلسلة.

لتحويل سلسلة بايثون عادية إلى بايت، استدعِ أسلوب encode() على السلسلة. في الاتجاه الآخر، تحوّل طريقة فك ترميز سلسلة البايت() البايت العادي وحدات البايت العادية المشفرة إلى سلسلة يونيكود:

> ustring = 'A unicode \u018e string \xf1'
> b = ustring.encode('utf-8')
> b
b'A unicode \xc6\x8e string \xc3\xb1'  ## bytes of utf-8 encoding. Note the b-prefix.
> t = b.decode('utf-8')                ## Convert bytes back to a unicode string
> t == ustring                         ## It's the same as the original, yay!

True

في قسم قراءة الملف، يوجد مثال يوضح كيفية فتح ملف نصي باستخدام بعض الترميز وقراءة سلاسل يونيكود.

عبارة If

لا تستخدم بايثون { } لتضمين كتل من التعليمات البرمجية لـ if/loops/function وما إلى ذلك. بدلاً من ذلك، تستخدم بايثون النقطتين (:) والمسافة البادئة/المسافة البيضاء لتجميع العبارات. لا يُشترط أن يكون الاختبار المنطقي لـ if بين قوسين (فرق كبير عن C++/Java)، ويمكن أن يحتوي على عبارتي *elif* و *else* (لتذكير: كلمة "elif" لها نفس طول كلمة "else").

يمكن استخدام أي قيمة كاختبار if. يتم احتساب جميع القيم "صفر" على أنها خطأ: لا شيء، 0، سلسلة فارغة، قائمة فارغة، قاموس فارغ. يوجد أيضًا نوع منطقي بقيمتين: True وFalse (تم تحويله إلى عدد صحيح، وهما 1 و0). تتضمن لغة بايثون عمليات المقارنة المعتادة: == و!= و< و<= و> و>=. على عكس Java وC، يتم تحميل == بشكل زائد للعمل بشكل صحيح مع السلاسل. عوامل التشغيل المنطقية هي الكلمات المكتوبة *و*، *أو*، *not* (لا تستخدم Python عامل التشغيل C-style && || !). إليك الشكل الذي قد يبدو عليه الرمز لتطبيق الصحة الذي يقدم اقتراحات للمشروبات على مدار اليوم - لاحظ كيف تبدأ كل كتلة من عبارات ثم/else بـ : ويتم تجميع العبارات حسب المسافة البادئة لها:

  if time_hour >= 0 and time_hour <= 24:
    print('Suggesting a drink option...')
    if mood == 'sleepy' and time_hour < 10:
      print('coffee')
    elif mood == 'thirsty' or time_hour < 2:
      print('lemonade')
    else:
      print('water')

أجد أن حذف ":" هو الخطأ الأكثر شيوعًا في بناء الجملة عند كتابة نوع التعليمة البرمجية أعلاه، ربما نظرًا لأن هذا شيء إضافي ينبغي كتابته مقابل عادات C++/Java الخاصة بي. أيضًا، لا تضع الاختبار المنطقي بين قوسين -- فهذه عادة C/Java. إذا كانت التعليمة البرمجية قصيرة، فيمكنك وضع التعليمة البرمجية في نفس السطر بعد ":"، على هذا النحو (ينطبق هذا على الدوال والتكرارات الحلقية وغيرها أيضًا)، على الرغم من أن بعض الأشخاص يشعرون أنه من الأسهل قراءة الأشياء على أسطر منفصلة.

  if time_hour < 10: print('coffee')
  else: print('water')

تمرين: string1.py

للتدرب على المواد الموجودة في هذا القسم، جرِّب تمرين string1.py في التمارين الأساسية.