Skip to content

4. سلاسل

Image

4.1. البرنامج النصي [str_01]: تدوين السلاسل

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

1
2
3
4
5
6
7
8
#  character strings
#  three possible notations
chaine1 = "un"
chaine2 = 'deux'
chaine3 = """hélène va au
marché acheter des légumes"""
#  display
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>، وهي فئة السلسلة:

#  string functions
#  lowercase string
print(f"'ABCD'.lower()={'ABCD'.lower()}")
#  string in uppercase
print(f"'abcd'.upper()={'abcd'.upper()}")
#  character n° 2
print(f"'cheval[2]={'cheval'[2]}")
#  substring with characters 5 and 6
print(f"'caractères accentués'[5:7]={'caractères accentués'[5:7]}")
#  substring from character 4 inclusive
print(f"'caractères accentués'[4:]={'caractères accentués'[4:]}")
#  substring up to but not including character 6
print(f"'caractères accentués'[:5]={'caractères accentués'[:5]}")
#  chain length
print(f"len('123')={len('123')}")
#  elimination of blanks preceding and following the chain
print(f"'  abcd '.strip()=[{'  abcd '.strip()}]")
#  elimination of whites following the chain
print(f"'  abcd '.rstrip()=[{'  abcd '.rstrip()}]")
#  elimination of blanks preceding the chain
print(f"'  abcd '.lstrip()=[{'  abcd '.lstrip()}]")
#  the term "white" in fact covers different characteristics
str = '  \r\nabcd \t\f'
print(f"str.strip()=[{str.strip()}]")
#  replacing one substring with another
print(f"'abcd'.replace('a','x')={'abcd'.replace('a', 'x')}")
print(f"'abcd'.replace('ab','xy')={'abcd'.replace('ab', 'xy')}")
#  search for substring: returns position or -1 if substring not found
print(f"'abcd'.find('bc')={'abcd'.find('bc')}")
print(f"'abcd'.find('bc')={'abcd'.find('Bc')}")
#  start of a chain
print(f"'abcd'.startswith('ab')={'abcd'.startswith('ab')}")
print(f"'abcd'.startswith('x')={'abcd'.startswith('x')}")
#  end of a chain
print(f"'abcd'.endswith('cd')={'abcd'.endswith('cd')}")
print(f"'abcd'.endswith('x')={'abcd'.endswith('x')}")
#  switch from a channel list to a channel
print(f"'[X]'.join(['abcd', '123', 'èéà'])={'[X]'.join(['abcd', '123', 'èéà'])}")
print(f"''.join(['abcd', '123', 'èéà'])={''.join(['abcd', '123', 'èéà'])}")
#  switch from a channel to a list of channels
print(f"'abcd 123 cdXY'.split('cd')={'abcd 123 cdXY'.split('cd')}")
#  retrieve words from a string
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
'caractères accentués'[5:7]=tè
'caractères accentués'[4:]=ctères accentués
'caractères accentués'[: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', 'èéà'])=abcd[X]123[X]èéà
''.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] مفاهيم متعلقة بترميز السلاسل:

#  character coding

#  str-type string
str = "hélène va au marché acheter des légumes"
print(f"str=[{str}, type={type(str)}]")
#  utf-8 encoding
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 encoding
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)}")
#  encoding 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> هي سلاسل أحرف Unicode |https://docs.python.org/3/howto/unicode.html|، |https://realpython.com/python-encodings-guide/
  • الأسطر 6-11: طريقتان لترميز سلسلة في UTF-8:
    • السطر 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 برسالة بريد إلكتروني، سيخضع لإحدى هاتين الطريقتين من الترميز اعتمادًا على عميل البريد الإلكتروني المستخدم. وينطبق هذا على معظم الملفات المرفقة.

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

#  encoding / decoding
import codecs

#  chain
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 encoding
print("---- chaîne unicode -> binaire utf-8")
bytes1 = bytes(str1, "utf-8")
print(f"bytes1=[{bytes1}], type(bytes1)={type(bytes1)}")

#  utf-8 decoding
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 encoding
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 decoding
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}")

#  decoding error - bytes1 is in utf-8 - decode it in 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)}")

#  utf-8 encoding of a Unicode string
print("---- chaîne unicode -> binaire utf-8")
bytes3 = codecs.encode(str1, "utf-8")
print(f"bytes3=[{bytes3}], type(bytes3)={type(bytes3)}")

#  encoding a UTF-8 binary string in base64
print("---- binaire utf-8 -> binaire base64")
bytes4 = codecs.encode(bytes1, "base64")
print(f"bytes4=[{bytes4}], type(bytes4)={type(bytes4)}")

#  return to original unicode string
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)}")

#  encoding a binary string in quoted-printable
print("---- binaire utf-8 -> binaire quoted-printable")
str7 = codecs.encode(bytes1, "quoted-printable")
print(f"str7=[{str7}], type(str7)={type(str7)}")

#  return to original unicode string
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' مرة أخرى إلى سلسلة Unicode الأصلية؛
  • الأسطر 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 إلى سلسلة Unicode باستخدام أداة فك التشفير الخاطئة 'iso-8859-1'. ونتيجة لذلك، تكون بعض أحرف Unicode التي تم إنشاؤها غير صحيحة، وفي هذه الحالة الأحرف التي تحتوي على علامات التشكيل؛
  • السطران 18-19: يتضمن ترميز «base64» استخدام 64 حرفًا من أحرف ASCII (المشفرة بـ 7 بتات) لترميز أي بيانات ثنائية. وكما نرى، يؤدي ذلك إلى زيادة حجم البيانات الثنائية للسلسلة؛
  • السطران 22-23: يستخدم ترميز "quoted-printable" أيضًا أحرف ASCII (مشفرة بـ 7 بتات) لترميز أي بيانات ثنائية؛

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