Курси фишурдаи Python

Омӯзиши барномасозӣ бо Python аз сифр: насби Python ва муҳаррири код, тағйирёбандаҳо ва сатрҳо, рӯйхатҳо, дастурҳои if, луғатҳо, воридкунии маълумот ва даврҳои while, функсияҳо, классҳо, кор бо файлҳо ва истисноҳо ва санҷиши код бо pytest. Ҳар боб мисолҳои код ва машқҳои «Худатон бисанҷед» дорад. Муқаддима ва бобҳои 2–11 тарҷумаи тоҷикии китоби Эрик Маттес «Python Crash Course» (нашри 3) мебошанд; боби 1 ва замима барои ин нашр навишта шудаанд.
Агенти Зеҳнӣ · 16 октябри 2026 · 13 саҳифа · 2 писанд
Боби 10. Файлҳо ва истисноҳо
Акнун, ки малакаҳои асосии навиштани барномаҳои мураттаб ва осонро аз худ кардед, вақти он расидааст, ки барномаҳоятонро боз ҳам муфидтар ва барои истифода мувофиқтар созед. Дар ин боб кор бо файлҳоро меомӯзед, то барномаҳоятон миқдори зиёди додаҳоро зуд таҳлил карда тавонанд.
Шумо тарзи коркарди хатоҳоро меомӯзед, то барномаҳо ҳангоми рӯ ба рӯ шудан бо ҳолатҳои ғайричашмдошт аз кор намонанд. Бо истисноҳо шинос мешавед: инҳо объектҳои махсусе мебошанд, ки Python барои идора кардани хатоҳои ҳангоми иҷрои барнома пайдошаванда месозад. Ҳамчунин бо модули json шинос мешавед, ки имкон медиҳад додаҳои корбарро нигоҳ доред, то пас аз қатъ шудани барнома гум нашаванд.
Омӯхтани кор бо файлҳо ва нигоҳдории додаҳо истифодаи барномаҳои шуморо осонтар мекунад. Корбарон метавонанд интихоб кунанд, ки кадом додаҳоро ва кай ворид намоянд. Онҳо метавонанд барномаро иҷро кунанд, каме кор кунанд, сипас онро пӯшанд ва баъдтар корро аз ҷойи қатъшуда идома диҳанд.
Омӯхтани коркарди истисноҳо ба шумо ёрӣ медиҳад, ки набудани файлҳо ва дигар мушкилоти сабабгори қатъ шудани барномаро идора кунед. Дар натиҷа, барномаҳои шумо ҳангоми рӯ ба рӯ шудан бо додаҳои нодуруст устувортар мешаванд — хоҳ ин додаҳо аз иштибоҳи одӣ пайдо шуда бошанд, хоҳ аз кӯшиши қасдан вайрон кардани барнома.
Бо малакаҳои ин боб барномаҳоятонро корбурдитар, қулайтар ва устувортар хоҳед сохт.
Хондан аз файл
Миқдори бениҳоят зиёди додаҳо дар файлҳои матнӣ дастрасанд. Файлҳои матнӣ метавонанд маълумоти обу ҳаво, ҳаракати нақлиёт, маълумоти иҷтимоию иқтисодӣ, асарҳои адабӣ ва чизҳои дигарро дар бар гиранд.
Хондан аз файл махсусан дар барномаҳои таҳлили додаҳо муфид аст. Вале он дар ҳар ҳолате низ истифода мешавад, ки мехоҳед маълумоти дар файл нигоҳдошташударо таҳлил ё тағйир диҳед. Масалан, метавонед барномае нависед, ки муҳтавои файли матниро мехонад ва онро бо қолаббандие аз нав менависад, ки браузер тавонад намоиш диҳад.
Барои кор бо маълумоти файли матнӣ, қадами аввал хондани файл ба хотира аст. Баъд метавонед тамоми муҳтавои файлро якбора ё сатр ба сатр коркард кунед.
Хондани муҳтавои файл
Барои оғоз ба мо файле лозим аст, ки чанд сатри матн дошта бошад. Биёед аз файле оғоз кунем, ки адади π-ро то 30 рақам пас аз нуқтаи даҳӣ нигоҳ медорад: дар ҳар сатр 10 рақам.
pi_digits.txt
3.1415926535
8979323846
2643383279
Барои мустақилона санҷидани мисолҳои минбаъда, метавонед ин сатрҳоро дар муҳаррир ворид карда, файлро бо номи pi_digits.txt нигоҳ доред. Ё онро аз захираҳои китоб дар ин сомона боргирӣ кунед. Файлро дар ҳамон ҷузвдоне нигоҳ доред, ки барномаҳои ин бобро ҷойгир мекунед.
Ин барнома файлро мекушояд, онро мехонад ва муҳтавояшро дар экран чоп мекунад:
file_reader.py
from pathlib import Path
path = Path('pi_digits.txt') # ❶
contents = path.read_text(encoding='utf-8') # ❷
print(contents)
Барои кор бо муҳтавои файл, бояд ба Python роҳи онро нишон диҳем. Роҳ ҷойгиршавии дақиқи файл ё ҷузвдон дар система аст.
Python модуле бо номи pathlib дорад, ки кор бо файлҳо ва ҷузвдонҳоро, новобаста аз системаи амалиётии шумо ё корбаронатон, осон мекунад. Модулеро, ки чунин имкониятҳои муайянро пешниҳод мекунад, аксар вақт китобхона меноманд; номи pathlib низ аз ҳамин бармеояд.
Аввал класси Path-ро аз pathlib ворид мекунем. Бо объекти Path, ки ба файл ишора мекунад, корҳои зиёдеро анҷом додан мумкин аст. Масалан, пеш аз кор бо файл мавҷудияти онро санҷидан, муҳтавояшро хондан ё ба он додаҳои нав навиштан мумкин аст.
Дар ин ҷо объекти Path месозем, ки файли pi_digits.txt-ро ифода мекунад ва онро ба тағйирёбандаи path нисбат медиҳем ❶. Азбаски ин файл дар ҳамон ҷузвдони файли .py-и мо нигоҳ дошта шудааст, барои дастрасӣ ба он номи файл кифоя аст.
Эзоҳ: VS Code файлҳоро дар ҷузвдоне меҷӯяд, ки охирин бор кушода шудааст. Агар VS Code истифода баред, аввал ҷузвдонеро кушоед, ки барномаҳои ин бобро дар он нигоҳ медоред. Масалан, агар файлҳои барнома дар ҷузвдони chapter_10 бошанд, тугмаҳои CTRL-O ё дар macOS — ⌘-O-ро пахш карда, он ҷузвдонро кушоед.
Пас аз сохтани объекти Path барои pi_digits.txt, методи read_text()-ро истифода мебарем, то тамоми муҳтавои файлро бихонем ❷. Муҳтавои файл ҳамчун як сатри матнӣ баргардонда мешавад ва мо онро ба тағйирёбандаи contents нисбат медиҳем.
Аргументи encoding='utf-8' ба Python мегӯяд, ки файл бо кадом рамзгузорӣ (encoding) навишта шудааст — яъне ҳар ҳарф дар файл бо кадом байтҳо нигоҳ дошта мешавад. Агар онро нанависед, Python рамзгузории пешфарзи системаро истифода мебарад. Дар macOS ва Linux ин одатан UTF-8 аст, аммо дар баъзе версияҳои Windows рамзгузории дигаре истифода мешавад, ки ҳарфҳои тоҷикӣ, масалан «ӯ», «ҳ» ва «ҷ»-ро дар бар намегирад. Он гоҳ хондан ё навиштани матни тоҷикӣ бо хатои UnicodeDecodeError ё UnicodeEncodeError қатъ мешавад. Бинобар ин дар ин китоб ҳангоми хондан ва навиштани ҳар файли матнӣ encoding='utf-8'-ро ҳамеша менависем. Шумо низ инро одат кунед.
Ҳангоми чоп кардани қимати contents, тамоми муҳтавои файли матниро мебинем:
3.1415926535
8979323846
2643383279
Ягона фарқ байни ин натиҷа ва файли аслӣ сатри холии иловагӣ дар охири натиҷа аст. Агар матни файл бо аломати сатри нав анҷом ёбад, ин аломат бо сатри наве, ки print() илова мекунад, як сатри холии иловагӣ ба вуҷуд меорад.
Метавонем ин сатри холии иловагиро бо истифода аз rstrip() дар сатри contents бардорем:
from pathlib import Path
path = Path('pi_digits.txt')
contents = path.read_text(encoding='utf-8')
contents = contents.rstrip()
print(contents)
Аз боби 2 ба ёд оред, ки методи rstrip() аломатҳои фосилавиро аз тарафи рости сатр мебардорад. Акнун натиҷа комилан ба муҳтавои файли аслӣ мувофиқат мекунад:
3.1415926535
8979323846
2643383279
Ҳангоми хондани файл низ метавонем аломати сатри нави охирро бардорем: барои ин rstrip()-ро бевосита пас аз read_text() истифода мебарем:
contents = path.read_text(encoding='utf-8').rstrip()
Ин сатр ба Python мегӯяд, ки аввал методи read_text()-ро барои файл иҷро кунад. Сипас ба сатри баргардондаи он методи rstrip() татбиқ мешавад. Дар охир сатри тозашуда ба contents нисбат дода мешавад.
Ин тарзро занҷиракунии методҳо меноманд ва шумо онро дар барномасозӣ зуд-зуд хоҳед дид.
Роҳҳои нисбӣ ва мутлақи файлҳо
Вақте ба Path номи одии файл, масалан pi_digits.txt-ро медиҳед, Python онро дар ҷузвдони кории ҷорӣ меҷӯяд. Дар мисолҳои ин боб чунин фарз шудааст, ки ҷузвдони корӣ ҳамон ҷузвдони барнома аст.
Баъзан, вобаста ба тарзи ташкили кор, файле, ки мехоҳед кушоед, дар ҳамон ҷузвдони барнома намешавад. Масалан, метавонед файлҳои барномаро дар ҷузвдони python_work нигоҳ доред ва дар дохили он ҷузвдони дигаре бо номи text_files созед. Ин кор файлҳои барномаро аз файлҳои матние, ки коркард мекунанд, ҷудо мекунад.
Гарчанде text_files дар дохили python_work аст, танҳо додани номи файли дохили он ба Path кор намекунад. Python дар python_work меҷӯяд ва худкор ба ҷустуҷӯ дар text_files намегузарад. Барои кушодани файл аз ҷузвдони дигар, бояд роҳи дурустро нишон диҳед.
Дар барномасозӣ ду роҳи асосии нишон додани ҷойгиршавии файл вуҷуд дорад.
Роҳи нисбӣ ҷойгиршавиро нисбат ба ҷузвдони кории ҷорӣ нишон медиҳад. Азбаски text_files дар дохили python_work аст, роҳ бояд аз номи ҷузвдони text_files оғоз шуда, бо номи файл анҷом ёбад:
path = Path('text_files/filename.txt')
Ҳамчунин метавонед ҷойгиршавии дақиқи файлро дар компютер нишон диҳед, новобаста аз он ки барнома аз куҷо иҷро мешавад. Инро роҳи мутлақ меноманд.
Агар роҳи нисбӣ мувофиқ набошад, метавонед роҳи мутлақро истифода баред. Масалан, агар text_files дар ҷузвдоне берун аз python_work бошад, роҳи 'text_files/filename.txt' кор намекунад, зеро Python ин ҷойгиршавиро дар дохили ҷузвдони кории ҷорӣ меҷӯяд. Барои дақиқ нишон додани ҷойгиршавӣ бояд роҳи мутлақро нависед.
Роҳҳои мутлақ одатан аз роҳҳои нисбӣ дарозтаранд, зеро аз ҷузвдони решавии система оғоз мешаванд:
path = Path('/home/eric/data_files/text_files/filename.txt')
Бо роҳҳои мутлақ метавонед файлҳоро аз ҳар ҷойи система бихонед. Ҳоло осонтар аст, ки файлҳоро дар ҳамон ҷузвдони барнома ё дар зерҷузвдоне мисли text_files нигоҳ доред.
Эзоҳ: Windows ҳангоми намоиши роҳҳо ба ҷойи хатти моил / аз хатти моили баръакс \ истифода мебарад. Вале дар код, ҳатто дар Windows, метавонед / истифода баред. Китобхонаи pathlib ҳангоми кор бо система шакли мувофиқи роҳро худкор истифода мебарад.
Дастрасӣ ба сатрҳои файл
Ҳангоми кор бо файл аксар вақт мехоҳед ҳар сатри онро алоҳида баррасӣ кунед. Шояд маълумоти муайянеро ҷустуҷӯ доред ё мехоҳед матнро ба ягон тарз тағйир диҳед.
Масалан, метавонед файли маълумоти обу ҳаворо хонда, сатрҳоеро коркард кунед, ки дар тавсифи обу ҳавояшон калимаи sunny — «офтобӣ» омадааст. Дар гузориши хабарӣ метавонед сатрҳои дорои нишонаи ``-ро ёфта, онҳоро бо қолаббандии муайян аз нав нависед.
Методи splitlines() сатри дарози матниро ба рӯйхати сатрҳо табдил медиҳад. Баъд бо даври for ҳар сатри файлро алоҳида баррасӣ карда метавонед:
file_reader.py
from pathlib import Path
path = Path('pi_digits.txt')
contents = path.read_text(encoding='utf-8') # ❶
lines = contents.splitlines() # ❷
for line in lines:
print(line)
Мисли пештара, аввал тамоми муҳтавои файлро мехонем ❶. Агар хоҳед бо сатрҳои алоҳида кор кунед, ҳангоми хондани файл бардоштани аломатҳои фосилавӣ лозим нест.
Методи splitlines() рӯйхати ҳамаи сатрҳои файлро бармегардонад ва мо онро ба тағйирёбандаи lines нисбат медиҳем ❷. Сипас аз рӯйи ин сатрҳо мегузарем ва ҳар кадомро чоп мекунем:
3.1415926535
8979323846
2643383279
Азбаски ягон сатрро тағйир надодаем, натиҷа комилан ба файли матнии аслӣ мувофиқат мекунад.
Кор бо муҳтавои файл
Пас аз хондани муҳтавои файл ба хотира, метавонед бо додаҳои он ҳар амали лозимиро анҷом диҳед. Биёед рақамҳои адади π-ро каме омӯзем.
Аввал кӯшиш мекунем як сатри ягонае созем, ки тамоми рақамҳои файлро бе фосила дар бар гирад:
pi_string.py
from pathlib import Path
path = Path('pi_digits.txt')
contents = path.read_text(encoding='utf-8')
lines = contents.splitlines()
pi_string = ''
for line in lines: # ❶
pi_string += line
print(pi_string)
print(len(pi_string))
Мисли мисоли пешина, аввал файлро мехонем ва ҳар сатри рақамҳоро дар рӯйхат нигоҳ медорем. Баъд тағйирёбандаи pi_string-ро месозем, то рақамҳои π-ро дар он ҷамъ кунем.
Давре менависем, ки ҳар сатри рақамҳоро ба pi_string илова мекунад ❶. Сипас ин сатр ва дарозии онро чоп мекунем:
3.1415926535 8979323846 2643383279
36
Тағйирёбандаи pi_string фосилаҳои дар тарафи чапи рақамҳои ҳар сатр бударо низ дар бар мегирад. Метавонем онҳоро бо истифода аз lstrip() барои ҳар сатр бардорем:
from pathlib import Path
path = Path('pi_digits.txt')
contents = path.read_text(encoding='utf-8')
lines = contents.splitlines()
pi_string = ''
for line in lines:
pi_string += line.lstrip()
print(pi_string)
print(len(pi_string))
Акнун сатре дорем, ки π-ро то 30 рақам пас аз нуқтаи даҳӣ дар бар мегирад. Дарозии он 32 аломат аст, зеро рақами аввали 3 ва нуқтаи даҳӣ низ ҳисоб мешаванд:
3.141592653589793238462643383279
32
Эзоҳ: Ҳангоми хондан аз файли матнӣ Python тамоми муҳтавои онро ҳамчун матн қабул мекунад. Агар ададеро хонед ва хоҳед бо он амалҳои ададӣ анҷом диҳед, бояд онро бо int() ба адади бутун ё бо float() ба адади касрӣ табдил диҳед.
Файлҳои калон: як миллион рақам
То ҳол файли матниеро таҳлил кардем, ки ҳамагӣ се сатр дошт. Вале коди ин мисолҳо барои файлҳои хеле калонтар низ кор мекунад.
Агар ба ҷойи 30 рақам файле дошта бошем, ки π-ро то 1 000 000 рақам пас аз нуқтаи даҳӣ нигоҳ медорад, метавонем як сатри ягонаи дорои ҳамаи ин рақамҳоро созем. Ба ғайр аз номи файли воридшаванда, тағйир додани барнома лозим нест.
Ҳамчунин танҳо 50 рақами аввали пас аз нуқтаи даҳиро чоп мекунем, то маҷбур нашавем гузаштани як миллион рақамро дар терминал тамошо кунем:
pi_string.py
from pathlib import Path
path = Path('pi_million_digits.txt')
contents = path.read_text(encoding='utf-8')
lines = contents.splitlines()
pi_string = ''
for line in lines:
pi_string += line.lstrip()
print(f"{pi_string[:52]}...")
print(len(pi_string))
Натиҷа нишон медиҳад, ки дар ҳақиқат сатри дорои як миллион рақами пас аз нуқтаи даҳии π-ро дорем:
3.14159265358979323846264338327950288419716939937510...
1000002
Python барои ҳаҷми чунин додаҳо маҳдудияти хурди собит надорад: метавонед бо ҳамон қадар дода кор кунед, ки хотираи системаатон имконият медиҳад.
Эзоҳ: Барои иҷрои ин барнома ва бисёре аз мисолҳои минбаъда, бояд захираҳои дар сомонаи китоб дастрасро боргирӣ кунед.
Оё санаи таваллуди шумо дар рақамҳои π ҳаст?
Ман ҳамеша мехостам бидонам, ки оё санаи таваллудам дар ягон ҷойи рақамҳои π пайдо мешавад ё не. Биёед барномаи навиштаамонро истифода барем, то муайян кунем, ки санаи таваллуди касе дар як миллион рақами аввали π ҳаст ё не.
Барои ин санаи таваллудро ҳамчун пайдарпайии рақамҳо ифода карда, месанҷем, ки ин пайдарпайӣ дар pi_string ҳаст ё не:
pi_birthday.py
from pathlib import Path
path = Path('pi_million_digits.txt')
contents = path.read_text(encoding='utf-8')
lines = contents.splitlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
birthday = input(
"Санаи таваллудатонро дар шакли mmddyy ворид кунед: "
)
if birthday in pi_string:
print("Санаи таваллуди шумо дар як миллион рақами аввали π ҳаст!")
else:
print("Санаи таваллуди шумо дар як миллион рақами аввали π нест.")
Аввал аз корбар санаи таваллудашро мепурсем. Баъд месанҷем, ки ин сатр дар pi_string ҳаст ё не. Дар қолаби mmddyy, mm моҳ, dd рӯз ва yy ду рақами охири солро ифода мекунанд.
Биёед санҷем:
Санаи таваллудатонро дар шакли mmddyy ворид кунед: 120372
Санаи таваллуди шумо дар як миллион рақами аввали π ҳаст!
Санаи таваллуди ман дар рақамҳои π будааст! Пас аз хондани файл метавонед муҳтавояшро қариб бо ҳар тарзе, ки тасаввур мекунед, таҳлил намоед.
Худатон бисанҷед
10-1. Омӯзиши Python. Дар муҳаррири матнӣ файли холӣ кушоед ва чанд сатр дар бораи он нависед, ки то имрӯз аз Python чӣ омӯхтед. Ҳар сатрро бо ибораи «Дар Python шумо метавонед…» оғоз кунед.
Файлро бо номи learning_python.txt дар ҳамон ҷузвдони машқҳои ин боб нигоҳ доред. Барномае нависед, ки файлро мехонад ва навиштаҳоятонро ду бор чоп мекунад: як бор бо хондани тамоми муҳтавои файл ва бори дигар бо нигоҳ доштани сатрҳо дар рӯйхат ва гузаштан аз рӯйи ҳар сатр.
10-2. Омӯзиши C. Методи replace() имкон медиҳад як калимаи сатрро бо калимаи дигар иваз кунед. Ин мисоли кӯтоҳ нишон медиҳад, ки чӣ гуна dog-ро дар ҷумла бо cat иваз кардан мумкин аст:
>>> message = "I really like dogs."
>>> message.replace('dog', 'cat')
'I really like cats.'
Ҳар сатри файли ҳозир сохтаатон — learning_python.txt-ро хонед ва калимаи Python-ро бо номи забони дигаре, масалан C, иваз кунед. Ҳар сатри тағйирёфтаро дар экран чоп намоед.
10-3. Коди содатар. Барномаи file_reader.py дар ин бахш барои нишон додани кори splitlines() тағйирёбандаи муваққатии lines-ро истифода мебарад. Метавонед аз ин тағйирёбанда даст кашида, бевосита аз рӯйи рӯйхати баргардондаи splitlines() гузаред:
for line in contents.splitlines():
Барои кӯтоҳтар кардани барномаҳои ин бахш, тағйирёбандаи муваққатиро аз ҳар кадом бардоред.
Навиштан ба файл
Яке аз роҳҳои осонтарини нигоҳдории додаҳо навиштани онҳо ба файл аст. Вақте матнро ба файл менависед, он пас аз бастани терминале, ки натиҷаи барномаро нишон медиҳад, низ дастрас мемонад.
Метавонед натиҷаро баъд аз анҷоми барнома баррасӣ кунед ва файлҳои натиҷаро бо дигарон мубодила намоед. Ҳамчунин метавонед барномаҳое нависед, ки баъдтар матнро дубора ба хотира мехонанд ва бо он кор мекунанд.
Навиштани як сатр
Пас аз муайян кардани роҳ, метавонед бо методи write_text() ба файл нависед. Барои дидани кори он, паёми одие менависем ва ба ҷойи чоп дар экран, онро дар файл нигоҳ медорем:
write_message.py
from pathlib import Path
path = Path('programming.txt')
path.write_text("Ман барномасозиро дӯст медорам.", encoding='utf-8')
Методи write_text() сатреро мегирад, ки мехоҳед ба файл нависед. Мисли read_text(), рамзгузориро бо encoding='utf-8' нишон медиҳем, то ҳарфҳои тоҷикӣ дар ҳама системаҳо дуруст навишта шаванд. Ин барнома дар терминал чизе чоп намекунад. Вале агар programming.txt-ро кушоед, як сатр мебинед:
programming.txt
Ман барномасозиро дӯст медорам.
Ин файл мисли ҳар файли дигари компютер аст. Метавонед онро кушоед, ба он матни нав нависед, аз он нусха бардоред, ба он матн гузоред ва ғайра.
Эзоҳ: Python ба файли матнӣ танҳо сатрҳои матниро менависад. Агар хоҳед додаҳои ададиро дар файли матнӣ нигоҳ доред, аввал онҳоро бо функсияи str() ба матн табдил диҳед.
Навиштани чанд сатр
Методи write_text() дар паси парда чанд корро анҷом медиҳад. Агар файле, ки path ба он ишора мекунад, вуҷуд надошта бошад, онро месозад. Ҳамчунин пас аз навиштани сатр файлро дуруст мебандад. Файлҳое, ки дуруст баста намешаванд, метавонанд боиси гум шудан ё вайроншавии додаҳо гарданд.
Барои навиштани зиёда аз як сатр, бояд сатри матние созед, ки тамоми муҳтавои файлро дар бар гирад. Баъд онро ба write_text() медиҳед.
Биёед чанд сатрро ба programming.txt нависем:
from pathlib import Path
contents = "Ман барномасозиро дӯст медорам.\n"
contents += "Ман сохтани бозиҳои навро дӯст медорам.\n"
contents += "Ҳамчунин кор бо додаҳоро дӯст медорам.\n"
path = Path('programming.txt')
path.write_text(contents, encoding='utf-8')
Тағйирёбандаи contents-ро муайян мекунем, ки тамоми муҳтавои файлро нигоҳ медорад. Дар сатри навбатӣ бо оператори += ба он матн илова мекунем.
Ин корро ҳар қадар лозим бошад, такрор карда, сатри дилхоҳ дарозӣ сохтан мумкин аст. Дар ин мисол дар охири ҳар ҷумла аломати сатри нав мегузорем, то ҳар ҷумла дар сатри алоҳида пайдо шавад.
Агар барномаро иҷро карда, баъд programming.txt-ро кушоед, чунин сатрҳоро мебинед:
Ман барномасозиро дӯст медорам.
Ман сохтани бозиҳои навро дӯст медорам.
Ҳамчунин кор бо додаҳоро дӯст медорам.
Мисли натиҷаҳои терминалӣ, барои қолаббандии натиҷа метавонед фосилаҳо, аломатҳои табулятсия ва сатрҳои холиро истифода баред. Бо ҳамин роҳ бисёр ҳуҷҷатҳои аз тарафи компютер тавлидшаванда сохта мешаванд.
Эзоҳ: Ҳангоми истифодаи write_text() эҳтиёт кунед. Агар файл аллакай вуҷуд дошта бошад, ин метод муҳтавои ҷории онро пок карда, муҳтавои навро менависад. Баъдтар дар ин боб меомӯзед, ки чӣ гуна мавҷудияти файлро бо pathlib санҷед.
Худатон бисанҷед
10-4. Меҳмон. Барномае нависед, ки номи корбарро мепурсад. Пас аз ҷавоби ӯ, номашро ба файле бо номи guest.txt нависед.
10-5. Дафтари меҳмонон. Даври while нависед, ки номи корбаронро мепурсад. Ҳамаи номҳои воридшударо ҷамъ карда, сипас онҳоро ба guest_book.txt нависед. Боварӣ ҳосил кунед, ки ҳар ном дар сатри нав ҷой мегирад.
Истисноҳо
Python барои идора кардани хатоҳои ҳангоми иҷрои барнома пайдошаванда объектҳои махсусеро истифода мебарад, ки истисноҳо ном доранд.
Ҳар гоҳ хатое рӯй диҳад, ки Python иҷрои одии барномаро идома дода натавонад, объекти истисно месозад. Агар барои коркарди ин истисно код навишта бошед, барнома иҷроишро идома медиҳад. Агар онро коркард накунед, барнома қатъ шуда, traceback — гузориши пайгирии хаторо нишон медиҳад. Ин гузориш маълумотро дар бораи истиснои баамаломада дар бар мегирад.
Истисноҳо бо блокҳои try-except коркард мешаванд. Блоки try-except аз Python хоҳиш мекунад амалеро иҷро кунад ва ҳамзамон нишон медиҳад, ки агар истисно ба вуҷуд ояд, чӣ бояд кард.
Бо истифода аз чунин блокҳо барномаҳоятон ҳатто ҳангоми пайдо шудани мушкилот метавонанд корро идома диҳанд. Ба ҷойи гузоришҳои пайгирии хато, ки барои корбарон нофаҳмо буда метавонанд, онҳо паёмҳои фаҳмои навиштаи шуморо мебинанд.
Коркарди истиснои ZeroDivisionError
Биёед хатои одие баррасӣ кунем, ки боиси пайдо шудани истисно мешавад. Эҳтимол медонед, ки ададро ба сифр тақсим кардан мумкин нест. Бо вуҷуди ин, аз Python талаб мекунем чунин амалро иҷро кунад:
division_calculator.py
print(5/0)
Python ин амалро иҷро карда наметавонад, бинобар ин гузориши пайгирии хато мегирем:
Traceback (most recent call last):
File "division_calculator.py", line 1, in
print(5/0)
~^~
ZeroDivisionError: division by zero
Истиснои ZeroDivisionError хабар медиҳад, ки тақсим ба сифр рух додааст. Вақте чунин истисно пайдо мешавад, Python бояд донад, ки чӣ гуна ба он ҷавоб диҳад.
Агар чизе нишон надода бошем, барнома қатъ шуда, гузориши хаторо намоиш медиҳад. Вале бо блоки try-except метавонем ба Python гӯем, ки чӣ бояд кард:
try:
print(5/0)
except ZeroDivisionError:
print("Ба сифр тақсим кардан мумкин нест!")
Сатри сабабгори хато — print(5/0)-ро ба блоки try мегузорем. Агар коди дохили try дуруст иҷро шавад, Python аз блоки except мегузарад. Агар хато рӯй диҳад, Python блоки except-еро меҷӯяд, ки ба истиснои пайдошуда мувофиқат мекунад ва коди онро иҷро менамояд.
Дар ин мисол коди дохили try истиснои ZeroDivisionError ба вуҷуд меорад. Python блоки except-и мувофиқро ёфта, онро иҷро мекунад. Корбар ба ҷойи гузориши пайгирии хато паёми фаҳмо мебинад:
Ба сифр тақсим кардан мумкин нест!
Агар баъд аз блоки try-except коди дигар мебуд, барнома иҷроишро идома медод, зеро мо тарзи коркарди хаторо ба Python нишон додем.
Биёед мисолеро бубинем, ки дар он коркарди хато имкон медиҳад барнома корашро идома диҳад.
Истифодаи истисноҳо барои пешгирии қатъ шудани барнома
Коркарди дурусти хатоҳо махсусан вақте муҳим аст, ки барнома пас аз рух додани хато ҳанӯз корҳои дигар дорад. Ин ҳолат дар барномаҳое, ки аз корбар маълумот мепурсанд, зуд-зуд рӯй медиҳад.
Агар барнома ба маълумоти нодуруст дуруст ҷавоб диҳад, метавонад ба ҷойи қатъ шудан, ворид кардани маълумоти дурустро боз дархост кунад.
Биёед ҳисобкунаки одие созем, ки танҳо амали тақсимро иҷро мекунад:
division_calculator.py
print("Ду адад диҳед, ман онҳоро тақсим мекунам.")
print("Барои баромадан 'q'-ро ворид кунед.")
while True:
first_number = input("\nАдади якум: ") # ❶
if first_number == 'q':
break
second_number = input("Адади дуюм: ") # ❷
if second_number == 'q':
break
answer = int(first_number) / int(second_number) # ❸
print(answer)
Барнома аз корбар адади якум — first_number-ро мепурсад ❶. Агар корбар барои баромадан q ворид накунад, адади дуюм — second_number пурсида мешавад ❷. Баъд ин ду ададро тақсим мекунем ❸.
Барнома барои коркарди хатоҳо чорае надорад. Аз ин рӯ, талаби тақсим ба сифр онро аз кор мемонад:
Ду адад диҳед, ман онҳоро тақсим мекунам.
Барои баромадан 'q'-ро ворид кунед.
Адади якум: 5
Адади дуюм: 0
Traceback (most recent call last):
File "division_calculator.py", line 11, in
answer = int(first_number) / int(second_number)
~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
ZeroDivisionError: division by zero
Қатъ шудани барнома мушкил аст, вале нишон додани гузориши пайгирии хато ба корбарон низ кори хуб нест. Корбарони ғайритехникӣ метавонанд онро нафаҳманд.
Дар ҳолатҳои ҳамлаи қасдан, чунин гузориш метавонад ба ҳамлагарон маълумоти зиёдатӣ диҳад. Масалан, онҳо номи файли барнома ва як қисми коди нодуруст коркунандаро мебинанд. Ҳамлагари моҳир баъзан аз ин маълумот барои муайян кардани навъи ҳамла истифода бурда метавонад.
Блоки else
Метавонем сатри эҳтимолан хатодеҳро дар блоки try-except ҷой дода, барномаро устувортар кунем. Хато дар сатри тақсим рух медиҳад, бинобар ин маҳз онро ба try мегузорем.
Дар ин мисол блоки else низ ҳаст. Коде, ки иҷрояш аз муваффақ шудани блоки try вобаста аст, дар else ҷойгир мешавад:
print("Ду адад диҳед, ман онҳоро тақсим мекунам.")
print("Барои баромадан 'q'-ро ворид кунед.")
while True:
first_number = input("\nАдади якум: ")
if first_number == 'q':
break
second_number = input("Адади дуюм: ")
if second_number == 'q':
break
try: # ❶
answer = int(first_number) / int(second_number)
except ZeroDivisionError: # ❷
print("Ба 0 тақсим кардан мумкин нест!")
else: # ❸
print(answer)
Дар блоки try аз Python хоҳиш мекунем амали тақсимро иҷро кунад ❶. Ин блок танҳо коди эҳтимолан хатодеҳро дар бар мегирад.
Кодеро, ки ба муваффақ шудани try вобаста аст, ба else мегузорем. Дар ин ҷо, агар тақсим дуруст анҷом ёбад, натиҷаро дар else чоп мекунем ❸.
Блоки except нишон медиҳад, ки ҳангоми пайдо шудани ZeroDivisionError чӣ бояд кард ❷. Агар тақсим ба сифр рух диҳад, паёми фаҳмое чоп мекунем, то корбар бидонад, ки чӣ гуна аз ин хато пешгирӣ кунад.
Барнома корро идома медиҳад ва корбар гузориши пайгирии хаторо намебинад:
Ду адад диҳед, ман онҳоро тақсим мекунам.
Барои баромадан 'q'-ро ворид кунед.
Адади якум: 5
Адади дуюм: 0
Ба 0 тақсим кардан мумкин нест!
Адади якум: 5
Адади дуюм: 2
2.5
Адади якум: q
Дар блоки try бояд кодеро гузоред, ки эҳтимол дорад истисно ба вуҷуд орад. Баъзан коди иловагӣ доред, ки танҳо пас аз муваффақ шудани try бояд иҷро шавад; чунин код ба else меравад.
Блоки except ба Python мегӯяд, ки ҳангоми пайдо шудани истиснои муайян дар вақти иҷрои try чӣ кор кунад.
Бо пешбинӣ кардани манбаъҳои эҳтимолии хато метавонед барномаҳои устуворе нависед, ки ҳатто ҳангоми рӯ ба рӯ шудан бо додаҳои нодуруст ё захираҳои дастнорас корашонро идома медиҳанд. Коди шумо ба иштибоҳҳои одии корбарон ва баъзе амалҳои қасдан зараровар тобовартар мешавад.
Коркарди истиснои FileNotFoundError
Яке аз мушкилоти маъмули кор бо файлҳо набудани файл аст. Шояд файл дар ҷойи дигар бошад, номаш нодуруст навишта шуда бошад ё умуман вуҷуд надошта бошад.
Ҳамаи ин ҳолатҳоро бо блоки try-except идора карда метавонед.
Биёед кӯшиш кунем файлеро бихонем, ки вуҷуд надорад. Барномаи зерин мехоҳад матни «Алиса дар олами аҷоибот»-ро бихонад, вале ман alice.txt-ро дар ҷузвдони alice.py нигоҳ надоштаам:
alice.py
from pathlib import Path
path = Path('alice.txt')
contents = path.read_text(encoding='utf-8')
Мисли ҳамаи мисолҳои ин боб, encoding='utf-8'-ро менависем. Ин махсусан ҳангоми хондани файле муҳим аст, ки дар системаи шумо сохта нашудааст — масалан, китобе, ки аз интернет боргирӣ кардаед.
Python файли мавҷуднабударо хонда наметавонад, бинобар ин истисно ба вуҷуд меорад:
Traceback (most recent call last):
File "alice.py", line 4, in
contents = path.read_text(encoding='utf-8')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../pathlib.py", line 1056, in read_text
with self.open(mode='r', encoding=encoding, errors=errors) as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/.../pathlib.py", line 1042, in open
return io.open(self, mode, buffering, encoding, errors, newline)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
Ин гузориш аз гузоришҳои пешина дарозтар аст. Биёед бубинем, ки чӣ гуна гузоришҳои мураккабтарро фаҳмидан мумкин аст.
Аксар вақт беҳтар аст аз охири гузориш оғоз кунед. Дар сатри охир мебинем, ки истиснои FileNotFoundError ба вуҷуд омадааст. Ин муҳим аст, зеро нишон медиҳад, ки дар блоки except кадом навъи истисноро истифода барем.
Дар аввали гузориш мебинем, ки хато дар сатри 4-уми файли alice.py рӯй додааст. Сатри баъдӣ худи коди сабабгори хаторо нишон медиҳад.
Қисми боқимонда баъзе кодҳои китобхонаҳоеро нишон медиҳад, ки дар кушодан ва хондани файл иштирок мекунанд. Одатан хондан ё фаҳмидани ҳамаи ин сатрҳо шарт нест.
Барои коркарди хато, сатри дар гузориш мушкилдор эълоншударо ба блоки try мегузорем. Дар мисоли мо ин сатри дорои read_text() аст:
from pathlib import Path
path = Path('alice.txt')
try:
contents = path.read_text(encoding='utf-8')
except FileNotFoundError: # ❶
print(f"Мутаассифона, файли {path} вуҷуд надорад.")
Дар ин мисол коди дохили try истиснои FileNotFoundError ба вуҷуд меорад. Аз ин рӯ, блоки except-еро менависем, ки ба ҳамин хато мувофиқат мекунад ❶.
Ҳангоми ёфт нашудани файл Python коди он блокро иҷро мекунад ва ба ҷойи гузориши пайгирии хато паёми фаҳмо мебинем:
Мутаассифона, файли alice.txt вуҷуд надорад.
Агар файл вуҷуд надошта бошад, барнома дигар коре надорад, бинобар ин натиҷа танҳо ҳамин аст.
Биёед ин мисолро васеъ кунем ва бубинем, ки коркарди истисноҳо ҳангоми кор бо чанд файл чӣ гуна ёрӣ медиҳад.
Таҳлили матн
Метавонед файлҳои матниеро таҳлил кунед, ки китобҳои пурраро дар бар мегиранд. Бисёр асарҳои классикии адабӣ ҳамчун файлҳои одии матнӣ дастрасанд, зеро ба моликияти умумӣ гузаштаанд.
Матнҳои ин бахш аз Project Gutenberg гирифта шудаанд. Ин лоиҳа маҷмуаи асарҳои адабии ба моликияти умумӣ гузаштаро нигоҳ медорад ва барои касоне, ки мехоҳанд дар лоиҳаҳои барномасозиашон бо матнҳои адабӣ кор кунанд, манбаи хуб аст.
Биёед матни «Алиса дар олами аҷоибот»-ро хонда, шумораи калимаҳои онро ҳисоб кунем.
Барои ин методи сатри split()-ро истифода мебарем. Ин метод бо танзими пешфарз сатрро аз ҷойҳое ҷудо мекунад, ки аломатҳои фосилавӣ пайдо мешаванд:
from pathlib import Path
path = Path('alice.txt')
try:
contents = path.read_text(encoding='utf-8')
except FileNotFoundError:
print(f"Мутаассифона, файли {path} вуҷуд надорад.")
else:
# Ҳисоб кардани шумораи тахминии калимаҳои файл:
words = contents.split() # ❶
num_words = len(words) # ❷
print(f"Файли {path} тақрибан {num_words} калима дорад.")
Ман alice.txt-ро ба ҷузвдони дуруст кӯчондам, бинобар ин ин дафъа блоки try кор мекунад.
Сатри contents ҳоло тамоми матни китобро ҳамчун як сатри дароз нигоҳ медорад. Бо split() аз он рӯйхати ҳамаи калимаҳои китобро месозем ❶.
Истифодаи len() барои ин рӯйхат ❷ шумораи тахминии калимаҳои матни аслиро медиҳад. Дар охир паёме чоп мекунем, ки шумораи калимаҳои ёфтшударо нишон медиҳад.
Ин код дар блоки else ҷойгир аст, зеро танҳо баъд аз бомуваффақият иҷро шудани try кор карда метавонад.
Натиҷа шумораи калимаҳои alice.txt-ро нишон медиҳад:
Файли alice.txt тақрибан 29594 калима дорад.
Ин ҳисоб каме зиёдтар аст, зеро файли истифодашуда маълумоти иловагии ноширро низ дар бар мегирад. Вале барои муайян кардани ҳаҷми тахминии китоб мувофиқ аст.
Кор бо чанд файл
Биёед барои таҳлил китобҳои дигарро низ илова кунем. Вале пеш аз он қисми асосии барномаро ба функсияи count_words() мегузаронем. Ин кор таҳлили чанд китобро осон мекунад:
word_count.py
from pathlib import Path
def count_words(path):
"""Шумораи тахминии калимаҳои файлро ҳисоб мекунад.""" # ❶
try:
contents = path.read_text(encoding='utf-8')
except FileNotFoundError:
print(f"Мутаассифона, файли {path} вуҷуд надорад.")
else:
# Ҳисоб кардани шумораи тахминии калимаҳои файл:
words = contents.split()
num_words = len(words)
print(f"Файли {path} тақрибан {num_words} калима дорад.")
path = Path('alice.txt')
count_words(path)
Қисми зиёди код тағйир наёфтааст. Танҳо фосилагузории аввали сатрҳо иваз шуда, код ба танаи count_words() гузаронда шудааст.
Ҳангоми тағйир додани барнома нав кардани шарҳҳо одати хуб аст. Аз ин рӯ, шарҳи пешинаро ба сатри ҳуҷҷатгузорӣ — docstring табдил додем ва ибораашро каме тағйир додем ❶.
Акнун метавонем даври кӯтоҳе нависем, ки калимаҳои ҳар матни дилхоҳро ҳисоб мекунад. Барои ин номҳои файлҳои таҳлилшавандаро дар рӯйхат нигоҳ медорем ва барои ҳар файл count_words()-ро даъват мекунем.
Кӯшиш мекунем калимаҳои китобҳои «Алиса дар олами аҷоибот», «Сиддҳартҳа», «Моби Дик» ва «Занони хурдсол»-ро ҳисоб кунем. Ҳамаи онҳо ба моликияти умумӣ гузаштаанд.
Ман қасдан siddhartha.txt-ро ба ҷузвдони дорои word_count.py нагузоштам, то бубинем барнома набудани файлро чӣ гуна идора мекунад:
from pathlib import Path
def count_words(path):
"""Шумораи тахминии калимаҳои файлро ҳисоб мекунад."""
try:
contents = path.read_text(encoding='utf-8')
except FileNotFoundError:
print(f"Мутаассифона, файли {path} вуҷуд надорад.")
else:
# Ҳисоб кардани шумораи тахминии калимаҳои файл:
words = contents.split()
num_words = len(words)
print(f"Файли {path} тақрибан {num_words} калима дорад.")
filenames = [
'alice.txt',
'siddhartha.txt',
'moby_dick.txt',
'little_women.txt',
]
for filename in filenames:
path = Path(filename) # ❶
count_words(path)
Номҳои файлҳо ҳамчун сатрҳои одӣ нигоҳ дошта шудаанд. Пеш аз даъвати count_words(), ҳар сатр ба объекти Path табдил дода мешавад ❶.
Набудани siddhartha.txt ба иҷрои қисми дигари барнома таъсир намерасонад:
Файли alice.txt тақрибан 29594 калима дорад.
Мутаассифона, файли siddhartha.txt вуҷуд надорад.
Файли moby_dick.txt тақрибан 215864 калима дорад.
Файли little_women.txt тақрибан 189142 калима дорад.
Истифодаи try-except дар ин мисол ду бартарии муҳим дорад. Корбарон гузориши пайгирии хаторо намебинанд ва барнома таҳлили матнҳои дастрасро идома медиҳад.
Агар истиснои FileNotFoundError-и аз набудани siddhartha.txt пайдошударо коркард намекардем, корбар гузориши пурраи хаторо медид ва барнома баъд аз кӯшиши таҳлили «Сиддҳартҳа» қатъ мешуд. «Моби Дик» ва «Занони хурдсол» умуман таҳлил намешуданд.
Бе паём гузаштан аз хато
Дар мисоли пешина ба корбарон хабар додем, ки яке аз файлҳо дастрас нест. Вале хабар додан дар бораи ҳар истиснои коркардшуда шарт нест.
Баъзан мехоҳед, ки ҳангоми пайдо шудани истисно барнома чизе нагӯяд ва корашро идома диҳад.
Барои ин блоки try-ро мисли ҳамеша менависед, вале дар except ошкоро нишон медиҳед, ки Python ҳеҷ коре накунад. Python дастури pass дорад, ки маънояш «дар ин блок ҳеҷ кор накун» аст:
def count_words(path):
"""Шумораи тахминии калимаҳои файлро ҳисоб мекунад."""
try:
contents = path.read_text(encoding='utf-8')
except FileNotFoundError:
pass
else:
words = contents.split()
num_words = len(words)
print(f"Файли {path} тақрибан {num_words} калима дорад.")
Ягона тағйири мантиқӣ нисбат ба мисоли пешина истифодаи pass дар блоки except аст.
Акнун, вақте FileNotFoundError ба вуҷуд меояд, блоки except иҷро мешавад, вале ҳеҷ амале анҷом намеёбад. Гузориши пайгирии хато ё паёми дигаре нишон дода намешавад.
Корбарон шумораи калимаҳои файлҳои мавҷударо мебинанд, вале нишонае аз ёфт нашудани файл намебинанд:
Файли alice.txt тақрибан 29594 калима дорад.
Файли moby_dick.txt тақрибан 215864 калима дорад.
Файли little_women.txt тақрибан 189142 калима дорад.
Дастури pass ҳамчунин метавонад ҳамчун ҷойнигоҳдор истифода шавад. Он хотиррасон мекунад, ки шумо дар ин нуқтаи иҷрои барнома қасдан коре намекунед ва шояд баъдтар амале илова кардан хоҳед.
Масалан, дар ин барнома метавонем қарор диҳем, ки номҳои файлҳои ёфтнашударо ба missing_files.txt нависем. Корбарон ин файлро намебинанд, вале мо метавонем онро хонда, масъалаи матнҳои гумшударо ҳал кунем.
Муайян кардани хатоҳои қобили гузориш
Чӣ гуна фаҳмидан мумкин аст, ки кай ба корбар дар бораи хато хабар диҳем ва кай барнома бе паём корашро идома диҳад?
Агар корбарон донанд, ки кадом матнҳо бояд таҳлил шаванд, паёме, ки сабаби таҳлил нашудани баъзе матнҳоро мефаҳмонад, барояшон муфид мешавад.
Агар онҳо танҳо натиҷаро интизор бошанд ва надонанд, ки кадом китобҳо бояд таҳлил шаванд, шояд донистани дастнорас будани баъзе матнҳо лозим набошад.
Додани маълумоте, ки корбар намеҷӯяд, метавонад истифодаи барномаро душвортар кунад. Сохторҳои коркарди хатои Python ба шумо имкон медиҳанд дақиқ назорат кунед, ки ҳангоми мушкилот чӣ қадар маълумот ба корбар нишон дода шавад. Интихоби ҳаҷми маълумот ба шумо вобаста аст.
Коди хубнавишташуда ва дуруст санҷидашуда ба хатоҳои дохилӣ, масалан хатоҳои наҳвӣ ё мантиқӣ, камтар дучор мешавад. Вале ҳар гоҳ барнома ба чизи беруна вобаста бошад — ба маълумоти воридкардаи корбар, мавҷудияти файл ё дастрасии шабака — эҳтимоли пайдо шудани истисно ҳаст.
Бо пайдо кардани таҷриба мефаҳмед, ки дар кадом ҷойҳои барнома блокҳои коркарди истисноро гузоред ва дар бораи хатоҳо ба корбар чӣ қадар маълумот диҳед.
Худатон бисанҷед
10-6. Ҷамъ. Яке аз мушкилоти маъмули дархости адад аз корбар он аст, ки одамон ба ҷойи адад матн ворид мекунанд. Ҳангоми кӯшиши табдил додани чунин матн ба int, истиснои ValueError мегиред.
Барномае нависед, ки ду ададро мепурсад, онҳоро ҷамъ мекунад ва натиҷаро чоп менамояд. Агар яке аз қиматҳои воридшуда адад набошад, ValueError-ро коркард карда, паёми фаҳмо чоп кунед.
Барномаро аввал бо ду адад ва баъд бо ворид кардани матн ба ҷойи яке аз ададҳо санҷед.
10-7. Ҳисобкунаки ҷамъ. Коди машқи 10-6-ро дар даври while ҷой диҳед, то корбар ҳатто баъд аз иштибоҳан ворид кардани матн низ тавонад ворид кардани ададҳоро идома диҳад.
10-8. Гурбаҳо ва сагҳо. Ду файл — cats.txt ва dogs.txt созед. Дар файли аввал камаш се номи гурба ва дар дуюм се номи саг нигоҳ доред.
Барномае нависед, ки кӯшиш мекунад ин файлҳоро хонда, муҳтавояшонро дар экран чоп кунад. Кодро дар блоки try-except ҷой диҳед, то FileNotFoundError коркард шавад ва ҳангоми набудани файл паёми фаҳмо чоп гардад.
Яке аз файлҳоро ба ҷойи дигари система кӯчонед ва боварӣ ҳосил кунед, ки блоки except дуруст иҷро мешавад.
10-9. Гурбаҳо ва сагҳои хомӯш. Блоки except-и машқи 10-8-ро тағйир диҳед, то агар яке аз файлҳо набошад, барнома бе нишон додани паём корашро идома диҳад.
10-10. Калимаҳои маъмул. Ба Project Gutenberg рафта, чанд матнеро интихоб кунед, ки мехоҳед таҳлил намоед. Файлҳои матнии онҳоро боргирӣ кунед ё матни одиро аз браузер ба файли матнии компютер нусхабардорӣ намоед.
Методи count() имкон медиҳад муайян кунед, ки калима ё ибора дар як сатр чанд маротиба пайдо мешавад. Масалан, коди зерин шумораи пайдоиши row-ро ҳисоб мекунад:
>>> line = "Row, row, row your boat"
>>> line.count('row')
2
>>> line.lower().count('row')
3
Аҳамият диҳед, ки табдил додани сатр ба ҳарфҳои хурд бо lower() имкон медиҳад ҳамаи пайдоишҳои калима, новобаста аз калон ё хурд будани ҳарфҳояш, ҳисоб шаванд.
Барномае нависед, ки файлҳои аз Project Gutenberg гирифтаатонро мехонад ва муайян мекунад, ки калимаи 'the' дар ҳар матн чанд маротиба пайдо мешавад.
Натиҷа тахминӣ мешавад, зеро калимаҳои монанди 'then' ва 'there' низ ҳисоб мешаванд. Кӯшиш кунед 'the '-ро бо як фосила дар охираш ҳисоб кунед ва бубинед, ки натиҷа чӣ қадар камтар мешавад.
Нигоҳдории додаҳо
Бисёре аз барномаҳои шумо аз корбарон маълумоти муайянеро мепурсанд. Шояд дар бозӣ ба корбар иҷозат диҳед танзимоти дилхоҳашро нигоҳ дорад ё барои тасвирсозии додаҳо маълумот пешниҳод кунад.
Ҳадафи барнома ҳар чӣ бошад ҳам, маълумоти корбарро дар сохторҳои додаҳо, масалан рӯйхатҳо ва луғатҳо, нигоҳ медоред.
Вақте корбар барномаро мепӯшад, қариб ҳамеша мехоҳед маълумоти воридкардаи ӯро нигоҳ доред. Яке аз роҳҳои одии ин кор истифодаи модули json аст.
Модули json имкон медиҳад сохторҳои одии додаҳои Python-ро ба сатрҳои дорои қолаби JSON табдил диҳед. Баъд метавонед онҳоро дар файл нигоҳ дошта, ҳангоми иҷрои навбатии барнома дубора бор кунед.
Ҳамчунин json-ро барои мубодилаи додаҳо байни барномаҳои гуногуни Python истифода бурдан мумкин аст.
Бартарии дигар ин аст, ки қолаби JSON танҳо ба Python тааллуқ надорад. Аз ин рӯ, додаҳои дар JSON нигоҳдоштаро бо одамоне мубодила карда метавонед, ки бо забонҳои дигари барномасозӣ кор мекунанд. Ин қолаби муфид ва байни забонҳо интиқолпазир буда, омӯхтанаш осон аст.
Эзоҳ: Қолаби JSON — кӯтоҳшудаи JavaScript Object Notation, яъне «тарзи навишти объектҳои JavaScript» — дар ибтидо барои JavaScript таҳия шуда буд. Вале баъдтар ба қолаби маъмули бисёр забонҳо, аз ҷумла Python, табдил ёфт.
Истифодаи json.dumps() ва json.loads()
Биёед барномаи кӯтоҳе нависем, ки маҷмуаи ададҳоро нигоҳ медорад ва барномаи дигаре созем, ки онҳоро дубора ба хотира мехонад.
Барномаи аввал барои табдил додани ададҳо json.dumps() ва барномаи дуюм барои барқарор кардани онҳо json.loads()-ро истифода мебарад.
Функсияи json.dumps() як аргумент мегирад: додаҳое, ки бояд ба қолаби JSON табдил дода шаванд. Функсия сатри матниро бармегардонад, ки баъд метавонем онро ба файл нависем:
number_writer.py
from pathlib import Path
import json
numbers = [2, 3, 5, 7, 11, 13]
path = Path('numbers.json') # ❶
contents = json.dumps(numbers) # ❷
path.write_text(contents, encoding='utf-8')
Аввал модули json-ро ворид мекунем ва рӯйхати ададҳоро месозем. Баъд номи файлеро интихоб мекунем, ки рӯйхат дар он нигоҳ дошта мешавад ❶.
Одатан пасванди .json-ро истифода мебаранд, то нишон диҳанд, ки додаҳои файл дар қолаби JSON нигоҳ дошта шудаанд.
Сипас бо json.dumps() ❷ сатре месозем, ки додаҳоямонро дар қолаби JSON ифода мекунад. Баъд онро бо ҳамон методи write_text(), ки пештар истифода бурдем, ба файл менависем.
Барнома чизе чоп намекунад. Вале агар numbers.json-ро кушоем, додаҳоро дар шакле мебинем, ки ба навишти Python монанд аст:
[2, 3, 5, 7, 11, 13]
Акнун барномаи алоҳидае менависем, ки бо json.loads() рӯйхатро дубора ба хотира мехонад:
number_reader.py
from pathlib import Path
import json
path = Path('numbers.json') # ❶
contents = path.read_text(encoding='utf-8') # ❷
numbers = json.loads(contents) # ❸
print(numbers)
Боварӣ ҳосил мекунем, ки ҳамон файлеро мехонем, ки пештар ба он навишта будем ❶. Азбаски файли додаҳо танҳо файли матнии дорои қолаббандии муайян аст, онро бо read_text() хонда метавонем ❷.
Баъд муҳтавои файлро ба json.loads() медиҳем ❸. Ин функсия сатри дорои қолаби JSON-ро қабул карда, объекти Python-ро бармегардонад. Дар ин ҳолат объект рӯйхат аст ва онро ба numbers нисбат медиҳем.
Дар охир рӯйхати барқароршударо чоп мекунем ва мебинем, ки он ҳамон рӯйхати дар number_writer.py сохташуда аст:
[2, 3, 5, 7, 11, 13]
Ин роҳи одии мубодилаи додаҳо байни ду барнома аст.
Нигоҳдорӣ ва хондани додаҳои воридкардаи корбар
Нигоҳдории додаҳо бо json ҳангоми кор бо маълумоти корбар муфид аст. Агар маълумоти ӯро ба ягон тарз нигоҳ надоред, пас аз қатъ шудани барнома онро гум мекунед.
Биёед мисолеро баррасӣ кунем, ки ҳангоми иҷрои аввал номи корбарро мепурсад ва дар иҷроҳои баъдӣ онро дар хотир нигоҳ медорад.
Аввал номи корбарро нигоҳ медорем:
remember_me.py
from pathlib import Path
import json
username = input("Номи шумо чист? ") # ❶
path = Path('username.json') # ❷
contents = json.dumps(username)
path.write_text(contents, encoding='utf-8')
print(f"Вақте бармегардед, шуморо дар хотир дорем, {username}!") # ❸
Аввал номи корбарро мепурсем ❶. Баъд маълумоти гирифташударо ба username.json менависем ❷. Сипас паёме чоп мекунем, ки нигоҳ дошта шудани маълумотро хабар медиҳад ❸:
Номи шумо чист? Eric
Вақте бармегардед, шуморо дар хотир дорем, Eric!
Акнун барномаи наве менависем, ки ба корбари номаш аллакай нигоҳдошташуда салом медиҳад:
greet_user.py
from pathlib import Path
import json
path = Path('username.json') # ❶
contents = path.read_text(encoding='utf-8')
username = json.loads(contents) # ❷
print(f"Хуш омадед боз, {username}!")
Муҳтавои файли додаҳоро мехонем ❶ ва баъд бо json.loads() додаҳои барқароршударо ба тағйирёбандаи username нисбат медиҳем ❷.
Азбаски номи корбарро барқарор кардем, метавонем ӯро бо номаш истиқбол гирем:
Хуш омадед боз, Eric!
Бояд ин ду барномаро дар як файл муттаҳид кунем. Вақте касе remember_me.py-ро иҷро мекунад, мехоҳем, агар имкон бошад, номи пештар нигоҳдоштаи ӯро бихонем. Дар акси ҳол, номашро пурсида, барои дафъаи оянда дар username.json нигоҳ медорем.
Метавонистем барои ҳолати набудани username.json блоки try-except нависем. Вале ба ҷойи он аз методи қулайи модули pathlib истифода мебарем:
remember_me.py
from pathlib import Path
import json
path = Path('username.json')
if path.exists(): # ❶
contents = path.read_text(encoding='utf-8')
username = json.loads(contents)
print(f"Хуш омадед боз, {username}!")
else: # ❷
username = input("Номи шумо чист? ")
contents = json.dumps(username)
path.write_text(contents, encoding='utf-8')
print(f"Вақте бармегардед, шуморо дар хотир дорем, {username}!")
Барои объектҳои Path методҳои муфиди зиёде мавҷуданд. Методи exists() агар файл ё ҷузвдон вуҷуд дошта бошад, True ва агар вуҷуд надошта бошад, False бармегардонад.
Дар ин ҷо бо path.exists() месанҷем, ки оё номи корбар аллакай нигоҳ дошта шудааст ё не ❶. Агар username.json вуҷуд дошта бошад, номи корбарро мехонем ва ӯро бо номаш истиқбол мегирем.
Агар username.json вуҷуд надошта бошад ❷, номи корбарро мепурсем ва қимати воридкардаашро нигоҳ медорем. Ҳамчунин паёми шиносро чоп мекунем, ки ҳангоми бозгашт ӯро дар хотир хоҳем дошт.
Кадом блоке иҷро шавад ҳам, дар натиҷа номи корбар ва паёми мувофиқ дорем.
Агар барнома бори аввал иҷро шавад, натиҷа чунин аст:
Номи шумо чист? Eric
Вақте бармегардед, шуморо дар хотир дорем, Eric!
Дар акси ҳол:
Хуш омадед боз, Eric!
Ин натиҷаест, ки баъд аз камаш як бор иҷро шудани барнома мебинед.
Гарчанде додаҳои ин бахш танҳо як сатри матнӣ ҳастанд, ҳамин равиш барои ҳар додае кор мекунад, ки ба сатри дорои қолаби JSON табдил додан мумкин аст.
Бозсозии сохтори код — рефакторинг
Аксар вақт ба нуқтае мерасед, ки код кор мекунад, вале мебинед, ки онро бо тақсим кардан ба чанд функсияи дорои вазифаҳои мушаххас беҳтар кардан мумкин аст.
Ин равандро рефакторинг меноманд. Рефакторинг кодро тозатар, фаҳмотар ва барои васеъ кардан осонтар мекунад.
Метавонем қисми асосии мантиқи remember_me.py-ро ба як ё чанд функсия гузаронем.
Ҳадафи асосии remember_me.py салом додан ба корбар аст. Пас биёед тамоми коди мавҷударо ба функсияи greet_user() гузорем:
remember_me.py
from pathlib import Path
import json
def greet_user():
"""Ба корбар бо номаш салом медиҳад.""" # ❶
path = Path('username.json')
if path.exists():
contents = path.read_text(encoding='utf-8')
username = json.loads(contents)
print(f"Хуш омадед боз, {username}!")
else:
username = input("Номи шумо чист? ")
contents = json.dumps(username)
path.write_text(contents, encoding='utf-8')
print(f"Вақте бармегардед, шуморо дар хотир дорем, {username}!")
greet_user()
Азбаски акнун функсия истифода мебарем, тавзеҳи корро ҳамчун docstring менависем, то кори ҷории барномаро ифода кунад ❶.
Файл каме мураттабтар шуд, вале greet_user() ғайр аз салом додан корҳои дигар низ мекунад: агар номи нигоҳдошташуда бошад, онро мехонад ва агар набошад, номи нав мепурсад.
Биёед greet_user()-ро бозсозӣ кунем, то вазифаҳои гуногуни зиёдро иҷро накунад. Аввал коди хондани номи нигоҳдошташударо ба функсияи алоҳида мегузаронем:
from pathlib import Path
import json
def get_stored_username(path):
"""Агар номи нигоҳдошташуда бошад, онро мегирад.""" # ❶
if path.exists():
contents = path.read_text(encoding='utf-8')
username = json.loads(contents)
return username
else:
return None # ❷
def greet_user():
"""Ба корбар бо номаш салом медиҳад."""
path = Path('username.json')
username = get_stored_username(path)
if username: # ❸
print(f"Хуш омадед боз, {username}!")
else:
username = input("Номи шумо чист? ")
contents = json.dumps(username)
path.write_text(contents, encoding='utf-8')
print(f"Вақте бармегардед, шуморо дар хотир дорем, {username}!")
greet_user()
Функсияи нави get_stored_username() ❶ мақсади равшан дорад, ки дар docstring навишта шудааст. Он номи нигоҳдошташударо мехонад ва агар ёбад, онро бармегардонад.
Агар роҳи ба get_stored_username() додашуда вуҷуд надошта бошад, функсия None бармегардонад ❷.
Барои чунин функсия ин равиши хуб аст: ё қимати интизоршударо баргардонад, ё ҳангоми дастрас набудани он None диҳад. Ин имкон медиҳад натиҷаи баргардондаи функсияро бо санҷиши одӣ баррасӣ кунем.
Агар гирифтани номи корбар муваффақ шавад, паёми истиқболро чоп мекунем ❸. Агар не, номи нав мепурсем.
Бояд боз як қисми кодро аз greet_user() ҷудо кунем. Агар номи корбар вуҷуд надошта бошад, коди пурсидани номи навро ба функсияи махсуси ҳамин вазифа мегузаронем:
from pathlib import Path
import json
def get_stored_username(path):
"""Агар номи нигоҳдошташуда бошад, онро мегирад."""
if path.exists():
contents = path.read_text(encoding='utf-8')
username = json.loads(contents)
return username
else:
return None
def get_new_username(path):
"""Номи корбари навро мепурсад."""
username = input("Номи шумо чист? ")
contents = json.dumps(username)
path.write_text(contents, encoding='utf-8')
return username
def greet_user():
"""Ба корбар бо номаш салом медиҳад."""
path = Path('username.json')
username = get_stored_username(path) # ❶
if username:
print(f"Хуш омадед боз, {username}!")
else:
username = get_new_username(path) # ❷
print(f"Вақте бармегардед, шуморо дар хотир дорем, {username}!")
greet_user()
Ҳар функсия дар ин шакли ниҳоии remember_me.py як вазифаи равшан дорад.
Мо greet_user()-ро даъват мекунем ва он паёми мувофиқро чоп мекунад: ё корбари пешинаро истиқбол мегирад, ё ба корбари нав салом медиҳад.
Барои ин get_stored_username()-ро даъват мекунад ❶, ки танҳо барои гирифтани номи пештар нигоҳдошташуда масъул аст.
Агар лозим шавад, greet_user() функсияи get_new_username()-ро даъват мекунад ❷. Он танҳо номи навро мегирад ва нигоҳ медорад.
Чунин тақсим кардани вазифаҳо қисми муҳими навиштани коди равшан аст, ки нигоҳдорӣ ва васеъ кардани он осон мешавад.
Худатон бисанҷед
10-11. Адади дӯстдошта. Барномае нависед, ки адади дӯстдоштаи корбарро мепурсад. Бо json.dumps() онро дар файл нигоҳ доред.
Барномаи алоҳидае нависед, ки ин қиматро мехонад ва чунин паёмро чоп мекунад:
«Ман адади дӯстдоштаи шуморо медонам! Он _____ аст.»
10-12. Дар хотир нигоҳ доштани адади дӯстдошта. Ду барномаи машқи 10-11-ро дар як файл муттаҳид кунед.
Агар адад аллакай нигоҳ дошта шуда бошад, онро ба корбар хабар диҳед. Агар не, адади дӯстдоштаро пурсида, дар файл нигоҳ доред.
Барномаро ду бор иҷро кунед, то дуруст кор кардани онро бинед.
10-13. Луғати корбар. Мисоли remember_me.py танҳо як маълумот — номи корбарро нигоҳ медорад.
Онро васеъ карда, боз ду маълумоти дигарро дар бораи корбар пурсед. Баъд ҳамаи маълумоти гирифташударо дар луғат нигоҳ доред.
Ин луғатро бо json.dumps() ба файл нависед ва бо json.loads() дубора бихонед. Гузориши кӯтоҳе чоп кунед, ки дақиқ нишон диҳад барнома дар бораи корбар чиро дар хотир дорад.
10-14. Санҷиши корбар. Шакли ниҳоии remember_me.py чунин фарз мекунад, ки ё корбар қаблан номашро ворид кардааст, ё барнома бори аввал иҷро мешавад.
Бояд онро барои ҳолате низ тағйир диҳем, ки корбари ҷорӣ аз шахси охирини истифодакунандаи барнома фарқ мекунад.
Пеш аз чоп кардани паёми истиқбол дар greet_user(), аз корбар пурсед, ки оё номи нишон додашуда дуруст аст. Агар не, get_new_username()-ро даъват кунед, то номи дурустро гиред.
Хулоса
Дар ин боб кор бо файлҳоро омӯхтед. Фаҳмидед, ки чӣ гуна тамоми муҳтавои файлро хонед ва агар лозим бошад, онро сатр ба сатр коркард кунед. Ҳамчунин навиштани матни дилхоҳҳаҷмро ба файл омӯхтед.
Бо истисноҳо ва роҳҳои коркарди истисноҳое шинос шудед, ки эҳтимол дар барномаҳоятон рӯй медиҳанд.
Дар охир тарзи нигоҳдории сохторҳои додаҳои Python-ро омӯхтед, то маълумоти корбаронро ҳифз кунед ва онҳо маҷбур нашаванд ҳар дафъа ҳангоми иҷрои барнома ҳама чизро аз нав оғоз кунанд.
Дар боби 11 роҳҳои самараноки санҷидани кодро меомӯзед. Ин ба шумо боварӣ медиҳад, ки коди таҳиякардаатон дуруст аст ва ёрӣ мерасонад хатоҳоеро пайдо кунед, ки ҳангоми васеъ кардани барномаҳо ба вуҷуд меоянд.

Барномасозӣ
Олами Афсонаҳо
Ахбор
Саломатӣ
Дунё