۲۲ ترفند پایتون برای کار با رشته ها — راهنمای کاربردی
دستکاری رشتهها کاری است که برنامهنویسان پایتون به وفور انجام میدهند. در این نوشته با 22 ترفند پایتون برای کار با رشته ها آشنا خواهیم شد. در همه این مثالها از پایتون نسخه 3 استفاده شده است. در زمان نگارش این نوشته جدیدترین نسخه پایتون، نسخه 3.8.2 بوده است.
یافتن یک عبارت درون یک رشته
با استفاده از مقایسهگر داخلی پایتون به نام in میتوانیم بفهمیم که آیا یک عبارت درون یک رشته وجود دارد یا نه.
این عملگر مقدار true یا false بازگشت میدهد.
1def sub_00(haystack: str="", needle:str="") -> bool:
2 return needle in haystack
3
4assert sub_00("the quick brown fox jumped over the lazy dog", "lazy") == True
5assert sub_00("the quick brown fox jumped over the lazy dog", "lazys") == False
معکوس ساختن یک رشته
با تعیین یک گام کاهشی برای عملگر slice میتوانیم یک رشته را معکوس کنیم.
1def string_reverse(forward: str = "") -> str:
2 return forward[::-1]
3
4assert string_reverse("hello") == "olleh"
5assert string_reverse("goodbye") != "goodbye"
بررسی برابر بودن دو رشته
بررسی برابر بودن با استفاده از عملگر == موجب میشود که متوجه شویم دو شیء مقدار یکسانی دارند یا نه. برای مقایسه هویت از عملگر is استفاده میکنیم تا متوجه شویم آیا دو شیء یکی و یکسان هستند یا نه.
1def are_equal(first_comparator: str = "", second_comparator: str = "") -> bool:
2 return first_comparator == second_comparator
3
4
5assert are_equal("thing one", "thing two") is False
6assert are_equal("a thing", "a " + "thing") is True
حالتهای مختلف کوچکی/بزرگی حروف در رشتهها
پایتون برخی تابعهای داخلی دارد که میتوان از آنها برای تغییر حالت حروف یک رشته استفاده کرد.
1def to_uppercase(input_string:str) -> str:
2 return input_string.upper()
3
4def to_lowercase(input_string:str) -> str:
5 return input_string.lower()
6
7def to_sentencecase(input_string:str) -> str:
8 return input_string.capitalize()
9
10def to_titlecase(input_string:str) -> str:
11 return input_string.title()
12
13def to_swapcase(input_string:str) -> str:
14 return input_string.swapcase()
15
16assert to_uppercase("the end of time") == "THE END OF TIME"
17assert to_lowercase("The End Of Time") == "the end of time"
18assert to_sentencecase("The End of Time") == "The end of time"
19assert to_titlecase("the end of time") == "The End Of Time"
20assert to_swapcase("The End Of Time") == "tHE eND oF tIME"
الحاق کارآمد رشتهها در هم
استفاده از join روی یک رشته خالی موجب الحاق پارامترها میشود.
این تابع تعداد متغیری از آرگومانها را با استفاده از نشانگر * دریافت میکند.
1def concatenate(*argv)->str:
2 return ''.join(argv)
3
4
5assert concatenate("a", "b", "c") == "abc"
بررسی خالی بودن رشته
یک شیء string کاملاً معمولی میتواند شامل 0 کاراکتر باشد یا همه کاراکترهای آن فضای خالی باشند و یا حتی یک شیء از نوع None باشد. این تابع میتواند برای تست این مسئله استفاده شود که آیا رشته شامل محتوای کاراکتری یا بایتی است.
1def is_null_or_blank(input_string: str = "") -> bool:
2
3 if input_string:
4 if input_string.strip():
5 return False
6 return True
7
8
9assert is_null_or_blank(None) == True
10assert is_null_or_blank("") == True
11assert is_null_or_blank(" ") == True
12assert is_null_or_blank(" d ") == False
حذف فضاهای خالی ابتدا و انتهای رشته
تابع زیر یک سهتایی بازگشت میدهد که هر عنصر شامل یک نسخه از string اصلی است اما در هر کدام از آنها فضاهای خالی رشته به ترتیبی جدا شدهاند. در خط 6 میبینیم که پایتون گزارههایی که مقدار را به متغیرهای چندگانه نسبت میدهند درک کرده است.
1def strip_it(input_string: str) -> tuple:
2
3 return (input_string.lstrip(), input_string.rstrip(), input_string.strip())
4
5
6left, right, full = strip_it(" A padded string ")
7assert left == "A padded string "
8assert right == " A padded string"
9assert full == "A padded string"
تولید یک رشته از کاراکترهای تصادفی
امکان استفاده از ماژول secrets برای تولید گزینههای تصادفی از کاراکترها و افزودن آنها به یک رشته وجود دارد.
1import string
2import secrets
3
4
5def generate_random_string(length: int = 0) -> str:
6 result = "".join(
7 secrets.choice(string.ascii_letters + string.digits)
8 for _ in range(length))
9 return result
10
11
12assert len(generate_random_string(20)) == 20
خواندن خطوط یک فایل به یک لیست
در کد زیر شیء فایلخوان f به طور صریح به یک لیست تبدیل شده است. توجه کنید که ما فایل را در حالت ‘r’ برای read-only بودن باز نکردهایم.
1def file_to_list(filename: str = "") -> list:
2
3 with open(filename, "r") as f:
4 lines = list(f)
5
6 return lines
7
8
9assert len(file_to_list("<PATH TO FILE>")) == LINE_COUNT
توکندار کردن کامل یک جمله
توکندار کردن یک رویه در پردازش زبان طبیعی است که در طی آن همه توکنها در یک جمله مانند علائم سجاوندی بازگشت مییابند. در کد زیر از NLTK استفاده کردهایم که باید به صورت مجزا نصب شود.
1import nltk
2
3
4def tokenize_text(input_str: str = "") -> list:
5 return nltk.wordpunct_tokenize(input_str)
6
7
8assert tokenize_text("Good muffins cost $3.88\nin New York.") == [
9 "Good",
10 "muffins",
11 "cost",
12 "$",
13 "3",
14 ".",
15 "88",
16 "in",
17 "New",
18 "York",
19 ".",
20]
اجرای کد پایتون موجود درون یک رشته
در این بخش دو روش برای اجرای یک کد که درون رشته قرار دارد نمایش یافته است. متد exec_string محتوای یک رشته را به سیستم عامل ارسال میکند. متد eval_string از پایتون برای ارزیابی رشته استفاده میکند. در مورد کار کردن با هر دو متد هوشیار باشید، زیرا ممکن است رشتههایی که اجرا میکنید، شامل بدافزار باشند.
1import subprocess
2import ast
3
4
5def exec_string(input_string: str = "") -> str:
6 result = subprocess.getoutput(input_string)
7 return result
8
9
10def eval_string(input_string: str = "") -> str:
11 result = ast.literal_eval(input_string)
12 return str(result)
13
14
15assert exec_string("ls -l")
16assert eval_string("{ 'key':'value' }") == "{'key': 'value'}"
یافتن عبارت بین دو علامت
به این منظور از «عبارتهای منظم» (regular expressions) و F-String-ها استفاده کردهایم.
1import re
2
3
4def between(first: str = "", second: str = "", input_string="") -> str:
5
6 m = re.search(f"{first}(.+?){second}", input_string)
7 if m:
8 return m.group(1)
9
10 else:
11 return ""
12
13
14assert between(input_string="adCCCTHETEXTZZZdfhewihu",
15 first="CCC",
16 second="ZZZ") == "THETEXT"
حذف همه علائم سجاوندی از یک رشته
این ماژول رشته شامل لیستی از کاراکترهای سجاوندی است. با استفاده از translate (نکته شماره 21 را ببینید) میتوانیم آنها را از رشته حذف کنیم.
1import string
2
3
4def remove_punctuation(input_string: str = "") -> str:
5 return input_string.translate(str.maketrans("", "", string.punctuation))
6
7
8assert remove_punctuation("Hello!") == "Hello"
9assert remove_punctuation("He. Saw! Me?") == "He Saw Me"
انکود و دیکد کردن URL-های UTF-8
UTF-8 به ما امکان میدهد که از کاراکترهای بسطیافته و دابل-ورد مانند ایموجیها استفاده کنیم.
این کاراکترها پیش از آن که در یک URL استفاده شوند، باید انکود شوند.
1import urllib.parse
2
3
4def encode_url(url: str = "") -> str:
5 return urllib.parse.quote(url)
6
7
8def decode_url(url: str = "") -> str:
9 return urllib.parse.unquote(url)
10
11
12assert (encode_url("example.com?title=¨ˆπœ˚∑π") ==
13 "example.com%3Ftitle%3D%C2%A8%CB%86%CF%80%C5%93%CB%9A%E2%88%91%CF%80")
14assert decode_url("example.com?title=%a0%f7%b1") == "example.com?title=���"
استفاده از انکودینگ Base64 روی رشتهها
Base64 یک متد برای انکود کردن دادههای دودویی به صورت یک رشته و انتقال در پیامهای متنی است. از آن میتوان برای انکود کردن رشتههای UTF-8 نیز استفاده کرد.
1import base64
2
3
4def encode_b64(input_string: str = "") -> object:
5 return base64.b64encode(input_string.encode("utf-8"))
6
7
8def decode_b64(input_string: str = "") -> object:
9 return base64.b64decode(input_string).decode("utf-8")
10
11
12assert encode_b64("Hello") == b"SGVsbG8="
13assert decode_b64(b"SGVsbG8=") == "Hello"
محاسبه مشابهت بین دو رشته
برای محاسبه مشابهت بین دو رشته، جدا از استفاده از «مسافت لوناشتاین» (Levenshtein distance) در nltk.edit_distance میتوان از کتابخانه difflib نیز استفاده کرد. مقدار 1.0 به معنی برابری دقیق است.
1import difflib
2
3
4def similarity(left: str = "", right: str = "") -> float:
5
6 seq = difflib.SequenceMatcher(None, left, right)
7 return seq.ratio()
8
9
10assert similarity("I like bananas", "I like bananarama") >= 0.80
11assert similarity("I like bananas", "The quick brown fox") <= 0.25
حذف یک کاراکتر از یک اندیس خاص
بک بار دیگر باید اشاره کنیم که رشتهها دنبالهای از کاراکترها هستند و از این رو میتوانیم از عملیات slice روی آنها استفاده کنیم.
1def remove_by_index(original: str = "", index: int = -1) -> tuple:
2 if len(original) >= index and index >= 0:
3 return (original[:index] + original[index + 1:], original[index])
4 else:
5 return (original, "")
6
7
8assert remove_by_index("0123456789", 5) == ("012346789", "5")
9view rawstrings_22_remove_at_index.py hosted with ❤ by GitHub
تبدیل CSV به لیست و برعکس
مقادیر جدا شده با کاما (CSV) رواج زیادی دارند، زیرا اکسل آنها را به شیوه خوبی مدیریت میکند و راهکاری عمومی برای حل مسائل دادهای محسوب میشوند. در کد زیر یک خط منفرد CSV را دریافت کرده و آن را به یک لیست از مقادیر تبدیل میکنیم.
1def from_csv_line(line: str = "") -> list:
2
3 return line.split(",")
4
5
6assert from_csv_line("a,b,c") == ["a", "b", "c"]
خط 3 کد فوق یک لیست تولید میکند و خط ورودی را هر بار که با جداکننده (,) مواجه شود میشکند. اکنون عکس این کار را اجرا میکنیم و یک لیست را به خط CSV تبدیل میکنیم.
1def from_list(line: list = []) -> str:
2
3 ret = ", ".join(e for e in line)
4 return ret
5
6
7assert from_list(["a", "b", "c"]) == "a, b, c"
8assert from_list(["one", "two", "three"]) == "one, two, three"
الحاق یک در میان کاراکترهای دو رشته
با استفاده از متد zip_longest از ماژول itertools میتوانیم دو رشته با طولهای نابرابر را به صورت کاراکترهای یک در میان از هر یک از رشتهها در هم الحاق کنیم. این راهحل در خروجی یک «خلاصه لیست» (list comprehension) ارائه میکند که رشته I + j را در هم ادغام کرده است.
1import itertools
2
3
4def interleave(left: str = "", right: str = "") -> str:
5
6 return "".join(
7 [i + j for i, j in itertools.zip_longest(left, right, fillvalue="")])
8
9
10assert interleave("ABCD", "01") == "A0B1CD"
حذف کاراکترهای ناخواسته از یک رشته
به این منظور از تابع replace استفاده میکنیم. به خاطر داشته باشید که امکان تغییر مقدار یک رشته به صورت درجا وجود ندارد، چون رشتهها «تغییرناپذیر» (immutable) هستند. نکته شماره 21 را نیز ببینید:
1def remove_unwanted(original: str = "",
2 unwanted: str = "",
3 replacement: str = "") -> str:
4
5 return original.replace(unwanted, replacement)
6
7
8assert remove_unwanted(original="M'The Real String'",
9 unwanted="M") == "'The Real String'"
یافتن اندیس موقعیت یک کاراکتر در رشته
در این راهکار از یک «خلاصه لیست» (list comprehension) به همراه یک فیلتر با استفاده از if بهره میگیریم.
1def find_char_locations(original: str = "", character: str = "") -> list:
2
3 return [index for index, char in enumerate(original) if char == character]
4
5
6assert find_char_locations("The jolly green giant.", "e") == [2, 12, 13]
ترجمه رشته به کاراکترهای جایگزین
با استفاده از تابعهای maketrans و translate میتوانیم یک رشته را به حالت بهرهگیری از کاراکترهای جایگزین تبدیل کنیم.
1def to_leetspeak(normal_speak:str="") -> str:
2
3 leet_mapping = str.maketrans("iseoau", "1530^Ü")
4 return normal_speak.translate(leet_mapping).title().swapcase()
5
6assert to_leetspeak("the quick brown fox jumped over the lazy dogs") == \
7 "tH3 qÜ1cK bR0wN f0x jÜMP3d 0v3r tH3 l^zY d0g5"
به این ترتیب به پایان این مقاله با عنوان 22 ترفند پایتون برای کار با رشتهها میرسیم.