2010-04-08 17 views
6

मैंक्या पाइथन कक्षा में सभी कार्यों को लूप करने और निष्पादित करने का कोई तरीका है?

class Foo(): 
    function bar(): 
     pass 

    function foobar(): 
     pass 

बल्कि इस प्रकार एक के बाद प्रत्येक कार्य एक को क्रियान्वित करने से:

x = Foo() 
x.bar() 
x.foobar() 

वहाँ लूप करने के लिए निर्मित एक तरीका है और अनुक्रम जिसमें वे कर रहे हैं में प्रत्येक कार्य को अंजाम कक्षा में लिखा है?

उत्तर

6

नहीं। आप Foo.__dict__ तक पहुंच सकते हैं, और प्रत्येक मान को बदले में कॉल कर सकते हैं (गैर-कॉल करने योग्य सदस्यों के लिए त्रुटियों को पकड़ना), लेकिन आदेश संरक्षित नहीं है।

for callable in Foo.__dict__.values(): 
    try: 
     callable()  
    except TypeError: 
     pass 

यह मानता है कि आपके कार्यों में से कोई भी कार्य पैरामीटर नहीं लेता है।

5

चूंकि पाइथन एक शब्दकोश में कक्षा के तरीकों (और अन्य विशेषताओं) को संग्रहीत करता है, जो मूल रूप से अनियंत्रित है, यह असंभव है।

आप के बारे में परवाह नहीं करते हैं, का उपयोग वर्ग के __dict__:

x = Foo() 
results = [] 
for name, method in Foo.__dict__.iteritems(): 
    if callable(method): 
     results.append(method(x)) 

यह भी काम करता है समारोह अतिरिक्त पैरामीटर लेता है - सिर्फ उन्हें वर्ग के उदाहरण के बाद डाल दिया।

+0

अगर मुझे आदेश की परवाह नहीं है तो ऐसा करने का कोई तरीका? – curious

+0

निश्चित रूप से, मैं जवाब संपादित कर दूंगा। –

8
def assignOrder(order): 
    @decorator 
    def do_assignment(to_func): 
    to_func.order = order 
    return to_func 
    return do_assignment 

class Foo(): 

    @assignOrder(1) 
    def bar(self): 
    print "bar" 

    @assignOrder(2) 
    def foo(self): 
    print "foo" 

    #don't decorate functions you don't want called 
    def __init__(self): 
    #don't call this one either! 
    self.egg = 2 

x = Foo() 
functions = sorted(
      #get a list of fields that have the order set 
      [ 
       getattr(x, field) for field in dir(x) 
       if hasattr(getattr(x, field), "order") 
      ], 
      #sort them by their order 
      key = (lambda field: field.order) 
      ) 
for func in functions: 
    func() 

def bar(self) ऊपर हास्यास्पद @assignOrder(1) लाइन ऐसा ट्रिगर करता:

Foo.bar = assignOrder(1)(Foo.bar) 

assignOrder(1) एक समारोह है कि एक और समारोह लेता देता है, यह (क्षेत्र order जोड़ने और 1 करने के लिए इसे स्थापित करने) बदलता है और यह रिटर्न । इस फ़ंक्शन को तब सजाए जाने वाले फ़ंक्शन पर बुलाया जाता है (इसके order फ़ील्ड इस प्रकार सेट हो जाता है); नतीजा मूल कार्य को बदल देता है।

यह कह रही है की एक अधिक सजावटी, अधिक पठनीय और अधिक maintainable तरीका: (और अपने वर्ग बयान मैं हूँ में खाली कोष्ठकों से

def bar(self): 
    print "bar" 
    Foo.bar.order = 1 
+0

+1 - वाह - समारोह सजावट का उत्कृष्ट उपयोग! –

+2

यदि संभव हो तो 'eval' का उपयोग न करने का प्रयास करें। इस तरह कुछ काम करना चाहिए: 'हैर (आर) में फ़ील्ड के लिए गेट (एक्स) फ़ील्ड, अगर हैट्रर (गेटैटर (एक्स, फील्ड),' ऑर्डर ')] ' –

+0

मुझे पता था कि एक बेहतर तरीका होना चाहिए :) – badp

1

जब तक आप केवल अजगर 3.x में रुचि रखते हैं के रूप में अनुमान लगाओ कि आप हो सकते हैं), तो वास्तव में सजावटकर्ताओं के बिना ऐसा करने का एक आसान तरीका है: पायथन 3 आपको कक्षा के परिभाषित होने पर उपयोग करने के लिए ऑब्जेक्ट जैसे अपना शब्दकोश प्रदान करने की अनुमति देता है।

निम्नलिखित कोड लाइनों के पिछले कुछ के लिए छोड़कर PEP3115 से है जो मैं क्रम में बाहर तरीकों मुद्रित करने के लिए कहा:

# The custom dictionary 
class member_table(dict): 
    def __init__(self): 
    self.member_names = [] 

    def __setitem__(self, key, value): 
    # if the key is not already defined, add to the 
    # list of keys. 
    if key not in self: 
     self.member_names.append(key) 

    # Call superclass 
    dict.__setitem__(self, key, value) 

# The metaclass 
class OrderedClass(type): 

    # The prepare function 
    @classmethod 
    def __prepare__(metacls, name, bases): # No keywords in this case 
     return member_table() 

    # The metaclass invocation 
    def __new__(cls, name, bases, classdict): 
     # Note that we replace the classdict with a regular 
     # dict before passing it to the superclass, so that we 
     # don't continue to record member names after the class 
     # has been created. 
     result = type.__new__(cls, name, bases, dict(classdict)) 
     result.member_names = classdict.member_names 
     return result 

class MyClass(metaclass=OrderedClass): 
    # method1 goes in array element 0 
    def method1(self): 
    pass 

    # method2 goes in array element 1 
    def method2(self): 
    pass 

x = MyClass() 
print([name for name in x.member_names if hasattr(getattr(x, name), '__call__')]) 
1

शायद कम से कम तरीकों में से एक है (वर्ग के नाम सी है):

for func in filter(lambda x: callable(x), C.__dict__.values()): 
    pass # here func is the next function, you can execute it here 

फिल्टर अभिव्यक्ति वर्ग सी के सभी कार्यों रिटर्न

या एक लाइन में:

[func() for func in filter(lambda x: callable(x), C.__dict__.values())] 

आप किसी भी तरह आदेश कर सकते हैं काम करता है, उदाहरण के लिए, छोटे से अधिक जटिल अभिव्यक्ति द्वारा उनके नाम की lexicographical क्रम से।

संबंधित मुद्दे

 संबंधित मुद्दे