Object Oriented Python - Fitur Lanjutan
Dalam hal ini kita akan melihat beberapa fitur lanjutan yang disediakan Python
Sintaks Inti dalam desain Kelas kami
Dalam hal ini kita akan melihat, bagaimana Python memungkinkan kita memanfaatkan operator di kelas kita. Python sebagian besar adalah objek dan metode yang memanggil objek dan ini bahkan berlanjut bahkan ketika disembunyikan oleh beberapa sintaks yang nyaman.
>>> var1 = 'Hello'
>>> var2 = ' World!'
>>> var1 + var2
'Hello World!'
>>>
>>> var1.__add__(var2)
'Hello World!'
>>> num1 = 45
>>> num2 = 60
>>> num1.__add__(num2)
105
>>> var3 = ['a', 'b']
>>> var4 = ['hello', ' John']
>>> var3.__add__(var4)
['a', 'b', 'hello', ' John']
Jadi jika kita harus menambahkan metode ajaib __add__ ke kelas kita sendiri, dapatkah kita melakukannya juga. Ayo coba lakukan itu.
Kami memiliki kelas yang disebut Sumlist yang memiliki kontraktor __init__ yang mengambil list sebagai argumen yang disebut my_list.
class SumList(object):
def __init__(self, my_list):
self.mylist = my_list
def __add__(self, other):
new_list = [ x + y for x, y in zip(self.mylist, other.mylist)]
return SumList(new_list)
def __repr__(self):
return str(self.mylist)
aa = SumList([3,6, 9, 12, 15])
bb = SumList([100, 200, 300, 400, 500])
cc = aa + bb # aa.__add__(bb)
print(cc) # should gives us a list ([103, 206, 309, 412, 515])
Keluaran
[103, 206, 309, 412, 515]
Tetapi ada banyak metode yang dikelola secara internal oleh metode sihir lainnya. Di bawah ini beberapa di antaranya,
'abc' in var # var.__contains__('abc')
var == 'abc' # var.__eq__('abc')
var[1] # var.__getitem__(1)
var[1:3] # var.__getslice__(1, 3)
len(var) # var.__len__()
print(var) # var.__repr__()
Mewarisi Dari tipe bawaan
Kelas juga dapat mewarisi dari tipe bawaan, ini berarti mewarisi dari bawaan apa pun dan memanfaatkan semua fungsionalitas yang ditemukan di sana.
Dalam contoh di bawah ini kami mewarisi dari kamus tetapi kemudian kami menerapkan salah satu metode __setitem__. Ini (setitem) dipanggil saat kita menyetel kunci dan nilai dalam kamus. Karena ini adalah metode ajaib, ini akan dipanggil secara implisit.
class MyDict(dict):
def __setitem__(self, key, val):
print('setting a key and value!')
dict.__setitem__(self, key, val)
dd = MyDict()
dd['a'] = 10
dd['b'] = 20
for key in dd.keys():
print('{0} = {1}'.format(key, dd[key]))
Keluaran
setting a key and value!
setting a key and value!
a = 10
b = 20
Mari memperluas contoh kita sebelumnya, di bawah ini kita telah memanggil dua metode ajaib yang disebut __getitem__ dan __setitem__ lebih baik dipanggil ketika kita berurusan dengan indeks daftar.
# Mylist inherits from 'list' object but indexes from 1 instead for 0!
class Mylist(list): # inherits from list
def __getitem__(self, index):
if index == 0:
raise IndexError
if index > 0:
index = index - 1
return list.__getitem__(self, index) # this method is called when
# we access a value with subscript like x[1]
def __setitem__(self, index, value):
if index == 0:
raise IndexError
if index > 0:
index = index - 1
list.__setitem__(self, index, value)
x = Mylist(['a', 'b', 'c']) # __init__() inherited from builtin list
print(x) # __repr__() inherited from builtin list
x.append('HELLO'); # append() inherited from builtin list
print(x[1]) # 'a' (Mylist.__getitem__ cutomizes list superclass
# method. index is 1, but reflects 0!
print (x[4]) # 'HELLO' (index is 4 but reflects 3!
Keluaran
['a', 'b', 'c']
a
HELLO
Dalam contoh di atas, kami menetapkan daftar tiga item dalam Daftar Saya dan secara implisit metode __init__ dipanggil dan ketika kami mencetak elemen x, kami mendapatkan daftar tiga item (['a', 'b', 'c']). Kemudian kami menambahkan elemen lain ke daftar ini. Nanti kita minta indeks 1 dan indeks 4. Tetapi jika Anda melihat outputnya, kami mendapatkan elemen dari (indeks-1) apa yang kami minta. Seperti yang kita ketahui pengindeksan daftar dimulai dari 0 tetapi di sini pengindeksan dimulai dari 1 (itulah sebabnya kami mendapatkan item pertama dari daftar).
Konvensi Penamaan
Dalam hal ini kita akan melihat nama yang akan kita gunakan untuk variabel terutama variabel privat dan konvensi yang digunakan oleh programmer Python di seluruh dunia. Meskipun variabel ditetapkan sebagai pribadi tetapi tidak ada privasi dalam Python dan ini memang sengaja dibuat. Seperti bahasa lain yang terdokumentasi dengan baik, Python memiliki konvensi penamaan dan gaya yang dipromosikannya meskipun tidak memberlakukannya. Ada panduan gaya yang ditulis oleh "Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the link for this, https://www.python.org/dev/peps/pep-0008/
PEP adalah singkatan dari Python enhancement proposal dan merupakan serangkaian dokumentasi yang didistribusikan di antara komunitas Python untuk membahas perubahan yang diusulkan. Misalnya direkomendasikan semua,
- Nama modul - all_lower_case
- Nama kelas dan nama pengecualian - CamelCase
- Nama global dan lokal - all_lower_case
- Fungsi dan nama metode - all_lower_case
- Konstanta - ALL_UPPER_CASE
Ini hanya rekomendasi, Anda dapat memvariasikannya jika Anda suka. Tetapi karena sebagian besar pengembang mengikuti rekomendasi ini, mungkin saya kode Anda kurang dapat dibaca.
Mengapa menyesuaikan diri dengan konvensi?
Kami dapat mengikuti rekomendasi PEP yang kami izinkan untuk kami dapatkan,
- Lebih akrab bagi sebagian besar pengembang
- Lebih jelas bagi sebagian besar pembaca kode Anda.
- Akan cocok dengan gaya kontributor lain yang bekerja pada basis kode yang sama.
- Merek pengembang perangkat lunak profesional
- Semua orang akan menerima Anda.
Penamaan Variabel - 'Publik' dan 'Pribadi'
Di Python, ketika kita berurusan dengan modul dan kelas, kita menetapkan beberapa variabel atau atribut sebagai privat. Di Python, tidak ada variabel instance "Private" yang tidak dapat diakses kecuali di dalam objek. Pribadi berarti mereka tidak dimaksudkan untuk digunakan oleh pengguna kode melainkan dimaksudkan untuk digunakan secara internal. Secara umum, sebuah konvensi sedang diikuti oleh sebagian besar pengembang Python, misalnya nama yang diawali dengan garis bawah. _attrval (contoh di bawah) harus diperlakukan sebagai bagian non-publik dari API atau kode Python apa pun, baik itu fungsi, metode, atau anggota data. Di bawah ini adalah konvensi penamaan yang kami ikuti,
Atribut atau variabel publik (dimaksudkan untuk digunakan oleh importir modul ini atau pengguna kelas ini) -regular_lower_case
Atribut atau variabel pribadi (penggunaan internal oleh modul atau kelas) -_single_leading_underscore
Atribut pribadi yang tidak boleh disubkelas -__double_leading_underscore
Atribut ajaib -__double_underscores__(gunakan mereka, jangan membuatnya)
class GetSet(object):
instance_count = 0 # public
__mangled_name = 'no privacy!' # special variable
def __init__(self, value):
self._attrval = value # _attrval is for internal use only
GetSet.instance_count += 1
@property
def var(self):
print('Getting the "var" attribute')
return self._attrval
@var.setter
def var(self, value):
print('setting the "var" attribute')
self._attrval = value
@var.deleter
def var(self):
print('deleting the "var" attribute')
self._attrval = None
cc = GetSet(5)
cc.var = 10 # public name
print(cc._attrval)
print(cc._GetSet__mangled_name)
Keluaran
setting the "var" attribute
10
no privacy!