Cara menggunakan GETATTR pada Python

Skip to content

Deskripsi

Fungsi getattr() berfungsi untuk mendapatkan nilai dari attribut suatu objek.


Sintaks

Fungsi getattr() memiliki sintaks sebagai berikut:

getattr(object, name[, default])

Parameter

Fungsi getattr() memiliki tiga parameter, yaitu:

  • object – objek yang akan dikembalikan nilainya
  • name – nama attribut dari objek
  • default (opsional) – nilai yang ingin dikembalikan bila attribut tidak ditemukan

Nilai Kembalian

Fungsi getattr() mengembalikan:

  • value (nilai) jika attribut ditemukan
  • default, jika attribut tidak ditemukan
  • AttributeError, jika attribut tidak ditemukan dan nilai default tidak didefinisikan

Contoh

class Karyawan: nama = "Budi" usia = 27 karyawan = Karyawan() print('Nama karyawan:', getattr(karyawan, 'nama')) # Menggunakan nilai default print('Gaji:', getattr(karyawan, 'gaji', 1000000)) # Error, tanpa nilai default print('Usia karyawan:', getattr(karyawan, "jenis_kelamin"))


Output

Output dari program di atas adalah seperti berikut:

Nama karyawan: Budi
Gaji: 1000000

Traceback (most recent call last):
 File "<stdin>", line 12, in <module>
 print('Usia karyawan:', getattr(karyawan, "jenis_kelamin"))
AttributeError: 'Karyawan' object has no attribute 'jenis_kelamin'

Estimasi Waktu Baca: < 1 menit

Deskripsi Fungsi

Fungsi getattr() digunakan untuk mendapatkan nilai dari atribut suatu objek. Jika tidak ditemukan, akan mengembalikan nilai default yang diberikan ke fungsi tersebut.

Sintaks dan Parameter

Sintaks dari fungsi getattr() adalah sebagai berikut:


getattr(object, name[, default])

Fungsi getattr() menerima tiga parameter yaitu

  • object – objek yang nilai atributnya akan didapatkan
  • name – string yang berisi nama atribut dari objek
  • default (opsional) – nilai yang akan dikembalikan jika nama atribut tidak ditemukan

Nila kembalian fungsi getattr() berupa:

  • value – atau nilai, jika nama atribut ditemukan
  • default – jika nama atribut tidak ditemukan
  • AttributeError – jika nama atribut tidak ditemukan dan nilai dari parameter default tidak didefinisikan

Contoh Penerapan


class Siswa:
	nama = "Kuro Neko"
	usia = 20

siswa = Siswa()
print("Nama Siswa:", getattr(siswa, "nama"))

# Mendefinisikan nilai pada parameter default
print("Kelas:", getattr(siswa, "ttl", "Kelas A"))

# AttributeError, nama atribut tidak ditemukan dan tidak mendefinisikan nilai default
print("Gender:", getattr(siswa, "gender"))

Keluaran:


Nama Siswa: Kuro Neko
Kelas: Kelas A
Traceback (most recent call last):
  File "hello_world.py", line 127, in <module>
    print("Gender:", getattr(siswa, "gender"))
AttributeError: 'Siswa' object has no attribute 'gender'

Saya membaca tentang fungsi getattr() . Masalahnya adalah bahwa saya masih tidak dapat memahami ide penggunaannya. Satu-satunya hal yang saya mengerti tentang getattr() adalah getattr(li, "pop") sama dengan memanggil li.pop.

Saya tidak mengerti ketika buku itu menyebutkan bagaimana Anda menggunakannya untuk mendapatkan referensi ke suatu fungsi tanpa mengetahui namanya sampai waktu berjalan. Mungkin ini adalah saya menjadi noob dalam pemrograman, secara umum. Adakah yang bisa menjelaskan masalah ini? Kapan dan bagaimana tepatnya saya menggunakan ini?

Anda dapat melihat contoh lengkapnya di sini:

  • https://linux.die.net/diveintopython/html/power_of_introspection/index.html

Introspeksi dapat digunakan untuk tujuan yang berbeda, yang disajikan dalam 'Dive Into Python' hanyalah cara untuk menambahkan fungsionalitas (plug-in) secara dinamis di aplikasi Anda.

Maksud secara dinamis maksud saya tanpa melakukan modifikasi pada aplikasi inti untuk menambahkan fitur baru.

Contoh 'Dive Into Python' - aplikasi sederhana untuk mengekstrak atribut dari file file yang berbeda - Anda dapat menambahkan penanganan format file baru tanpa melakukan modifikasi pada aplikasi asli.

Saya sarankan Anda menyelesaikan buku. Saat Anda membaca, semuanya akan menjadi semakin jelas.

Objek dalam Python dapat memiliki atribut - atribut data dan fungsi untuk bekerja dengan mereka (metode). Sebenarnya, setiap objek memiliki atribut bawaan.

Misalnya Anda memiliki objek person, yang memiliki beberapa atribut: name, gender, dll.

Anda mengakses atribut-atribut ini (baik itu metode atau objek data) biasanya menulis: person.name, person.gender, person.the_method(), dll.

Tetapi bagaimana jika Anda tidak tahu nama atribut pada saat Anda menulis program? Misalnya Anda memiliki nama atribut yang disimpan dalam variabel yang disebut attr_name.

jika

attr_name = 'gender'

lalu, alih-alih menulis

gender = person.gender

kamu bisa menulis

gender = getattr(person, attr_name)

Beberapa latihan:

Python 3.4.0 (default, Apr 11 2014, 13:05:11)

>>> class Person():
...     name = 'Victor'
...     def say(self, what):
...         print(self.name, what)
... 
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello

getattr akan menaikkan AttributeError jika atribut dengan nama yang diberikan tidak ada di objek:

>>> getattr(person, 'age')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

Tapi Anda bisa memberikan nilai default sebagai argumen ketiga, yang akan dikembalikan jika atribut seperti itu tidak ada:

>>> getattr(person, 'age', 0)
0

Anda dapat menggunakan getattr bersama dengan dir untuk beralih pada semua nama atribut dan mendapatkan nilainya:

>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

>>> obj = 1000
>>> for attr_name in dir(obj):
...     attr_value = getattr(obj, attr_name)
...     print(attr_name, attr_value, callable(attr_value))
... 
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...

>>> getattr(1000, 'bit_length')()
10

Penggunaan praktis untuk ini adalah menemukan semua metode yang namanya dimulai dengan test dan panggil mereka .

Mirip dengan getattr ada setattr yang memungkinkan Anda untuk menetapkan atribut objek yang namanya:

>>> setattr(person, 'name', 'Andrew')
>>> person.name  # accessing instance attribute
'Andrew'
>>> Person.name  # accessing class attribute
'Victor'
>>>

Bagi saya, getattr paling mudah untuk dijelaskan dengan cara ini:

Ini memungkinkan Anda untuk memanggil metode berdasarkan isi string daripada mengetikkan nama metode.

Misalnya, Anda tidak dapat melakukan ini:

obj = MyObject()
for x in ['foo', 'bar']:
    obj.x()

karena x bukan dari tipe "builtin", tetapi "str". Namun, Anda BISA melakukan ini:

obj = MyObject()
for x in ['foo', 'bar']:
    getattr(obj, x)()

Ini memungkinkan Anda untuk terhubung secara dinamis dengan objek berdasarkan input Anda. Saya merasa berguna ketika berhadapan dengan objek dan modul khusus.

Kasus penggunaan yang cukup umum untuk getattr adalah memetakan data ke berbagai fungsi. 

Misalnya, dalam kerangka kerja web seperti Django atau Pylons, getattr memudahkan untuk memetakan URL permintaan web ke fungsi yang akan menanganinya. Jika Anda melihat di bawah kap perutean Pylons, misalnya, Anda akan melihat bahwa (secara default, setidaknya) itu memotong URL permintaan, seperti:

http://www.example.com/customers/list

ke dalam "pelanggan" dan "daftar". Kemudian ia mencari kelas controller bernama CustomerController. Dengan asumsi ia menemukan kelas, ia menciptakan turunan dari kelas dan kemudian menggunakan getattr untuk mendapatkan metode list-nya. Kemudian memanggil metode itu, meneruskannya permintaan sebagai argumen.

Setelah Anda memahami gagasan ini, menjadi sangat mudah untuk memperluas fungsionalitas aplikasi web: cukup tambahkan metode baru ke kelas controller, dan kemudian buat tautan di halaman Anda yang menggunakan URL yang sesuai untuk metode tersebut. Semua ini dimungkinkan oleh getattr.

Berikut adalah contoh cepat dan kotor tentang bagaimana suatu kelas dapat mem-boot versi berbeda dari metode penyimpanan tergantung pada sistem operasi mana yang sedang dieksekusi menggunakan getattr().

import os

class Log(object):
    def __init__(self):
        self.os = os.name
    def __getattr__(self, name):
        """ look for a 'save' attribute, or just 
          return whatever attribute was specified """
        if name == 'save':
            try:
                # try to dynamically return a save 
                # method appropriate for the user's system
                return getattr(self, self.os)
            except:
                # bail and try to return 
                # a default save method
                return getattr(self, '_save')
        else:
            return getattr(self, name)

    # each of these methods could have save logic specific to 
    # the system on which the script is executed
    def posix(self): print 'saving on a posix machine'
    def nt(self): print 'saving on an nt machine'
    def os2(self): print 'saving on an os2 machine'
    def ce(self): print 'saving on a ce machine'
    def Java(self): print 'saving on a Java machine'
    def riscos(self): print 'saving on a riscos machine'
    def _save(self): print 'saving on an unknown operating system'

    def which_os(self): print os.name

Sekarang mari kita gunakan kelas ini dalam contoh:

logger = Log()

# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along 
# somewhere else as 1st class:
save_func()

# or you can just call it directly:
logger.save()

# other attributes will hit the else 
# statement and still work as expected
logger.which_os()

Selain semua jawaban yang luar biasa di sini, ada cara untuk menggunakan getattr untuk menyimpan baris kode yang berlebihan dan menjaganya tetap nyaman. Pikiran ini muncul setelah representasi kode yang mengerikan yang kadang-kadang mungkin diperlukan.

Skenario

Misalkan struktur direktori Anda adalah sebagai berikut:

- superheroes.py
- properties.py

Dan, Anda memiliki fungsi untuk mendapatkan informasi tentang Thor, Iron Man, Doctor Strange di superheroes.py. Anda dengan cerdas menuliskan properti mereka semua di properties.py dalam dict yang kompak dan kemudian mengaksesnya.

properties.py

thor = {
    'about': 'Asgardian god of thunder',
    'weapon': 'Mjolnir',
    'powers': ['invulnerability', 'keen senses', 'vortex breath'], # and many more
}
iron_man = {
    'about': 'A wealthy American business magnate, playboy, and ingenious scientist',
    'weapon': 'Armor',
    'powers': ['intellect', 'armor suit', 'interface with wireless connections', 'money'],
}
doctor_strange = {
    'about': ' primary protector of Earth against magical and mystical threats',
    'weapon': 'Magic',
    'powers': ['magic', 'intellect', 'martial arts'],
}

Sekarang, katakanlah Anda ingin mengembalikan kemampuan masing-masing sesuai permintaan di superheroes.py. Jadi, ada fungsi seperti

from .properties import thor, iron_man, doctor_strange


def get_thor_weapon():
    return thor['weapon']


def get_iron_man_bio():
    return iron_man['about']


def get_thor_powers():
    return thor['powers']

... dan lebih banyak fungsi mengembalikan nilai yang berbeda berdasarkan tombol dan pahlawan super.

Dengan bantuan getattr, Anda dapat melakukan sesuatu seperti:

from . import properties


def get_superhero_weapon(hero):
    superhero = getattr(properties, hero)
    return superhero['weapon']


def get_superhero_powers(hero):
    superhero = getattr(properties, hero)
    return superhero['powers']

Anda sangat mengurangi jumlah baris kode, fungsi, dan pengulangan!

Oh dan tentu saja, jika Anda memiliki nama buruk seperti properties_of_thor untuk variabel, mereka dapat dibuat dan diakses dengan hanya melakukan

def get_superhero_weapon(hero):
    superhero = 'properties_of_{}'.format(hero)
    all_properties = getattr(properties, superhero)
    return all_properties['weapon']

CATATAN: Untuk masalah khusus ini, mungkin ada cara yang lebih cerdas untuk menangani situasi, tetapi idenya adalah untuk memberikan wawasan tentang penggunaan getattr di tempat yang tepat untuk menulis kode yang lebih bersih.

Saya kadang-kadang menggunakan getattr(..) untuk malas menginisialisasi atribut-atribut kepentingan sekunder sesaat sebelum mereka digunakan dalam kode. 

Bandingkan yang berikut ini:

class Graph(object):
    def __init__(self):
        self.n_calls_to_plot = 0

    #...
    #A lot of code here
    #...

    def plot(self):
        self.n_calls_to_plot += 1

Untuk ini:

class Graph(object):
    def plot(self):
        self.n_calls_to_plot = 1 + getattr(self, "n_calls_to_plot", 0)

Keuntungan dari cara kedua adalah bahwa n_calls_to_plot hanya muncul di sekitar tempat dalam kode di mana ia digunakan. Ini bagus untuk keterbacaan, karena (1) Anda dapat segera melihat nilai apa yang dimulai dengan ketika membaca bagaimana itu digunakan, (2) itu tidak memperkenalkan gangguan ke dalam metode __init__(..), yang idealnya harus tentang keadaan konseptual dari kelas, daripada beberapa penghitung utilitas yang hanya digunakan oleh salah satu metode fungsi karena alasan teknis, seperti optimasi, dan tidak ada hubungannya dengan makna objek.

Cukup sering ketika saya membuat file XML dari data yang disimpan di kelas saya akan sering menerima kesalahan jika atribut tidak ada atau bertipe None. Dalam hal ini, masalah saya tidak tidak tahu apa nama atribut itu, seperti yang dinyatakan dalam pertanyaan Anda, tetapi apakah data pernah disimpan dalam atribut itu.

class Pet:
    def __init__(self):
        self.hair = None
        self.color = None

Jika saya menggunakan hasattr untuk melakukan ini, itu akan mengembalikan True bahkan jika nilai atributnya bertipe None dan ini akan menyebabkan perintah ElementTree set saya gagal.

hasattr(temp, 'hair')
>>True

Jika nilai atribut bertipe None, getattr juga akan mengembalikannya yang akan menyebabkan perintah ElementTree set saya gagal. 

c = getattr(temp, 'hair')
type(c)
>> NoneType

Saya menggunakan metode berikut untuk menangani kasus-kasus ini sekarang:

def getRealAttr(class_obj, class_attr, default = ''):
    temp = getattr(class_obj, class_attr, default)
    if temp is None:
        temp = default
    Elif type(temp) != str:
        temp = str(temp)
    return temp

Inilah saatnya dan bagaimana saya menggunakan getattr.

getattr(object, 'x') setara dengan hingga object.x.

Ada dua kasus di mana getattr dapat bermanfaat.

  • anda tidak dapat menulis object.x, (karena Anda sebelumnya tidak tahu atribut mana yang Anda inginkan. misalnya: itu berasal dari sebuah string)
  • anda ingin memberikan nilai default. object.y akan memunculkan AttributeError jika tidak ada y. Tetapi getattr(object, 'y', 5) akan mengembalikan 5.

Penggunaan lain dari getattr () dalam mengimplementasikan pernyataan switch dengan Python. Ini menggunakan kedua refleksi untuk mendapatkan jenis case.

import sys

class SwitchStatement(object):
    """ a class to implement switch statement and a way to show how to use gettattr in Pythion"""

    def case_1(self):
        return "value for case_1"

    def case_2(self):
        return "value for case_2"

    def case_3(self):
        return "value for case_3"

    def case_4(self):
        return "value for case_4"

    def case_value(self, case_type=1):
        """This is the main dispatchmethod, that uses gettattr"""
        case_method = 'case_' + str(case_type)
        # fetch the relevant method name
        # Get the method from 'self'. Default to a lambda.
        method = getattr(self, case_method, lambda: "Invalid case type")
        # Call the method as we return it
        return method()

def main(_):
    switch = SwitchStatement()
    print swtich.case_value(_)

if __== '__main__':
    main(int(sys.argv[1]))

# getattr

class hithere():

    def french(self):
        print 'bonjour'

    def english(self):
        print 'hello'

    def german(self):
        print 'hallo'

    def czech(self):
        print 'ahoj'

    def noidea(self):
        print 'unknown language'


def dispatch(language):
    try:
        getattr(hithere(),language)()
    except:
        getattr(hithere(),'noidea')()
        # note, do better error handling than this

dispatch('french')
dispatch('english')
dispatch('german')
dispatch('czech')
dispatch('spanish')

Ini juga mengklarifikasi dari https://www.programiz.com/python-programming/methods/built-in/getattr

class Person:
    age = 23
    name = "Adam"

person = Person()
print('The age is:', getattr(person, "age"))
print('The age is:', person.age)

Usia adalah: 23

Usia adalah: 23

class Person:
    age = 23
    name = "Adam"

person = Person()

# when default value is provided
print('The sex is:', getattr(person, 'sex', 'Male'))

# when no default value is provided
print('The sex is:', getattr(person, 'sex'))

Jenis kelaminnya adalah: Pria

AttributeError: Objek 'Orang' tidak memiliki atribut 'seks'