শ্রেণি যে সংজ্ঞায়িত পদ্ধতি


89

পাইথনের যে পদ্ধতিটি সংজ্ঞায়িত হয়েছে আমি কীভাবে ক্লাস পেতে পারি?

আমি নীচের উদাহরণটি " __main__.FooClass" মুদ্রণ করতে চাই :

class FooClass:
    def foo_method(self):
        print "foo"

class BarClass(FooClass):
    pass

bar = BarClass()
print get_class_that_defined_method(bar.foo_method)

পাইথনের কোন সংস্করণ আপনি ব্যবহার করছেন? ২.২ এর আগে আপনি im_class ব্যবহার করতে পারতেন তবে এটি সীমাবদ্ধ স্ব-বস্তুর প্রকারটি প্রদর্শন করতে পরিবর্তন করা হয়েছিল।
ক্যাথি ভ্যান স্টোন

4
জানা ভাল. তবে আমি ২.6 ব্যবহার করছি।
জেসি অ্যালড্রিজ

উত্তর:


70
import inspect

def get_class_that_defined_method(meth):
    for cls in inspect.getmro(meth.im_class):
        if meth.__name__ in cls.__dict__: 
            return cls
    return None

4
ধন্যবাদ, নিজে থেকে এটি বের করতে আমার কিছুটা সময় লাগত
ডেভিড

সাবধান, সব শ্রেণি প্রয়োগ হয় না __dict__! কখনও কখনও __slots__ব্যবহৃত হয়। getattrপদ্ধতিটি ক্লাসে থাকলে পরীক্ষার জন্য ব্যবহার করা ভাল ।
কোডি কোডমনেকি

16
জন্য Python 3, দয়া করে এই উত্তর দেখুন
ইওয়েল

27
আমি পাচ্ছি:'function' object has no attribute 'im_class'
জিতরেক্স

4
পাইথন ২.7 এ এটি কার্যকর হয় না। 'Im_class' অনুপস্থিত সম্পর্কে একই ত্রুটি।
রেডএক্স

8

ধন্যবাদ Sr2222 দেখানোর জন্য যে আমি পয়েন্টটি মিস করছি ...

এখানে সংশোধিত পদ্ধতিটি যা অ্যালেক্সের মতো তবে কিছুই আমদানির প্রয়োজন হয় না। আমি যদিও এটি উন্নতি বলে মনে করি না, যদি না উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণির একটি বৃহত্তর শ্রেণিবৃত্তি না হয় কারণ এই পদ্ধতিটি সংজ্ঞায়িত শ্রেণীর সন্ধান পাওয়া মাত্রই থামবে, পুরো উত্তরাধিকারের মতো ফিরে আসার পরিবর্তে getmro। যেমনটি বলা হয়েছে, এটি খুব সম্ভাবনাময় একটি দৃশ্য।

def get_class_that_defined_method(method):
    method_name = method.__name__
    if method.__self__:    
        classes = [method.__self__.__class__]
    else:
        #unbound method
        classes = [method.im_class]
    while classes:
        c = classes.pop()
        if method_name in c.__dict__:
            return c
        else:
            classes = list(c.__bases__) + classes
    return None

এবং উদাহরণ:

>>> class A(object):
...     def test(self): pass
>>> class B(A): pass
>>> class C(B): pass
>>> class D(A):
...     def test(self): print 1
>>> class E(D,C): pass

>>> get_class_that_defined_method(A().test)
<class '__main__.A'>
>>> get_class_that_defined_method(A.test)
<class '__main__.A'>
>>> get_class_that_defined_method(B.test)
<class '__main__.A'>
>>> get_class_that_defined_method(C.test)
<class '__main__.A'>
>>> get_class_that_defined_method(D.test)
<class '__main__.D'>
>>> get_class_that_defined_method(E().test)
<class '__main__.D'>
>>> get_class_that_defined_method(E.test)
<class '__main__.D'>
>>> E().test()
1

অ্যালেক্স সমাধান একই ফলাফল দেয়। যতক্ষণ না অ্যালেক্সের পদ্ধতির ব্যবহার করা যায় ততক্ষণ আমি এটির পরিবর্তে এটি ব্যবহার করব।


Cls().meth.__self__কেবলমাত্র আপনাকে সেই উদাহরণটি Clsনির্দিষ্ট নির্দিষ্ট ক্ষেত্রে আবদ্ধ meth। এটি অনুরূপ Cls().meth.im_class। আপনি যদি class SCls(Cls), SCls().meth.__self__আপনি একটি পাবেন SClsউদাহরণস্বরূপ, একটি Clsউদাহরণ হিসেবে বলা যায়। ওপি Clsযা চায় তা পেতে চায় , যা এটি প্রদর্শিত হয় কেবলমাত্র অ্যালেক্স মার্টেলির মতো এমআরও হাঁটা দ্বারা উপলব্ধ।
সিলাস রায়

@ sr2222 আপনি ঠিক বলেছেন আমি ইতিমধ্যে শুরু হিসাবে উত্তরটি পরিবর্তন করেছি যদিও আমি মনে করি অ্যালেক্স সমাধানটি আরও কমপ্যাক্ট।
এস্তানি

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

সময় এবং সময় আবার, "খুব সম্ভাবনাময় পরিস্থিতি" প্রোগ্রামিংয়ে ঘটে in খুব কমই বিপর্যয় ঘটাচ্ছে। সাধারণভাবে, কোডিং করার সময় "XY.Z% এটি কখনও ঘটবে না" চিন্তার ধরণটি অত্যন্ত লম্পট চিন্তার সরঞ্জাম। এটি ব্যবহার করবেন না। 100% সঠিক কোড লিখুন।
ulidtko

@ জুলিদকো আমার মনে হয় আপনি ব্যাখ্যাটি ভুলভাবে লিখেছেন। এটি নির্ভুলতা নয় গতি সম্পর্কে। কোনও "নিখুঁত" সমাধান নেই যা সমস্ত ক্ষেত্রে ফিট করে, অন্যথায় যেমন কেবলমাত্র একটি বাছাই করা অ্যালগরিদম থাকবে। এখানে প্রস্তাবিত সমাধানটি "বিরল" ক্ষেত্রে দ্রুত হওয়া উচিত। যেহেতু পাঠযোগ্যতার পরে গতি 99% শতাংশে আসে, তাই এই সমাধানটি "কেবলমাত্র" বিরল ক্ষেত্রেই এর চেয়ে ভাল সমাধান হতে পারে। কোডটি যদি আপনি এটি না পড়ে থাকেন তবে এটি 100% সঠিক, যদি আপনার ভয় ছিল।
ইস্তানী

6

আমি জানি না কেন কেন কেউ এটিকে সামনে আনেনি বা যখন নরকের মতো ধীর হয় তখন শীর্ষের উত্তরে 50 টি উত্স থাকবে কেন তবে আপনি নিম্নলিখিতগুলিও করতে পারেন:

def get_class_that_defined_method(meth):
    return meth.im_class.__name__

অজগর 3 এর জন্য আমি বিশ্বাস করি এটি পরিবর্তিত হয়েছে এবং আপনাকে এটি খতিয়ে দেখতে হবে .__qualname__


4
হুঁ। অজগর ২.7-এ করার সময় আমি সংজ্ঞায়িত শ্রেণিটি দেখছি না - আমি যে ক্লাসটি পদ্ধতিটি আহ্বান করা হয়েছিল সেখানেই ক্লাস পাচ্ছি, যেখানে এটি সংজ্ঞায়িত করা হয়নি ...
F1Rumors

5

পাইথন 3 এ, আপনার যদি সত্যিকারের শ্রেণীর অবজেক্টের প্রয়োজন হয় তবে আপনি এটি করতে পারেন:

import sys
f = Foo.my_function
vars(sys.modules[f.__module__])[f.__qualname__.split('.')[0]]  # Gets Foo object

যদি ফাংশনটি কোনও নেস্টেড শ্রেণীর অন্তর্ভুক্ত হতে পারে তবে আপনাকে নিম্নলিখিত হিসাবে পুনরাবৃত্তি করতে হবে:

f = Foo.Bar.my_function
vals = vars(sys.modules[f.__module__])
for attr in f.__qualname__.split('.')[:-1]:
    vals = vals[attr]
# vals is now the class Foo.Bar

2

পাইথন ঘ

এটি খুব সাধারণ উপায়ে সমাধান করেছেন:

str(bar.foo_method).split(" ", 3)[-2]

এই দেয়

'FooClass.foo_method'

ক্লাস এবং ফাংশনটির নাম আলাদাভাবে পেতে ডটে বিভক্ত করুন


বাহ কি বাঁচা!
ব্যবহারকারী 371212978

1

আমি কিছুটা অনুরূপ কিছু করতে শুরু করেছিলাম, মূলত ধারণাটি পরীক্ষা করা হয়েছিল যখনই কোনও বেস ক্লাসে কোনও পদ্ধতি উপ-শ্রেণিতে প্রয়োগ করা হয়েছিল বা হয়নি। একটি মধ্যবর্তী শ্রেণি আসলে পদ্ধতিটি বাস্তবায়ন করছিল তখন আমি সনাক্ত করতে পারি না যেভাবে আমি এটি প্রাথমিকভাবে করেছি out

এটির জন্য আমার কাজটি বেশ সহজ ছিল; একটি পদ্ধতি বৈশিষ্ট্য নির্ধারণ এবং এর উপস্থিতি পরে পরীক্ষা করে। এখানে পুরো জিনিসটির সরলীকরণ রয়েছে:

class A():
    def method(self):
        pass
    method._orig = None # This attribute will be gone once the method is implemented

    def run_method(self, *args, **kwargs):
        if hasattr(self.method, '_orig'):
            raise Exception('method not implemented')
        self.method(*args, **kwargs)

class B(A):
    pass

class C(B):
    def method(self):
        pass

class D(C):
    pass

B().run_method() # ==> Raises Exception: method not implemented
C().run_method() # OK
D().run_method() # OK

আপডেট: আসলে method()থেকে কল করুন run_method()(এটি স্পিরিট নয়?) এবং এটিকে সমস্ত যুক্তিটি পদ্ধতিতে বিনা পরিবর্তিতভাবে পাস করার জন্য।

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

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