Skip to content

4. سلاسل الأحرف

Image

4.1. البرنامج النصي [str_01]: ترميز سلاسل الأحرف

النص البرمجي [str_01] هو كما يلي:


# سلاسل أحرف
# ثلاثة صيغ ممكنة
chaine1 = "un"
chaine2 = 'deux'
chaine3 = """hélène va au
 marché acheter des légumes"""
# العرض
print(f"chaine1=[{chaine1}], chaine2=[{chaine2}], chaine3=[{chaine3}]")

تعليقات

  • السطر 3: سلسلة محددة بعلامات اقتباس "؛
  • السطر 4: سلسلة محددة بعلامات الفاصلة العليا '؛
  • السطر 5: سلسلة محددة بعلامات اقتباس ثلاثية """. في هذه الحالة، يمكن أن تمتد السلسلة على عدة أسطر؛

النتائج هي كما يلي:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_01.py
chaine1=[un], chaine2=[deux], chaine3=[hélène va au
 marché acheter des légumes]

Process finished with exit code 0

4.2. البرنامج النصي [str_02]: أساليب فئة <str>

يعرض البرنامج النصي [str_02] بعضًا من طرق الفئة <str>، وهي الفئة الخاصة بسلاسل الأحرف:


# وظائف على سلاسل الأحرف
# سلسلة أحرف صغيرة
print(f"'ABCD'.lower()={'ABCD'.lower()}")
# سلسلة أحرف كبيرة
print(f"'abcd'.upper()={'abcd'.upper()}")
# الحرف رقم 2
print(f"'cheval[2]={'cheval'[2]}")
# سلسلة فرعية تحتوي على الحرفين 5 و6
print(f"'caractères accentués'[5:7]={'caractères accentués'[5:7]}")
# سلسلة فرعية بدءًا من الحرف 4 بما في ذلك
print(f"'caractères accentués'[4:]={'caractères accentués'[4:]}")
# سلسلة فرعية حتى الحرف 6 غير مشمول
print(f"'caractères accentués'[:5]={'caractères accentués'[:5]}")
# طول السلسلة
print(f"len('123')={len('123')}")
# إزالة المسافات التي تسبق السلسلة وتليها
print(f"'  abcd '.strip()=[{'  abcd '.strip()}]")
# إزالة المسافات التي تلي السلسلة
print(f"'  abcd '.rstrip()=[{'  abcd '.rstrip()}]")
# إزالة المسافات التي تسبق السلسلة
print(f"'  abcd '.lstrip()=[{'  abcd '.lstrip()}]")
# يشمل مصطلح «مسافة» في الواقع أحرفًا مختلفة
str = '  \r\nabcd \t\f'
print(f"str.strip()=[{str.strip()}]")
# استبدال سلسلة فرعية بأخرى
print(f"'abcd'.replace('a','x')={'abcd'.replace('a', 'x')}")
print(f"'abcd'.replace('ab','xy')={'abcd'.replace('ab', 'xy')}")
# البحث عن سلسلة فرعية: يُرجع الموضع أو -1 في حالة عدم العثور على السلسلة الفرعية
print(f"'abcd'.find('bc')={'abcd'.find('bc')}")
print(f"'abcd'.find('bc')={'abcd'.find('Bc')}")
# بداية سلسلة
print(f"'abcd'.startswith('ab')={'abcd'.startswith('ab')}")
print(f"'abcd'.startswith('x')={'abcd'.startswith('x')}")
# نهاية سلسلة
print(f"'abcd'.endswith('cd')={'abcd'.endswith('cd')}")
print(f"'abcd'.endswith('x')={'abcd'.endswith('x')}")
# التحويل من قائمة سلاسل إلى سلسلة
print(f"'[X]'.join(['abcd', '123', 'èéà'])={'[X]'.join(['abcd', '123', 'èéà'])}")
print(f"''.join(['abcd', '123', 'èéà'])={''.join(['abcd', '123', 'èéà'])}")
# الانتقال من سلسلة إلى قائمة سلاسل
print(f"'abcd 123 cdXY'.split('cd')={'abcd 123 cdXY'.split('cd')}")
# استخراج الكلمات من سلسلة
print(f"'abcd 123 cdXY'.split(None)={'abcd 123 cdXY'.split(None)}")

تكفي التعليقات المرتبطة بالنتائج التي تم الحصول عليها لفهم البرنامج النصي. والنتائج هي كما يلي:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_02.py
'ABCD'.lower()=abcd
'abcd'.upper()=ABCD
'cheval[2]=e
'أحرف مشطبة'[5:7]=tè
'أحرف مشطبة'[4:]=أحرف مشطبة
'أحرف معلمة'[:5]=carac
len('123')=3
'  abcd '.strip()=[abcd]
'  abcd '.rstrip()=[  abcd]
'  abcd '.lstrip()=[abcd ]
str.strip()=[abcd]
'abcd'.replace('a','x')=xbcd
'abcd'.replace('ab','xy')=xycd
'abcd'.find('bc')=1
'abcd'.find('bc')=-1
'abcd'.startswith('ab')=True
'abcd'.startswith('x')=False
'abcd'.endswith('cd')=True
'abcd'.endswith('x')=False
'[X]'.join(['abcd', '123', 'èéà'])=abcdQZXW2HTMLBW1hdZQX123QZXW2HTMLBW1hdZQXèéà
''.join(['abcd', '123', 'èéà'])=abcd123èéà
'abcd 123 cdXY'.split('cd')=['ab', ' 123 ', 'XY']
'abcd 123 cdXY'.split(None)=['abcd', '123', 'cdXY']

Process finished with exit code 0

4.3. البرنامج النصي [str_03]: ترميز سلاسل الأحرف (1)

يقدم البرنامج النصي [str_03] مفاهيم حول ترميز سلاسل الأحرف:


# ترميز الأحرف

# سلسلة من النوع str
str = "hélène va au marché acheter des légumes"
print(f"str=[{str}, type={type(str)}]")
# ترميز utf-8
print("--- utf-8")
bytes1 = str.encode('utf-8')
print(f"bytes1={bytes1}, type={type(bytes1)}")
bytes2 = bytes(str, 'utf-8')
print(f"bytes2={bytes2}, type={type(bytes2)}")
# ترميز iso-8859-1
print("--- iso-8859-1")
bytes1 = str.encode('iso-8859-1')
print(f"bytes1={bytes1}, type={type(bytes1)}")
bytes2 = bytes(str, 'iso-8859-1')
print(f"bytes2={bytes2}, type={type(bytes2)}")
# ترميز latin1=iso-8859-1
print("--- latin1")
bytes1 = str.encode('latin1')
print(f"bytes1={bytes1}, type={type(bytes1)}")
bytes2 = bytes(str, 'latin1')
print(f"bytes2={bytes2}, type={type(bytes2)}")

يؤدي ترميز سلسلة أحرف من النوع <str> إلى إنتاج سلسلة ثنائية يتم فيها تمثيل كل حرف في السلسلة ببايت واحد أو أكثر. توجد أنواع مختلفة من الترميز. يعرض البرنامج النصي أعلاه النوعين الأكثر شيوعًا في الغرب، وهما «utf-8» و«iso-8859-1» المعروف أيضًا باسم «latin1».

يتم توضيح مبدأ الترميز/فك الترميز أدناه (المرجع |https://realpython.com/python-encodings-guide/ |):

Image

تعليقات

  • السطران 4-5: سلسلة الأحرف الأولية التي سيتم ترميزها. المثيلات من النوع <str> هي سلاسل يونيكود |https://docs.python.org/3/howto/unicode.html|، |https://realpython.com/python-encodings-guide/
  • الأسطر 6-11: طريقتان لترميز سلسلة أحرف باستخدام UTF68:
    • السطر 8: str.encode('utf-8) ;
    • السطر 10: bytes(str, 'utf-8')؛
  • الأسطر 12-17: نكرر نفس العملية باستخدام الترميز 'iso-8859-1
  • الأسطر 18-23: 'latin1' هو اسم آخر لترميز 'iso-8859-1

النتائج هي كما يلي:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_03.py
str=[hélène va au marché acheter des légumes, type=<class 'str'>
--- utf-8
bytes1=b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes', type=<class 'bytes'>
bytes2=b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes', type=<class 'bytes'>
--- iso-8859-1
bytes1=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
bytes2=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
--- latin1
bytes1=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
bytes2=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>

Process finished with exit code 0

تعليقات

  • السطر 4: نلاحظ أن الأحرف المُشَدَّدة قد تم ترميزها باستخدام بايتين:
    • é: [\xc3\xa9] وهو التسلسل الثنائي 11000011 10101001؛
    • è: [\xc3\xa8] وهو التسلسل الثنائي 11000011 10101000؛
  • السطر 7: باستخدام ترميز iso-8859-1، يتم ترميز هذين الحرفين المُشَدَّدين بشكل مختلف:
    • é: [\xe9] وهو التسلسل الثنائي 11101001؛
    • è: [\xe8]، وهو التسلسل الثنائي 11101000؛

4.4. نص برمجي [str_04]: ترميز سلاسل الأحرف (2)

يقدم البرنامج النصي [str_04] نوعين آخرين من الترميز: «base64» و«quoted-printable». لا يقوم هذان النوعان بترميز سلاسل أحرف Unicode بل كائنات ثنائية. على سبيل المثال، عند إرفاق مستند Word برسالة بريد إلكتروني، سيخضع هذا المستند لأحد هذين النوعين من الترميز وفقًا لبرنامج البريد الإلكتروني المستخدم. وينطبق هذا على معظم الملفات المرفقة.

النص البرمجي هو كما يلي:


# التشفير/فك التشفير
import codecs

# سلسلة
print("---- chaîne unicode")
str1 = "hélène va au marché acheter des légumes"
print(f"str1=[{str1}], type(str1)={type(str1)}")

# ترميز utf-8
print("---- chaîne unicode -> binaire utf-8")
bytes1 = bytes(str1, "utf-8")
print(f"bytes1=[{bytes1}], type(bytes1)={type(bytes1)}")

# فك الترميز utf-8
print("---- binaire utf-8 -> chaîne unicode")
str2 = bytes1.decode("utf-8")
print(f"str2=[{str2}], type(str2)={type(str2)}")
print(f"str2==str1={str2 == str1}")

# ترميز iso-8859-1
print("---- chaîne unicode -> binaire iso-8859-1")
bytes2 = bytes(str1, "iso-8859-1")
print(f"bytes2=[{bytes2}], type(bytes2)={type(bytes2)}")

# فك الترميز iso-8859-1
print("---- binaire iso-8859-1 -> chaîne unicode")
str3 = bytes2.decode("iso-8859-1")
print(f"str3=[{str3}], type(str3)={type(str3)}")
print(f"str3==str1={str3 == str1}")

# خطأ في فك الترميز - bytes1 بتنسيق utf-8 - يتم فك ترميزه بتنسيق iso-8859-1
print("--- binaire utf-8 (décodage iso-8859-1) --> chaîne unicode")
str4 = bytes1.decode("iso-8859-1")
print(f"str4=[{str4}], type(str4)={type(str4)}")

# ترميز سلسلة Unicode بـ utf-8
print("---- chaîne unicode -> binaire utf-8")
bytes3 = codecs.encode(str1, "utf-8")
print(f"bytes3=[{bytes3}], type(bytes3)={type(bytes3)}")

# ترميز سلسلة ثنائية UTF-8 بتنسيق base64
print("---- binaire utf-8 -> binaire base64")
bytes4 = codecs.encode(bytes1, "base64")
print(f"bytes4=[{bytes4}], type(bytes4)={type(bytes4)}")

# العودة إلى سلسلة يونيكود الأصلية
print("---- binaire base64 -> binaire utf-8 -> chaîne unicode")
str6 = codecs.decode(bytes4, "base64").decode("utf-8")
print(f"str6=[{str6}], type(str6)={type(str6)}")

# ترميز سلسلة ثنائية بتنسيق quoted-printable
print("---- binaire utf-8 -> binaire quoted-printable")
str7 = codecs.encode(bytes1, "quoted-printable")
print(f"str7=[{str7}], type(str7)={type(str7)}")

# العودة إلى السلسلة الأصلية بتنسيق Unicode
print("---- binaire quoted-printable -> binaire utf-8 -> chaîne unicode")
str8 = codecs.decode(str7, "quoted-printable").decode("utf-8")
print(f"str8=[{str8}], type(str8)={type(str8)}")

تعليقات

  • السطر 2: تسمح الوحدة النمطية [codecs] بإجراء الترميزات «base64» و«quoted-printable». ويمكنها إجراء العديد من الترميزات الأخرى؛
  • الأسطر 4-7: سلسلة Unicode التي ستخضع لعمليات ترميز متنوعة؛
  • الأسطر 9-12: ترميز utf-8. نحصل على ملف ثنائي؛
  • الأسطر 14-18: فك الترميز utf-8 للعودة إلى سلسلة Unicode الأصلية؛
  • الأسطر 20-29: يتم تكرار نفس العملية باستخدام الترميز «iso-8859-1»؛
  • الأسطر 31-34: نوضح خطأً في فك الترميز:
  • السطر 33: bytes1 عبارة عن سلسلة ثنائية مشفرة بـ «utf-8». يتم فك تشفيرها إلى «iso-8859-1»؛
  • الأسطر 36-39: طريقة أخرى لترميز سلسلة أحرف بـ utf-8 باستخدام الوحدة النمطية [codecs]؛
  • الأسطر 41-44: يتم ترميز سلسلة ثنائية بتنسيق «utf-8» إلى «base64»؛
  • الأسطر 46-49: توضح كيفية الانتقال من السلسلة الثنائية «base64» إلى سلسلة يونيكود الأصلية؛
  • الأسطر 51-59: يتم تكرار هذه العملية باستخدام ترميز «quoted-printable» بدلاً من «base64»؛

والنتائج هي كما يلي:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_04.py
---- chaîne unicode
str1=[hélène va au marché acheter des légumes], type(str1)=<class 'str'>
---- chaîne unicode -> binaire utf-8
bytes1=[b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes'], type(bytes1)=<class 'bytes'>
---- binaire utf-8 -> chaîne unicode
str2=[hélène va au marché acheter des légumes], type(str2)=<class 'str'>
str2==str1=True
---- chaîne unicode -> binaire iso-8859-1
bytes2=[b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes'], type(bytes2)=<class 'bytes'>
---- binaire iso-8859-1 -> chaîne unicode
str3=[hélène va au marché acheter des légumes], type(str3)=<class 'str'>
str3==str1=True
--- binaire utf-8 (décodage iso-8859-1) --> chaîne unicode
str4=[hélène va au marché acheter des légumes], type(str4)=<class 'str'>
---- chaîne unicode -> binaire utf-8
bytes3=[b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes'], type(bytes3)=<class 'bytes'>
---- binaire utf-8 -> binaire base64
bytes4=[b'aMOpbMOobmUgdmEgYXUgbWFyY2jDqSBhY2hldGVyIGRlcyBsw6lndW1lcw==\n'], type(bytes4)=<class 'bytes'>
---- binaire base64 -> binaire utf-8 -> chaîne unicode
str6=[hélène va au marché acheter des légumes], type(str6)=<class 'str'>
---- binaire utf-8 -> binaire quoted-printable
str7=[b'h=C3=A9l=C3=A8ne=20va=20au=20march=C3=A9=20acheter=20des=20l=C3=A9gumes'], type(str7)=<class 'bytes'>
---- binaire quoted-printable -> binaire utf-8 -> chaîne unicode
str8=[hélène va au marché acheter des légumes], type(str8)=<class 'str'>

Process finished with exit code 0
  • السطور 14-15: يتم فك تشفير تسلسل ثنائي utf-8 إلى سلسلة يونيكود باستخدام أداة فك التشفير الخاطئة 'iso-8859-1'. ولذلك فإن بعض أحرف يونيكود الناتجة تكون غير صحيحة، وهي في هذه الحالة الأحرف المُشَدَّدة؛
  • السطران 18-19: يتكون الترميز «base64» من استخدام 64 حرفًا ASCII (مشفرة بـ 7 بتات) لترميز أي ملف ثنائي. وهذا يزيد، كما نرى، من حجم الملف الثنائي للسلسلة؛
  • السطران 22-23: يتكون الترميز «quoted-printable» أيضًا من استخدام أحرف ASCII (المشفرة بـ 7 بت) لترميز أي ملف ثنائي؛

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