পাইথনে অবজেক্টের অ্যাট্রিবিউটগুলির উপরে আইট্রেট করুন


162

আমার কাছে বেশ কয়েকটি বৈশিষ্ট্য এবং পদ্ধতি সহ পাইথন অবজেক্ট রয়েছে। আমি অবজেক্টের বৈশিষ্ট্যগুলি নিয়ে পুনরাবৃত্তি করতে চাই।

class my_python_obj(object):
    attr1='a'
    attr2='b'
    attr3='c'

    def method1(self, etc, etc):
        #Statements

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

পিএইচপি ভেরিয়েবলগুলিতে কী হিসাবে ব্যবহার করা যেতে পারে, তবে পাইথনগুলিতে অবজেক্টগুলি অনুলিখনযোগ্য এবং যদি আমি এর জন্য ডট স্বরলিপি ব্যবহার করি তবে এটি আমার ভেরির নামের সাথে একটি নতুন বৈশিষ্ট্য তৈরি করে যা আমার উদ্দেশ্য নয়।

বিষয়গুলিকে আরও পরিষ্কার করার জন্য:

def to_dict(self):
    '''this is what I already have'''
    d={}
    d["attr1"]= self.attr1
    d["attr2"]= self.attr2
    d["attr3"]= self.attr3
    return d

·

def to_dict(self):
    '''this is what I want to do'''
    d={}
    for v in my_python_obj.attributes:
        d[v] = self.v
    return d

আপডেট: গুণাবলীর সাথে আমি এই পদার্থটির কেবলমাত্র ভেরিয়েবলগুলি বোঝাতে চাইছি, পদ্ধতিগুলি নয়।


3
stackoverflow.com/questions/1251692/… কিছু সাহায্য হতে পারে।
শন

বিশেষ করে @sean, stackoverflow.com/a/1251789/4203 যেতে উপায়; আপনি predicateকলযোগ্য কলটি পাস করার জন্য argumentচ্ছিক যুক্তিটি ব্যবহার করবেন যা (আবদ্ধ?) ফাংশনগুলি (যে পদ্ধতিগুলি থেকে মুক্তি পায়) কে ফিল্টার করে দেয়।
হ্যাঙ্ক গে

প্রতি শ্রুতি, এই আপনার প্রশ্নের উত্তর দেয়? পাইথনে কোনও বস্তুর বৈশিষ্ট্য কীভাবে গণনা করা যায়?
ডেভিস হেরিং

উত্তর:


227

ধরে নিচ্ছি আপনার যেমন ক্লাস রয়েছে

>>> class Cls(object):
...     foo = 1
...     bar = 'hello'
...     def func(self):
...         return 'call me'
...
>>> obj = Cls()

dirঅবজেক্টে কল করা আপনাকে পাইথনের বিশেষ বৈশিষ্ট্য সহ সেই বস্তুর সমস্ত বৈশিষ্ট্য ফিরিয়ে দেয়। যদিও কিছু বস্তুর বৈশিষ্ট্য কলযোগ্য, যেমন পদ্ধতি।

>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo', 'func']

আপনি একটি তালিকা বোধগম্যতা ব্যবহার করে সর্বদা বিশেষ পদ্ধতিগুলি ফিল্টার আউট করতে পারেন।

>>> [a for a in dir(obj) if not a.startswith('__')]
['bar', 'foo', 'func']

অথবা আপনি যদি মানচিত্র / ফিল্টার পছন্দ করেন।

>>> filter(lambda a: not a.startswith('__'), dir(obj))
['bar', 'foo', 'func']

আপনি যদি পদ্ধতিগুলি ফিল্টার করতে চান তবে আপনি বিল্টিনটিকে callableএকটি চেক হিসাবে ব্যবহার করতে পারেন ।

>>> [a for a in dir(obj) if not a.startswith('__') and not callable(getattr(obj, a))]
['bar', 'foo']

আপনি নিজের বর্গ এবং এর উদাহরণ বস্তুর ব্যবহারের মধ্যে পার্থক্যও পরিদর্শন করতে পারেন।

>>> set(dir(Cls)) - set(dir(object))
set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__'])

1
এটি একটি খারাপ ধারণা, আমি এটির পরামর্শও দেব না, তবে আপনি যদি যান তবে কমপক্ষে সাবধানতা সরবরাহ করুন।
জুলিয়ান

2
@ মিঠাম @ পাবলো কী ভুল তা মূলত আপনার এটি করার দরকার নেই। কোনটি বৈশিষ্ট্যাবলী তুমি আগ্রহী হওয়া উচিত সমেত না একচেটিয়া । আপনি ইতিমধ্যে দেখেছেন, আপনি পদ্ধতি সহ, এবং এগুলি বাদ দেওয়ার যে কোনও প্রচেষ্টা ত্রুটিযুক্ত হবে, কারণ তারা callableবা এর মতো বাজে জিনিস জড়িত করতে চলেছে types.MethodType। যদি আমি "_foo" নামক একটি বৈশিষ্ট্য যুক্ত করি যা কিছু মধ্যবর্তী ফলাফল বা অভ্যন্তরীণ ডেটা কাঠামো সঞ্চয় করে? আমি যদি নিরীহভাবে ক্লাসে একটি বৈশিষ্ট্য যুক্ত করি তবে কী হবে, ক name, বলুন, এবং এখন হঠাৎ করে এটি যুক্ত হয়ে যায় gets
জুলিয়ান

3
@ জুলিয়ান উপরের কোডটি উভয়ই বেছে নেবে _fooএবং nameকারণ তারা এখন বস্তুর বৈশিষ্ট্য। আপনি যদি এগুলি অন্তর্ভুক্ত না করতে চান তবে আপনি সেগুলি তালিকা বোঝার শর্তে বাদ দিতে পারেন। উপরের কোডটি পাইথন আইডিয়মের একটি সাধারণ প্রচলিত শব্দ এবং পাইথন অবজেক্টগুলিকে অন্তর্নিম্ন করার জনপ্রিয় উপায়।
মাইথাম

30
আসলে আপত্তি .__ ডোক__ (সম্ভবত) এই উদ্দেশ্যে ভাল।
ডেভ

5
@ জুলিয়ান dir()কেবলমাত্র "মিথ্যা" যখন মেটাক্লাসগুলি (একটি চূড়ান্ত প্রান্তের কেস) পাস হয় বা শ্রেণিবদ্ধ বৈশিষ্ট্যযুক্ত ক্লাসগুলি @DynamicClassAttribute(অন্য একটি চূড়ান্ত প্রান্তের কেস) দ্বারা সজ্জিত হয় । উভয় ক্ষেত্রেই, dirs()মোড়কে কল করা এটি inspect.getmembers()সমাধান করে। স্ট্যান্ডার্ড অবজেক্টের জন্য, তবে এই সমাধানের তালিকা বোঝার পদ্ধতির অ-কলযোগ্যদের পুরোপুরি যথেষ্ট করে দেয় filter কিছু পাইথনিস্টরা এটিকে একটি "খারাপ ধারণা" হিসাবে লেবেল দেবে, কিন্তু ... তাদের প্রত্যেকের কাছে, আমি মনে করি?
সিসিল কারি

57

সাধারণভাবে __iter__আপনার ক্লাসে একটি পদ্ধতি রাখুন এবং অবজেক্ট বৈশিষ্ট্যগুলির মাধ্যমে পুনরাবৃত্তি করুন বা এই ক্লাসে এই মিক্সিন ক্লাসটি রাখুন।

class IterMixin(object):
    def __iter__(self):
        for attr, value in self.__dict__.iteritems():
            yield attr, value

তোমার শ্রেণী:

>>> class YourClass(IterMixin): pass
...
>>> yc = YourClass()
>>> yc.one = range(15)
>>> yc.two = 'test'
>>> dict(yc)
{'one': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 'two': 'test'}

এই শুধুমাত্র যখন কাজ করে oneএবং twoপরে সংজ্ঞায়িত করা হয় yc = YourClass()। প্রশ্নটি বিদ্যমান অ্যাটারিসের মধ্যে লুপিং সম্পর্কে জিজ্ঞাসা করে YourClass()। এছাড়াও, IterMixinক্লাসের উত্তরাধিকার সূচনা হিসাবে সর্বদা পাওয়া যায় না।
জিয়াও

4
vars(yc)অন্য শ্রেণীর উত্তরাধিকারী না হয়ে একই ফলাফল দেয়।
নাথান

1
আমার উপরের মন্তব্যটি বেশ সঠিক নয়; vars(yc)প্রায় একইরকম, তবে এটি আপনাকে যে অভিধানটি ফিরিয়ে দেয় সেটি হ'ল দৃষ্টান্তের নিজস্ব __dict__, সুতরাং এটির সংশোধন করা উদাহরণটিতে প্রতিফলিত হবে। আপনি যদি সাবধান না হন তবে এটি সমস্যার সৃষ্টি করতে পারে, তাই উপরের পদ্ধতিটি মাঝে মাঝে ভাল হতে পারে (যদিও অভিধানটি অনুলিপি করা সম্ভবত সহজ)। এছাড়াও, নোট করুন যে উপরে অভিধানটি ফিরে এসেছে উদাহরণ হিসাবে নয় __dict__, মানগুলি একই, সুতরাং যে কোনও পরিবর্তনীয় মানগুলি সংশোধন করা এখনও উদাহরণের বৈশিষ্ট্যগুলিতে প্রতিফলিত হবে।
নাথান

25

ইতিমধ্যে কয়েকটি উত্তর / মন্তব্যে উল্লিখিত হিসাবে পাইথন অবজেক্টগুলি তাদের বৈশিষ্ট্যগুলির একটি অভিধান ইতিমধ্যে সংরক্ষণ করে (পদ্ধতিগুলি অন্তর্ভুক্ত নয়)। এটি হিসাবে অ্যাক্সেস করা যায় __dict__, তবে আরও ভাল উপায়টি ব্যবহার করা হয় vars(তবে আউটপুট একই হয়)। নোট করুন যে এই অভিধানটি সংশোধন করা উদাহরণগুলিতে বৈশিষ্ট্যগুলিকে সংশোধন করবে! এটি দরকারী হতে পারে তবে এর অর্থ আপনি কীভাবে এই অভিধানটি ব্যবহার করেন সে সম্পর্কে আপনার যত্নবান হওয়া উচিত। এখানে একটি দ্রুত উদাহরণ:

class A():
    def __init__(self, x=3, y=2, z=5):
        self.x = x
        self._y = y
        self.__z__ = z

    def f(self):
        pass

a = A()
print(vars(a))
# {'x': 3, '_y': 2, '__z__': 5}
# all of the attributes of `a` but no methods!

# note how the dictionary is always up-to-date
a.x = 10
print(vars(a))
# {'x': 10, '_y': 2, '__z__': 5}

# modifying the dictionary modifies the instance attribute
vars(a)["_y"] = 20
print(vars(a))
# {'x': 10, '_y': 20, '__z__': 5}

ব্যবহার dir(a)করা একটি বিজোড়, একেবারে খারাপ না হলে এই সমস্যার দিকে মনোযোগ দিন। আপনার যদি সত্যই ক্লাসের সমস্ত বৈশিষ্ট্য এবং পদ্ধতিগুলি (যেমন বিশেষ পদ্ধতি সহ __init__) দ্বারা পুনরাবৃত্তি করতে হবে তবে এটি ভাল । যাইহোক, এটি আপনি যা চান তা মনে হচ্ছে না এবং এমনকি গৃহীত উত্তরগুলি পদ্ধতিগুলি সরানোর চেষ্টা করতে এবং কেবলমাত্র বৈশিষ্ট্যগুলি ছেড়ে যাওয়ার চেষ্টা করার জন্য কিছু ভঙ্গুর ফিল্টারিং প্রয়োগ করে এটি সম্পর্কে খারাপ ধারণা দেয়; Aউপরের সংজ্ঞায়িত শ্রেণীর জন্য এটি কীভাবে ব্যর্থ হবে তা আপনি দেখতে পারেন ।

(ব্যবহার __dict__বেশ কয়েকটি উত্তরে করা হয়েছে, তবে তারা প্রত্যেকে এটি সরাসরি ব্যবহার না করে অপ্রয়োজনীয় পদ্ধতিগুলি সংজ্ঞায়িত করে Only কেবলমাত্র একটি মন্তব্য ব্যবহার করার পরামর্শ দেয় vars)।


1
ওয়ার্স () পদ্ধতির সাথে আমি যে বিষয়টি বের করতে পারি নি তা হল ক্লাস এ এর ​​সদস্য যে পরিস্থিতিটি পরিচালনা করতে পারে তার আরেকটি বিষয় যা ব্যবহারকারীর দ্বারা সংজ্ঞায়িত শ্রেণির বি বি রয়েছে (ক) __repr __ () বলে মনে হচ্ছে এর বি সদস্য হিসাবে __repr __ (), যেমনটি আমি বুঝতে পারি, একটি স্ট্রিং ফেরত আসবে বলে মনে করা হচ্ছে। তবে আমি যখন ভারগুলি (ক) বলি, মনে হয় যে এই কলটি বি এর স্ট্রিং প্রতিনিধিত্ব করে ডিকের পরিবর্তে নেস্টেড
ডিক্ট ফিরিয়ে দেবে তার অর্থ হবে

1
আপনার যদি a.bকিছু কাস্টম ক্লাস থাকে Bতবে vars(a)["b"] is a.bএকজন যেমন আশা করবেন; অন্য কিছুই সত্যিই অর্থবহ হবে (এর a.bজন্য সিনট্যাকটিক চিনি হিসাবে ভাবেন a.__dict__["b"])। যদি আপনার কাছে থাকে d = vars(a)এবং কল করেন repr(d)তবে এটি তার repr(d["b"])নিজস্ব পুনঃ-স্ট্রিং ফেরতের অংশ হিসাবে কল করবে কারণ কেবল শ্রেণিই Bজানে যে কীভাবে স্ট্রিং হিসাবে উপস্থাপন করা উচিত।
নাথান

2

পাইথন অবজেক্টস তাদের ক্রেডিট (ফাংশন সহ) ডেকে একটি ডিকের মধ্যে সংরক্ষণ করে __dict__। বৈশিষ্ট্যগুলি সরাসরি অ্যাক্সেস করতে আপনি এটি ব্যবহার করতে পারেন (তবে সাধারণভাবে হওয়া উচিত নয়)। আপনি যদি কেবল একটি তালিকা চান, আপনি কল করতেও পারেন dir(obj), যা সমস্ত বৈশিষ্ট্যের নামের সাথে একটি পুনরাবৃত্তিযোগ্য ফেরত দেয়, যার পরে আপনি পাস করতে পারেন getattr

তবে ভেরিয়েবলের নামের সাথে কিছু করা দরকার সাধারণত খারাপ ডিজাইন। কেন এগুলি একটি সংগ্রহে রাখবেন না?

class Foo(object):
    def __init__(self, **values):
        self.special_values = values

তারপরে আপনি কীগুলি দিয়ে পুনরাবৃত্তি করতে পারেন for key in obj.special_values:


আপনি কী আরও কিছুটা ব্যাখ্যা করতে পারেন আমি কীভাবে সংগ্রহ করতে চাই যা অর্জন করতে চাই?
পাবলো মেসের

1
আমি বস্তুটিতে গতিশীলভাবে গুণাবলী যুক্ত করছি না। আমার সাথে থাকা ভেরিয়েবলগুলি দীর্ঘ সময়ের জন্য একই থাকবে, তবে আমি মনে করি যে আমি যা করতে চাই তার মতো কিছু করতে পেরে ভাল লাগবে।
পাবলো মেসচার

1
class someclass:
        x=1
        y=2
        z=3
        def __init__(self):
           self.current_idx = 0
           self.items = ["x","y","z"]
        def next(self):
            if self.current_idx < len(self.items):
                self.current_idx += 1
                k = self.items[self.current_idx-1]
                return (k,getattr(self,k))
            else:
                raise StopIteration
        def __iter__(self):
           return self

তারপরে এটিকে কেবল পুনরাবৃত্তিযোগ্য হিসাবে কল করুন

s=someclass()
for k,v in s:
    print k,"=",v

এটি খুব জটিল বলে মনে হচ্ছে। আমার যদি কোনও উপায় না থাকে তবে আমি এখনই যা করছি তার সাথে আমি লেগে থাকি।
পাবলো মেসের

0

এর সঠিক উত্তরটি হ'ল আপনার উচিত নয়। আপনি যদি এই ধরণের জিনিসটি কেবল একটি ডিক ব্যবহার করেন তবে আপনার স্পষ্টভাবে কিছু ধারক হিসাবে বৈশিষ্ট্য যুক্ত করতে হবে। আপনি সজ্জাকারীদের সম্পর্কে শিখার মাধ্যমে এটি স্বয়ংক্রিয় করতে পারেন।

বিশেষত, যাইহোক, আপনার উদাহরণের পদ্ধতি 1 কোনও গুণাবলীর ঠিক তত ভাল।


2
হ্যাঁ, আমি জানি আমার উচিত হবে না .. তবে এটি কীভাবে কাজ করে তা বুঝতে সহায়তা করে। আমি পিএইচপি ব্যাকগ্রাউন্ড থেকে এসেছি এবং প্রতিদিন এই ধরণের জিনিস করতাম
পাবলো মেসচার

আপনি আমাকে বিশ্বাস করেছেন। টো ডিক্ট () পদ্ধতিটি আপডেট করা এখন পর্যন্ত যে কোনও উত্তরের চেয়ে অনেক সহজ for
পাবলো মেসচার

1
এমন কি এমন কিছু লোক রয়ে গেছে যা কূটনৈতিক পরামর্শ থেকে বিরত থাকবে? আপনি যদি সাবধান না হন তবে ডায়নামিক প্রোগ্রামিং আপনাকে জ্বালিয়ে দেবে, তবে বৈশিষ্ট্যগুলি ব্যবহার করার মতো ভাষায় রয়েছে।
হেনরিক ভেন্ডেলবো

0

অজগর জন্য 3.6

class SomeClass:

    def attr_list(self, should_print=False):

        items = self.__dict__.items()
        if should_print:
            [print(f"attribute: {k}    value: {v}") for k, v in items]

        return items

6
আপনি কি আপনার পোস্টগুলিতে কিছু ব্যাখ্যা যোগ করতে পারেন, যাতে অ পেশাগত পাইথনবাদীরাও আপনার উত্তরগুলি থেকে উপকৃত হতে পারে?
not2quit

-3

সমস্ত পাইথোনিয়ার উদ্যোগের জন্য আমি নিশ্চিত যে জোহান ক্লিজ আপনার কৌতুকবাদকে অনুমোদন করবে;)। আমি এই উত্তরটি ছেড়ে দিচ্ছি এটির অবজ্ঞার বিষয়টি রাখুন এটি আসলে আমাকে আরও বিশ্বাসী করে তুলেছে। একটি মন্তব্য আপনি মুরগি ছেড়ে!

অজগর জন্য 3.6

class SomeClass:

    def attr_list1(self, should_print=False):

        for k in self.__dict__.keys():
            v = self.__dict__.__getitem__(k)
            if should_print:
                print(f"attr: {k}    value: {v}")

    def attr_list(self, should_print=False):

        b = [(k, v) for k, v in self.__dict__.items()]
        if should_print:
            [print(f"attr: {a[0]}    value: {a[1]}") for a in b]
        return b

এই প্রশ্নে আপনার দুটি উত্তর থাকার কারণ আছে কি?
নাথান

@ নাথান সেখানে আছে কারণ একটি আরও ভার্জোজ এবং অন্যটি বেশি পাইথোনিয়ান। আমি জানি না কোনটি দ্রুত চলে তাই আমি পাঠককে বেছে নেওয়ার সিদ্ধান্ত নিয়েছি।
রাবার হাঁস

@ নাথান আপনি কি অজগর বা স্ট্যাক ওভারফ্লো পুলিশ? বিভিন্ন কোডিং শৈলী আছে। আমি একটি পাইথোনিককে পছন্দ করি না কারণ আমি অনেক ভাষা এবং প্রযুক্তিগুলিতে কাজ করি এবং আমি মনে করি এটি আইডিসিঙ্ক্র্যাটিক হতে পারে। তবুও Iist বোধগম্যতা শীতল এবং সংক্ষিপ্ত। তাহলে কেন আলোকিত পাঠক উভয়েরই সামর্থ নেই?
রাবার হাঁস

সমস্ত পাইথোনিয়ার উদ্যোগের জন্য আমি নিশ্চিত যে জোহান ক্লিজ আপনার কৌতুকবাদকে অনুমোদন করবে;)। আমি এই উত্তরটি ছেড়ে দিচ্ছি এটির অবজ্ঞার বিষয়টি রাখুন এটি আসলে আমাকে আরও বিশ্বাসী করে তুলেছে। একটি মন্তব্য আপনি মুরগি ছেড়ে!
রাবার হাঁস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.