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!