Formatlaşdırmanın köhnə üsulu

Bildiyiniz kimi, Guido van Rossum Python dilini meydana gətirərkən C dilindən də müəyyən sintaksis konstruksiyaları götürmüşdür. C dilində isə sırf formatlı çıxışlar üçün nəzərdə tutulan xüsusi printf()sprintf() kimi funksiyalar vardır. Python dilinə həmin funksiyalar keçməsə də, onların funksionallığını təmin edən % (modul) operatorundan adi print() funksiyası daxilində istifadə etmək mümkündür. Modul (riyazi modul ilə qarışdırmayın) operatoruna çox vaxt sətir modulu və ya sətir interpolyasiyası da deyilir.
Aşağıdakı sxem sətir modulu operatorunun necə işlədiyini göstərir:

Yuxarıdakı yazılışdan da gördüyünüz kimi, print() funksiyasına bütöv olaraq ötürülən parametr əslində üç hissədən ibarətdir:

Burada qiymətlər kortejinin elementləri literal, dəyişən və ya ixtiyari riyazi ifadədən ibarət ola bilər. Kortejin elementləri placeholders (yerləşdirmə göstəriciləri) vasitəsilə sətir formatında öz yerlərinə qoyulur. Bizim nümunədə iki (%5d%8.2f) placeholder var.
Placeholderin yazılışının ümumi sintaksisi aşağıdakı kimidir:

%[bayraqlar][genişlik][.dəqiqlik]tip

Burada bayraqlar bəzi konversiya (çevrilmə) tiplərinin nəticəsinə təsir edən parametrlərdir. Bu konversiya parametrlərinin istifadəsi opsionaldır (istəyə bağlıdır). Aşağıdakı cədvəldə onlarla tanış ola bilərsiniz:

BayraqTəyinatı
#o, x və ya X spesifikatorları ilə istifadə edildiyi zaman çıxış qiymətlərinin önünə müvafiq olaraq 0, 0o, 0O, 0x və ya 0X simvolları əlavə edilir.
0Ədədi qiymətlər üçün konversiya nəticəsi ön məsafəsiz çıxır.
Konversiya nəticələri soldan nizamlanır.
+Ədədi qiymətlərdə istifadə edildiyi zaman onların işarəsi (“+” və ya “-“) konversiya nəticəsinin önündə göstərilir.
boşluqBayraq olaraq boşluq (probel) yazıldıqda müsbət çıxış qiymətlərinin önünə boşluq (probel) qoyulur.

Placeholderin yazılışında göstərilən genişlik ədədi qiymətlərdə çıxış veriləni üçün soldan sağa ayrılmış xanaların ümumi sayıdır. Əgər çıxış veriləni həqiqi ədəddirsə, vergüldən sonrakı rəqəmlərinin sayını bildirmək üçün dəqiqlik də göstərilməlidir:

Əgər çıxış qiymətində vergüldən sonrakı rəqəmlərin sayı onun üçün qeyd olunan dəqiqlikdən çoxdursa, yuvarlaqlaşdırma, azdırsa, sıfırlarla tamamlama baş verəcək.
Aşağıdakı cədvəldə isə placeholderdə göstərilə bilən tiplər verilmişdir:

KonversiyaTəyinatı
dÇıxışa işarəli onluq tam ədəd çıxarır.
iÇıxışa işarəli onluq tam ədəd çıxarır.
uÇıxışa işarəsiz onluq tam ədəd çıxarır.
oÇıxışa işarəsiz səkkizlik ədəd çıxarır.
xÇıxışa işarəsiz onaltılıq ədəd çıxarır (aşağı registr).
XÇıxışa işarəsiz onaltılıq ədəd çıxarır (yuxarı registr).
eÇıxışa eksponensial formatda həqiqi ədəd çıxarır (aşağı registr).
EÇıxışa eksponensial formatda həqiqi ədəd çıxarır (yuxarı registr).
fÇıxışa onluq həqiqi ədəd çıxarır.
FÇıxışa onluq həqiqi ədəd çıxarır.
gEksponent -4-dən böyük və ya dəqiqlikdən kiçik olduqda e,əks halda, f konversiyası ilə eynidir.
GEksponent -4-dən böyük və ya dəqiqlikdən kiçik olduqda E,əks halda, F konversiyası ilə eynidir.
cÇıxışa tək simvol çıxarır.
rÇıxışa sətir çıxarır. (istənilən Python obyektini repr() funksiyası ilə çevirir).
sÇıxışa sətir çıxarır (istənilən Python obyektini str() funksiyası ilə çevirir).
aÇıxışa sətir çıxarır (istənilən Python obyektini ascii() funksiyası ilə çevirir).
%Çıxışa yalnız % simvolunu çıxarır.

İndi isə gəlin bizim misaldakı placeholderləri nəzərdən keçirək:

>>> print("Məhsul kod:%5d, qiymət:%8.2f" % (254, 65.076))
Məhsul kod:  254, qiymət:   65.08
>>>

Burada birinci olan %5d placeholderi kortejin ilk elementi olan 254 qiymətini sətir formatında öz yerinə yerləşdirir. Bu zaman çıxış veriləni üçün beş xanalıq yer ayrılır və o işarəli onluq tam ədəd şəklində konversiya olunur. Diqqət edin ki, çıxış veriləni üçün beş yer ayrıldığı halda onun özü üç rəqəmlidir. Məhz buna görə də, bu qiymət çıxışa önündə iki boşluqla gəlir.
Misalda ikinci olan %8.2f placeholderinə gəlincə isə görmək olar ki, o 65.076 qiymətini onluq həqiqi ədəd şəklində konversiya edir. Çıxış veriləni üçün ümumilikdə səkkiz, vergüldən sonrakı rəqəmlər üçün (dəqiqlik) iki xanalıq yer ayrılır. Dəqiqlik üçün ayrılan xanaların sayı bir vahid az olduğuna görə çıxışda ədəd bir mövqe yuvarlaqlaşdırılır.
Aşağıda verilmiş digər nümunələri də nəzərdən keçirin:

>>> print("%10.3e"% (425.07875))
     4.251e+02
>>> print("%10o"% (17))
            21
>>> print("%5.4X"% (54))
     0036
>>> print("%c"% ('A'))
A
>>> print("%s"% ('alma'))
alma
>>> print("Yalnız faiz simvolu: %%" % ())
Yalnız faiz simvolu: %
>>>
>>> print("%#5X"% (78))
     0X4E
>>> print("%#5o"% (33))
     0o41
>>> print("%+d"% (47))
+47
>>> print("%0d"% (42))
42
>>> print("%-5d"% (86))
86   
>>> print("% d"% (27))
     27
>>>

İlk baxışdan elə görünsə də, əslində formatlaşdırma print() funksiyasının bir parçası deyildir. Yazdığımız misallara diqqətlə nəzər yetirsəniz, görəcəksiniz ki, bütün hallarda print() funksiyasına ötürülən parametr sətir modulu (%) operatoru ilə formatlaşdırılan sətirdir. Köhnə üsulla çıxışları formatlaşdırarkən biz aşağıdakı ardıcıllıqdan da istifadə edə bilərdik:

>>> s = "Məhsul kod:%5d, qiymət:%8.2f" % (254, 65.076)
>>> print(s)
Məhsul kod:  254, qiymət:   65.08
>>>

Çıxışların formatlaşdırılması

Çıxışların formatlaşdırılması, başqa sözlə, çıxış verilənlərinin istifadəçilərə formatlı şəkildə təqdim edilməsi proqramlaşdırmada ən vacib məsələlərdən biridir. Biz bu dərsimizdə Python dilində çıxışların formatlaşdırılmasının müxtəlif üsullarından bəhs edəcəyik. Bununla belə sizə məsləhət görəcəyimiz üsul string sinfinin format metodudur. Bu üsul həm olduqca çevikdir, həm də Python dilinin fəlsəfəsinə uyğun gəlir. Gəlin tələsməyək və bütün üsulları bir-bir nəzərdən keçirək.

Biz indiyə qədər çıxış verilənlərini ekrana primitiv üsullarla çıxarırdıq. Ekrana çıxarılan məlumatlar birdən çox olduqda onları bir-birindən ayırmaq lazımdır. Bunun da ən sadə yolu ya print() funksiyasının sep parametrindən (ayırıcı) istifadə, ya da sətirləri konkatenasiya (birləşdirilmə) etməkdən ibarətdir.

Adi qaydada print() funksiyasında sep parametri yazılmır və interpretator onun qiymətini default olaraq boşluq qəbul edir. Bu zaman funksiyanın bir-birindən vergüllə ayrılan arqumentləri ekrana çıxarılanda aralarında boşluq olur:

>>> a = 78
>>> b = 0.19
>>> print(a, b, a * b) 
78 0.19 14.82
>>>

Zərurət olduqda biz sep parametrindən yararlanaraq onu ixtiyari qiymətlərlə təyin edə bilərik:

>>> a = 78
>>> b = 0.19
>>> print(a, b, a * b, sep = ',') 
78,0.19,14.82
>>> print(a, b, a * b, sep = '---') 
78---0.19---14.82
>>>

Aşağıdakı proqramda isə çıxışları formatlaşdırmaq üçün sətirlərin konkatenasiyasından istifadə olunur:

>>> a = 78
>>> b = 0.19
>>> print(str(a)+ " " +str(b)+" " +str(a * b)) 
78 0.19 14.82
>>>

Yuxarıda sadalanan bu üsullar nə qədər sadə olsa da, peşəkarlıq baxımından qənaətbəxş deyil.

Ədəd tipləri

Python proqramlaşdırma dilində üç müxtəlif ədəd tipi var: tam (int), həqiqi (float) və kompleks (complex). int və float tipləri ilə siz artıq tanışsınız. Bunlarla bağlı bir neçə məqamı qeyd etdikdən sonra complex tipindən də danışacağıq.

int

int tam ədəd tipində ədədlər istənilən uzunluqda ola bilər. Daha doğrusu, int tipindəki ədədin uzunluğu kompüterin əməli yaddaşının verdiyi imkanla məhdudlaşır. Adi insanlar gündəlik həyatda onluq say sistemindəki ədədlərlə işləyir, amma proqramçılara həm də ikilik, səkkizlikonaltılıq ədədlər lazım olur. Python dilində önlərinə müvafiq prefikslər qoymaqla bu ədədləri təsvir etmək mümkündür:

Say sistemiPrefiks
ikilik (binary)0b və ya 0B
səkkizlik (octal)0o və ya 0O
onaltılıq (hexadecimal)0x və ya 0X

İnterpretator prefikslərin köməyilə təsvir etdiyimiz ikilik, səkkizlikonaltılıq ədədləri onluq say sistemində göstərəcək:

>>> 0b1101011 
107
>>> 0xFB + 0b10 
253
>>> 0o15 
13
>>>

Müxtəlif say sistemlərində olan ədədləri onluq sistemə çevirmək üçün iki parametrli int(x, b) funksiyasından istifadə olunur. Burada x digər say sistemində olan ədəddir və dırnaq arasında göstərilməlidir. İkinci parametr olan b isə verilmiş ədədin hansı say sistemində olduğunu bildirmək üçündür. Burada say sisteminin əsası kimi [2…36] aralığında qiymət göstərə bilərik:

>>> int("1001", 2) 
9
>>> int("15", 8) 
13
>>> int("0xFB", 16) 
251
>>>

Onluq say sistemindəki bir ədədi ikilik, səkkizlikonaltılıq sistemə çevirmək üçün müvafiq olaraq bin(x), oct(x)hex(x) funksiyalarından istifadə olunur. Burada x onluq say sistemindəki ədəddir:

>>> bin(9) 
'0b1001' 
>>> oct(13) 
'0o15'
>>> hex(251) 
'0xfb'
>>>

float

Python dilində həqiqi ədədlərlə işləmək üçün float tipi nəzərdə tutulmuşdur. Bu tipin qiymət aralığı aşağıdakı kimi təyin edilmişdir:

[2.2250738585072020𝑥10-308 . . . 1.7976931348623157𝑥10308]

Bu sərhədlər pozulduqda interpretator xəta mesajı verir:

>>> a = 3 ** 1000
>>> a + 0.1
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module> 
    a + 0.1
OverflowError: int too large to convert to float 
>>>

Onu da qeyd etmək lazımdır ki, float tipində verilən ədədlər vergüldən sonra 15 işarə dəqiqliyində ola bilir (16-cı mövqe qeyri-dəqiqdir):

>>> 1.1234567890123456789 
1.1234567890123457
>>>

Hesablamalarda daha yüksək dəqiqlik tələb olunursa, decimal moduluna müraciət etmək lazımdır.
Python proqramlaşdırma dilində həqiqi ədədlər adi qaydadan başqa, eksponensial formatda da təsvir oluna bilər. Bu zaman eksponent E və ya e simvolları ilə verilir. Eksponensial formatda təsvir edilən həqiqi ədədi interpretator adi qaydada göstərəcək:

>>> 123.45 
123.45
>>> 1.2345e2 
123.45
>>> 5.45E-2 
0.0545
>>>

Sonda onu da qeyd edək ki, rasional ədədlər ilə bağlı hesablamalar üçün Python dilində ayrıca fractions modulu nəzərdə tutulmuşdur.

complex

Python proqramlaşdırma dilində kompleks ədədlərlə işləmək üçün complex adlı xüsusi bir tip nəzərdə tutulmuşdur. Bildiyiniz kimi, kompleks ədədlər iki hissədən ibarətdir: həqiqixəyali. Kompleks ədədlər a+bj şəklində göstərilir. Burada a həqiqi hissə, b isə xəyali hissənin əmsalıdır və hər ikisi ədəd (int, float və həmçinin complex) tipində qiymət və ya dəyişən ola bilər.

Buradakı j (və ya J) isə √-1 xəyali ədədinin özünü bildirən xüsusi simvoldur:

>>> 3+4j 
(3+4j)
>>> 2.5+7.7J 
(2.5+7.7j) 
>>>

Kompleks ədədləri iki parametrli complex(a, b) funksiyasından istifadə etməklə də vermək olar.
Burada yenə a həqiqi, b isə xəyali hissənin əmsalıdır:

>>> complex(3, 4) 
(3+4j)
>>> x = complex(1, 2) 
>>> print(x)
(1+2j) 
>>>

Bir parametrli complex(s) funksiyası isə verilmiş sətir və ya ədədi kompleks ədədə çevirir. Burada çevirmək istədiyimiz ifadə (s) sətir tipində olub dırnaq arasında verilməlidir:

>>> complex("2+3j") 
(2+3j)
>>> complex("4") 
(4+0j)
>>> complex("2j") 
2j
>>> complex()
0j
>>> complex("info")
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module> 
    complex("info")
ValueError: complex() arg is a malformed string 
>>>

Sonuncu misaldan da gördüyünüz kimi, verilmiş ifadəni kompleks ədədə çevirmək mümkün olmadıqda interpretator xəta mesajı verir. Eyni xəta ifadə içərisində + operatorlarının ətrafında boşluqlar olanda (məsələn: complex(“2 + 3j”) yazıldıqda) da qeydə alınır.
Kompleks ədədlər üzərində toplama, çıxma, vurma və bölmə əməliyyatlarını yerinə yetirmək olar:

>>> x = 2+3j 
>>> y = 1+2j 
>>> x + y 
(3+5j)
>>> x - y 
(1+1j) 
>>> x * y 
(-4+7j) 
>>> x / y 
(1.6-0.2j) 
>>>

İki kompleks ədədi bir-birilə müqayisə (>, <, >=, <=) etmək olmaz, lakin onların bir-birinə bərabərliyini yoxlamaq olar:

>>> x = 2+3j
>>> y = 1+2j
>>> x > y
Traceback (most recent call last):
  File "<pyshell#29>", line 1, in <module> 
    x > y
TypeError: unorderable types: complex() > complex() 
>>> x == y
False
>>>

Sonda kompleks ədədlər ilə bağlı bir neçə metodu da nəzərdən keçirək. Buradan “bəs metod nədir?” sualınızı eşidirəm 🙂 Əvvəlcədən qeyd edim ki, biz metodlar haqqında daha ətraflı obyekt yönlü proqramlaşdırmanı keçəndə bəhs edəcəyik. Hələlik isə onu bilməyiniz kifayətdir ki, metodlar da əslində funksiyalardır. Biz onları obyektlərə (indiki halda kompleks tipdə qiymət və ya dəyişənə) nöqtəli notasiya ilə tətbiq edirik. Yəni əvvəlcə qiymət və ya dəyişənin adını yazır, sonra nöqtə qoyur, ardınca da metodu qeyd edirik:

>>> x = 2+3j
>>> x.real # kompleks ədədin həqiqi hissəsi 
2.0
>>> x.imag # kompleks ədədin xəyali hissəsi 
3.0
>>> x.conjugate() # kompleks ədədin qoşması 
(2-3j)
>>>

Kompleks ədədlər ilə bağlı Python dilinin cmath modulunda bir sıra riyazi funksiyalar nəzərdə tutulmuşdur.