Getattr () ঠিক কী এবং আমি কীভাবে এটি ব্যবহার করব?


295

আমি সম্প্রতি ফাংশন সম্পর্কে পড়েছিgetattr() । সমস্যাটি হ'ল আমি এখনও এর ব্যবহারের ধারণাটি বুঝতে পারি না। আমি শুধু সম্পর্কে বুঝতে getattr()হয় getattr(li, "pop")কলিং হিসাবে একই li.pop

বইটি কীভাবে আপনি রান-টাইম পর্যন্ত এটির নাম না জেনে কোনও ফাংশনের রেফারেন্স পেতে কীভাবে এটি ব্যবহার করবেন তা উল্লেখ করেছিলাম। সাধারণত এটিই আমি সাধারণভাবে প্রোগ্রামিংয়ের নাকী হয়ে যাচ্ছি। কেউ কি এই বিষয়ে কিছু আলোকপাত করতে পারে? কখন এবং কীভাবে আমি এটি সঠিকভাবে ব্যবহার করব?


কোন অংশ নিয়ে আপনার সমস্যা হচ্ছে? স্ট্রিং হিসাবে বৈশিষ্ট্য? প্রথম শ্রেণির কাজ?
Ignacio Vazquez-Abram

1
আমি মনে করি আমার সমস্যাটি getattr () এর ধারণাটি বোঝে। আমি এখনও এর উদ্দেশ্য বুঝতে পারি না।
টেরেন্স পোনস

@ টেরেন্স আমার উত্তরগুলি কি আরও পরিষ্কার করে না?
অ্যালোস কোকার্ড

@ অলয়িস, আপনার উত্তরটি অবশ্যই আমার কিছু সন্দেহ দূর করেছে, তবে আমি এখনও পুরোপুরি বুঝতে পারি না গেটআটার () কীসের জন্য।
টেরেন্স পোনস

6
@ এসলট, আমি করেছি। ডকুমেন্টেশনের কেবলমাত্র সংজ্ঞা ছিল তাই আমি এর ব্যবহার সম্পর্কে একধরণের বিভ্রান্ত ছিলাম। আমি যদিও এখন এটি সম্পর্কে আরও পড়ার পরে getattr বুঝতে।
টেরেন্স পোনস

উত্তর:


87

getattr(object, 'x') সম্পূর্ণরূপে সমতুল্য করার object.x

আছে শুধু দুটি মামলা যেখানে getattrউপযোগী হতে পারে।

  • আপনি লিখতে পারবেন না object.x, কারণ আপনি কোন বৈশিষ্ট্যটি চান তা আগেই জানেন না (এটি একটি স্ট্রিং থেকে আসে)। মেটা-প্রোগ্রামিংয়ের জন্য খুব দরকারী।
  • আপনি একটি ডিফল্ট মান প্রদান করতে চান। object.yএকটি উঠাবে AttributeErrorআছে কিনা কোন y। তবে getattr(object, 'y', 5)ফিরে আসবে 5

2
আমি মনে করি এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। খুব পরিষ্কার এবং বিষয়টি।
yuqli

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 টি পরিস্থিতিতে ব্যবহার করা উচিত বলে মনে হয় : ১. যখন অ্যাট্রিবিউটের নামটি একটি ভেরিয়েবলের (যেমন 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
এটি একটি দুর্দান্ত সোজা এগিয়ে এবং সুনির্দিষ্ট উত্তর।
ব্যবহারকারী 6037143

43

একটি getattrকার্যকরী সাধারণ ব্যবহারের ক্ষেত্রে ফাংশনে ডেটা ম্যাপ করা।

উদাহরণস্বরূপ, জ্যাঙ্গো বা পাইলনের মতো ওয়েব ফ্রেমওয়ার্কে getattrএটি কোনও ওয়েব অনুরোধের ইউআরএলকে হ্যান্ডল করতে চলেছে এমন ফাংশনে ম্যাপ করা সহজ করে তোলে। আপনি যদি পাইলনের রাউটিংয়ের নীচে তাকান, উদাহরণস্বরূপ, আপনি দেখতে পাবেন যে (ডিফল্টরূপে, কমপক্ষে) এটি একটি অনুরোধের ইউআরএল চপ আপ করে, যেমন:

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

"গ্রাহক" এবং "তালিকা" এ। তারপরে এটি নামের একটি নিয়ামক শ্রেণীর সন্ধান করে CustomerController। অনুমান করে এটি শ্রেণিটি সন্ধান করে এটি শ্রেণীর একটি উদাহরণ তৈরি করে এবং এরপরে getattrতার listপদ্ধতিটি ব্যবহার করে । তারপরে এটি সেই পদ্ধতিটিকে কল করে এটি আর্গুমেন্ট হিসাবে অনুরোধটি পাস করে।

একবার আপনি এই ধারণাটি উপলব্ধি করলে, ওয়েব অ্যাপ্লিকেশনটির কার্যকারিতা বাড়ানো সত্যিই সহজ হয়ে যায়: কেবলমাত্র নিয়ামক শ্রেণিতে নতুন পদ্ধতি যুক্ত করুন এবং তারপরে আপনার পৃষ্ঠাগুলিতে লিঙ্কগুলি তৈরি করুন যা এই পদ্ধতির জন্য উপযুক্ত ইউআরএল ব্যবহার করে। এই সমস্তই সম্ভব হয়েছে 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
আপনি যে সমাধানটি সরবরাহ করেন সে সম্পর্কে আরও কিছু বিবরণ যুক্ত করে কী আপনি আরও উত্তর প্রদান করতে পারেন?
২ar

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কেবলমাত্র কোডটি যেখানে ব্যবহৃত হয়েছে সেই জায়গার চারপাশে প্রদর্শিত হবে। এটি পঠনযোগ্যতার পক্ষে ভাল, কারণ (১) আপনি কীভাবে এটি ব্যবহার করবেন তা পড়ার সাথে সাথে এটি কী মান দিয়ে শুরু হয় তা তাত্ক্ষণিকভাবে দেখতে পারবেন, (২) এটি __init__(..)পদ্ধতিতে কোনও বিভ্রান্তির পরিচয় দেয় না , যা আদর্শভাবে শ্রেণীর ধারণাগত অবস্থার সম্পর্কে হওয়া উচিত পরিবর্তে কিছু ইউটিলিটি কাউন্টার যা কেবলমাত্র প্রযুক্তিগত কারণে যেমন অপ্টিমাইজেশনের জন্য ফাংশনটির একটি পদ্ধতি দ্বারা ব্যবহৃত হয় এবং অবজেক্টটির অর্থের সাথে কিছুই করার থাকে না।


3

বেশিরভাগ সময় যখন আমি ক্লাসে সঞ্চিত ডেটা থেকে একটি এক্সএমএল ফাইল তৈরি করি তখন বৈশিষ্ট্যটি উপস্থিত না থাকলে বা টাইপ করা থাকলে আমি প্রায়শই ত্রুটিগুলি পেয়ে যাব None। এই ক্ষেত্রে, আমার ইস্যুটি আপনার প্রশ্নে বর্ণিত হিসাবে, গুণটির নাম কী তা জানছিল না, বরং সেই বৈশিষ্ট্যে ডেটা কখনও সংরক্ষণ করা হয়েছিল ever

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

যদি আমি এটি ব্যবহার করতাম তবে বৈশিষ্ট্যটির মানটি টাইপ করা হলেও hasattrএটি ফিরে আসত এবং এর ফলে আমার এলিমেন্ট্রি কমান্ড ব্যর্থ হতে পারে।TrueNoneset

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

আমি এই উত্তর মত কিন্তু ছোট টাইপস ঠিক করুন
may

2

setattr ()

আমরা আমাদের শ্রেণীর উদাহরণগুলিতে একটি বৈশিষ্ট্য যুক্ত করতে সেটট্রটার ব্যবহার করি । আমরা শ্রেণীর উদাহরণ, বৈশিষ্ট্যটির নাম এবং মানটি পাস করি।

getattr ()

সঙ্গে 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 (আপত্তি, 'সেট_ভ্যালু') কল করার চেষ্টা করেছি এবং এটি সেট_মূল্য পদ্ধতিটি কার্যকর করে না, সুতরাং আমি গ্যাটট্রারে পরিবর্তিত হয়েছি (অবজেক্ট, 'সেট_ভ্যালু') () -> এটি অনুরোধ করতে সহায়তা করে।

উদাহরণ কোড:

উদাহরণ 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.