Getattr () वास्तव में क्या है और मैं इसका उपयोग कैसे करूं?


295

मैंने हाल ही में getattr()फ़ंक्शन के बारे में पढ़ा है । समस्या यह है कि मैं अभी भी इसके उपयोग के विचार को समझ नहीं सकता। केवल एक चीज जो मैं समझता हूं getattr(), वह getattr(li, "pop")यह है कि कॉलिंग के समान ही है li.pop

मुझे समझ में नहीं आया जब पुस्तक ने उल्लेख किया कि आप रन-टाइम तक इसका नाम जाने बिना किसी फ़ंक्शन के संदर्भ में इसका उपयोग कैसे करते हैं। हो सकता है कि यह सामान्य रूप से प्रोग्रामिंग में एक नॉब हो। क्या कोई इस विषय पर कुछ प्रकाश डाल सकता है? मैं इसका उपयोग कब और कैसे करता हूं?


आप किस हिस्से से परेशान हैं? तार के रूप में विशेषताएँ? प्रथम श्रेणी के कार्य?
इग्नासियो वाज़क्वेज़-अब्राम्स

1
मुझे लगता है कि मेरी समस्या गेटअटर () की अवधारणा को समझ रही है। मुझे अभी भी इसका उद्देश्य समझ नहीं आ रहा है।
टेरेंस पोंस

@ मेरे जवाब से चीजें स्पष्ट नहीं होतीं?
Alois Cochard

@ नमस्ते, आपके उत्तर ने निश्चित रूप से मेरे कुछ संदेह को दूर कर दिया है, लेकिन मैं अभी भी पूरी तरह से समझ नहीं पा रहा हूं कि गेटैट () क्या है।
टेरेंस पोंस

6
@ S.Lott, मैंने किया। दस्तावेज़ में केवल परिभाषा थी इसलिए मैं इसके उपयोग के बारे में उलझन में था। मैं इसके बारे में अधिक पढ़ने के बाद अब गेटअटर समझता हूं।
टेरेंस पॉनस

जवाबों:


87

getattr(object, 'x') के बराबर है object.x

कर रहे हैं केवल दो मामलों जहां getattrउपयोगी हो सकता है।

  • आप नहीं लिख सकते object.x, क्योंकि आप पहले से नहीं जानते कि आपको कौन सी विशेषता चाहिए (यह एक स्ट्रिंग से आता है)। मेटा-प्रोग्रामिंग के लिए बहुत उपयोगी है।
  • आप एक डिफ़ॉल्ट मान प्रदान करना चाहते हैं। अगर कोई नहीं है तो object.yउठाएंगे । लेकिन लौट आएगा ।AttributeErrorygetattr(object, 'y', 5)5

2
मुझे लगता है कि यह स्वीकृत उत्तर होना चाहिए। बहुत स्पष्ट और बात तक।
युक्ली

290

पाइथन की वस्तुओं में विशेषताएँ हो सकती हैं - डेटा विशेषताएँ और कार्य उन (विधियों) के साथ काम करने के लिए। दरअसल, प्रत्येक वस्तु में अंतर्निहित विशेषताएं होती हैं।

उदाहरण के लिए आप एक वस्तु है person, जो कई गुण होते हैं: name, gender, आदि

आप का उपयोग इन विशेषताओं (यह तरीकों या डेटा वस्तुओं हो) आम तौर पर लेखन: person.name, person.gender, person.the_method(), आदि

लेकिन क्या होगा यदि आप कार्यक्रम लिखते समय विशेषता के नाम को नहीं जानते हैं? उदाहरण के लिए आपके पास विशेषता का नाम है जिसे चर में संग्रहीत किया जाता है attr_name

अगर

attr_name = 'gender'

फिर, लिखने के बजाय

gender = person.gender

तुम लिख सकते हो

gender = getattr(person, attr_name)

कुछ अभ्यास:

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

getattrAttributeErrorदिए गए नाम के साथ विशेषता वस्तु में मौजूद न होने पर उठाएंगे :

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

लेकिन आप तीसरे तर्क के रूप में एक डिफ़ॉल्ट मान पारित कर सकते हैं, जो कि यदि ऐसी विशेषता मौजूद नहीं है तो वापस कर दिया जाएगा:

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

आप सभी विशेषता नामों पर पुनरावृति getattrके साथ उपयोग कर सकते हैं dirऔर उनके मान प्राप्त कर सकते हैं:

>>> 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

इसके लिए एक व्यावहारिक उपयोग उन सभी तरीकों को खोजना होगा जिनके नाम उनके साथ शुरू होते हैं testऔर उन्हें कॉल करते हैं

getattrवहाँ के समान है setattrजो आपको एक वस्तु का गुण सेट करने की अनुमति देता है जिसका नाम है:

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

9
तो यह मुझे लगता है कि getattr(..)2 परिदृश्यों में उपयोग किया जाना चाहिए: 1. जब विशेषता नाम एक चर (जैसे getattr(person, some_attr)) और 2 के अंदर एक मूल्य है । जब हमें डिफ़ॉल्ट मान (जैसे getattr(person, 'age', 24)) के लिए तीसरे स्थितीय तर्क का उपयोग करने की आवश्यकता होती है । अगर मुझे ऐसा कोई दृश्य दिखाई देता है, जैसे getattr(person, 'age')मुझे लगता है कि यह समान है, person.ageजो मुझे लगता है कि person.ageअधिक पायथोनिक है। क्या वो सही है?
wpcarro

102

मेरे लिए, getattrइस तरह से समझाना सबसे आसान है:

यह आपको विधि नाम लिखने के बजाय एक स्ट्रिंग की सामग्री के आधार पर विधियों को कॉल करने की अनुमति देता है।

उदाहरण के लिए, आप ऐसा नहीं कर सकते:

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

क्योंकि एक्स प्रकार की नहीं है builtin, लेकिन str। हालाँकि, आप ऐसा कर सकते हैं:

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

यह आपको अपने इनपुट के आधार पर वस्तुओं के साथ गतिशील रूप से जुड़ने की अनुमति देता है। कस्टम ऑब्जेक्ट्स और मॉड्यूल के साथ काम करते समय मैंने इसे उपयोगी पाया है।


2
यह एक बहुत ही सीधा और सटीक उत्तर है।
user6037143

43

getattrकार्यों के लिए डेटा मैपिंग के लिए एक बहुत ही सामान्य उपयोग मामला है।

उदाहरण के लिए, Django या Pylons जैसे वेब फ्रेमवर्क में, getattrवेब फ़ंक्शन के URL को उस फ़ंक्शन को मैप करने के लिए सीधा बनाता है जो इसे संभालने जा रहा है। यदि आप मिसाल के तौर पर पाइलन्स के रूटिंग के नीचे देखते हैं, तो आप देखेंगे कि (डिफ़ॉल्ट रूप से, कम से कम) यह अनुरोध के URL को काट देता है, जैसे:

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

"ग्राहकों" और "सूची" में। फिर यह नाम के एक नियंत्रक वर्ग की खोज करता है CustomerController। यह मानते हुए कि यह कक्षा को ढूंढता है, यह कक्षा का एक उदाहरण बनाता है और फिर getattrइसका listतरीका प्राप्त करने के लिए उपयोग करता है । यह तब उस पद्धति को कहता है, इसे एक तर्क के रूप में अनुरोध करता है।

एक बार जब आप इस विचार को समझ लेते हैं, तो वेब एप्लिकेशन की कार्यक्षमता को बढ़ाना वास्तव में आसान हो जाता है: बस नियंत्रक वर्गों में नए तरीके जोड़ें, और फिर अपने पृष्ठों में लिंक बनाएं जो उन तरीकों के लिए उपयुक्त URL का उपयोग करते हैं। यह सब संभव हो जाता है getattr


13

यहां एक त्वरित और गंदा उदाहरण है कि एक वर्ग किस तरह से एक बचत विधि के विभिन्न संस्करणों को आग लगा सकता है, जिसके आधार पर इसका उपयोग करके किस ऑपरेटिंग सिस्टम को निष्पादित किया जा रहा है 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

अब एक उदाहरण में इस वर्ग का उपयोग करते हैं:

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()

7

यहां सभी आश्चर्यजनक उत्तरों के अलावा, getattrकोड की प्रचुर लाइनों को बचाने और इसे सुरक्षित रखने के लिए उपयोग करने का एक तरीका है । यह विचार कोड के भयानक प्रतिनिधित्व के बाद आया है जो कभी-कभी एक आवश्यकता हो सकती है।

परिदृश्य

मान लीजिए कि आपकी निर्देशिका संरचना इस प्रकार है:

- superheroes.py
- properties.py

और, यदि आप के बारे में जानकारी प्राप्त करने के लिए कार्य करता है Thor, Iron Man, Doctor Strangeमें superheroes.py। आप बहुत चालाकी से उन सभी के गुणों को properties.pyएक कॉम्पैक्ट में लिखते हैं dictऔर फिर उन्हें एक्सेस करते हैं।

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'],
}

अब, मान लें कि आप उनमें से प्रत्येक की क्षमताओं को मांग में वापस करना चाहते हैं superheroes.py। तो, जैसे कार्य हैं

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']

... और अधिक फ़ंक्शंस कुंजियों और सुपर हीरो के आधार पर अलग-अलग मान लौटाते हैं।

आपकी मदद से getattr, आप कुछ ऐसा कर सकते हैं:

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']

आपने कोड, फ़ंक्शन और पुनरावृत्ति की लाइनों की संख्या को काफी कम कर दिया है!

ओह और निश्चित रूप से, यदि आपके पास properties_of_thorचरों के लिए बुरे नाम हैं , तो उन्हें बस बनाकर पहुँचा जा सकता है

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

नोट: इस विशेष समस्या के लिए, स्थिति से निपटने के लिए स्मार्ट तरीके हो सकते हैं, लेकिन विचार यह है कि getattrक्लीनर कोड लिखने के लिए सही स्थानों का उपयोग करने के बारे में जानकारी दी जाए ।


3
# 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')

2
क्या आप अपने समाधान के बारे में थोड़ा और विवरण जोड़कर अपने उत्तर को विस्तृत कर सकते हैं?
अबारीसोन

3

कभी-कभी getattr(..)कोड में उपयोग किए जाने से पहले मैं माध्यमिक महत्व के आलसी प्रारंभिक गुण का उपयोग करता हूं ।

निम्नलिखित की तुलना करें:

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

इसके लिए:

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

दूसरे तरीके का लाभ यह है कि n_calls_to_plotकेवल उस कोड के स्थान के आसपास दिखाई देता है जहां इसका उपयोग किया जाता है। यह पठनीयता के लिए अच्छा है, क्योंकि (1) आप तुरंत देख सकते हैं कि पढ़ते समय यह किस मूल्य के साथ शुरू होता है, इसका उपयोग कैसे किया जाता है, (2) यह __init__(..)विधि में विकर्षण का परिचय नहीं देता है , जो आदर्श रूप से कक्षा की वैचारिक स्थिति के बारे में होना चाहिए , बल्कि कुछ उपयोगिता काउंटर की तुलना में जो केवल तकनीकी कारणों से फ़ंक्शन के तरीकों में से एक द्वारा उपयोग किया जाता है, जैसे कि अनुकूलन, और इसका ऑब्जेक्ट के अर्थ से कोई लेना-देना नहीं है।


3

जब मैं किसी वर्ग में संग्रहीत डेटा से XML फ़ाइल बना रहा होता हूं, तो अक्सर मुझे त्रुटियां प्राप्त होती हैं यदि विशेषता मौजूद नहीं थी या टाइप की थी None। इस मामले में, मेरा मुद्दा यह नहीं जान रहा था कि विशेषता नाम क्या था, जैसा कि आपके प्रश्न में कहा गया है, बल्कि उस विशेषता में संग्रहीत डेटा था।

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

यदि मैं hasattrऐसा करता था, तो यह तब Trueभी लौटेगा , जब विशेषता मान टाइप का हो Noneऔर इससे मेरा ElementTree setकमांड विफल हो जाएगा।

hasattr(temp, 'hair')
>>True

यदि विशेषता मान प्रकार का था None, तो getattrउसे भी लौटा दिया जाएगा, जिससे मेरा ElementTree setकमांड विफल हो जाएगा।

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

इन मामलों की देखभाल के लिए मैं निम्नलिखित विधि का उपयोग करता हूं:

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

यह मैं कब और कैसे उपयोग करता हूं getattr


3

पायथन में एक स्विच स्टेटमेंट को लागू करने में गेटैट () का एक और उपयोग। यह केस प्रकार प्राप्त करने के लिए दोनों प्रतिबिंब का उपयोग करता है।

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 __name__ == '__main__':
    main(int(sys.argv[1]))

मैं इस सवाल का जवाब की तरह लेकिन छोटे लिखने की त्रुटियों को ठीक कृपया
मई

2

setattr ()

हम अपने वर्ग उदाहरण में एक विशेषता जोड़ने के लिए setattr का उपयोग करते हैं। हम वर्ग उदाहरण, विशेषता नाम और मान पास करते हैं।

getattr ()

गेटअटर के साथ हम इन मूल्यों को पुनः प्राप्त करते हैं

उदाहरण के लिए

Employee = type("Employee", (object,), dict())

employee = Employee()

# Set salary to 1000
setattr(employee,"salary", 1000 )

# Get the Salary
value = getattr(employee, "salary")

print(value)

1

मुझे लगता है कि यह उदाहरण आत्म व्याख्यात्मक है। यह पहले पैरामीटर की विधि को चलाता है, जिसका नाम दूसरे पैरामीटर में दिया गया है।

class MyClass:
   def __init__(self):
      pass
   def MyMethod(self):
      print("Method ran")

# Create an object
object = MyClass()
# Get all the methods of a class
method_list = [func for func in dir(MyClass) if callable(getattr(MyClass, func))]
# You can use any of the methods in method_list
# "MyMethod" is the one we want to use right now

# This is the same as running "object.MyMethod()"
getattr(object,'MyMethod')()

0

यह 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)

उम्र है: 23

उम्र है: 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'))

लिंग है: पुरुष

गुण: 'व्यक्ति' की कोई विशेषता 'सेक्स' नहीं है


0

मैंने पायथन 2.7.17 में कोशिश की है

कुछ साथी लोगों ने पहले ही जवाब दे दिया। हालाँकि मैंने getattr (obj, 'set_value') को कॉल करने की कोशिश की है और इस set_value पद्धति को निष्पादित नहीं किया है, इसलिए मैं getattr (obj, 'set_value') में बदल गया () -> यह उसी को लागू करने में मदद करता है।

उदाहरण कोड:

उदाहरण 1:

    class GETATT_VERIFY():
       name = "siva"
       def __init__(self):
           print "Ok"
       def set_value(self):
           self.value = "myself"
           print "oooh"
    obj = GETATT_VERIFY()
    print getattr(GETATT_VERIFY, 'name')
    getattr(obj, 'set_value')()
    print obj.value
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.