2016-08-05 14 views
11

तुलना करें सी ++ में निम्न कोड:अजगर में तर्क के रूप में "एक आभासी कार्य करने के लिए सूचक" एक पासिंग

#include <iostream> 
#include <vector> 

struct A 
{ 
    virtual void bar(void) { std::cout << "one" << std::endl; } 
}; 

struct B : public A 
{ 
    virtual void bar(void) { std::cout << "two" << std::endl; } 
}; 

void test(std::vector<A*> objs, void (A::*fun)()) 
{ 
    for (auto o = objs.begin(); o != objs.end(); ++o) 
    { 
    A* obj = (*o); 
    (obj->*fun)(); 
    } 
} 

int main() 
{ 
    std::vector<A*> objs = {new A(), new B()}; 

    test(objs, &A::bar); 
} 

और में अजगर:

class A: 

    def bar(self): 
     print("one") 


class B(A): 

    def bar(self): 
     print("two") 


def test(objs, fun): 
    for o in objs: 
     fun(o) 

objs = [A(), B()] 
test(objs, A.bar) 

सी ++ कोड प्रिंट होगा:

one 
two 

जबकि अजगर कोड प्रिंट होगा

one 
one 

मैं "एक पद्धति के लिए एक सूचक" पारित कैसे कर सकते हैं और ओवरराइड एक करने के लिए इसे हल, सी ++ में के रूप में अजगर में समान व्यवहार को प्राप्त करने?

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

+0

तुम इतनी है कि आप कर रहे हैं * * में अर्थ विज्ञान को दोहराने की कोशिश नहीं कर अजगर कोड की संरचना माना जाता है:

अपने उदाहरण में, केवल बात यह है कि बदलने के लिए की आवश्यकता होगी test कार्य करने के लिए कॉल है एक अलग भाषा? मुझे लगता है कि ऐसा करने के अधिक पाइथोनिक तरीके से विरासत या गतिशील प्रेषण के साथ कुछ लेना देना नहीं है। –

+0

मैं मानता हूँ, समस्या यह है कि मैं अपनी समस्या के लिए मन में एक बेहतर पैटर्न नहीं है। कृपया समस्या विवरण के लिए संपादन देखें। मैं एक पायथनिक समाधान पसंद करेंगे। –

+0

लगता है जैसे आप विज़िटर पैटर्न चाहते हैं। –

उत्तर

9

अपने संपादित के बारे में, एक बात तुम कर सकते हो एक छोटे से आवरण लैम्ब्डा कि विधि आप संदर्भ लेना चाहते हैं कॉल का उपयोग करें। इस तरह विधि कॉल स्ट्रिंग-आधारित पहुंच के आधार पर कुछ जटिल होने के बजाय "नियमित पायथन कोड" जैसा दिखता है।

test(objs, (lambda x: x.bar())) 
+0

यह एक क्लीनर, समस्या को हल करने के pythonic तरीका की तरह लगता है। हालांकि, यह गतिशील प्रेषण की अनुमति नहीं देता है, जो कुछ अन्य उत्तर के साथ अनुकरण करना संभव है (अगर किसी को इसकी आवश्यकता है)। –

+0

मुझे समझ में नहीं आता कि आपका क्या मतलब है। 'बार' विधि कॉल को गतिशील रूप से प्रेषित किया जा रहा है। – hugomg

+0

मेरी शब्दावली बंद हो सकती है। क्या मैं का मतलब है कि इस दृष्टिकोण के साथ, यह संभव नहीं इस मामले में जहां 'bar' में उदाहरण के लिए' A' में और 'b' में विभिन्न तर्क लेता है,, संभाल करने के लिए है था' b' यह एक अतिरिक्त तर्क लेता है। स्ट्रिंग दृष्टिकोण में, 'test'' obj' के प्रकार के आधार पर 'bar' पर विभिन्न तर्क लागू करने का चयन कर सकता है। –

4

निम्नलिखित उत्पादन आप चाहते हैं पैदा करता है:

class A: 
    def bar(self): 
     print("one") 

class B(A): 
    def bar(self): 
     print("two") 

def test(objs, funcname): 
    noop = lambda: None 
    for o in objs: 
     getattr(o, funcname, noop)() 

objs = [A(), B()] 
test(objs, "bar") 
+0

यह सचमुच सवाल का जवाब लेकिन मुझे नहीं लगता यह बिल्कुल का प्रतिनिधित्व करता है क्या ओ पी पूरा करने के लिए कोशिश कर रहा है है। निश्चित रूप से यह कार्यक्रम एक और जटिल उदाहरण में स्केल नहीं करेगा। –

+0

@uh ओह: आईएमओ यह सवाल का जवाब देता है और प्रतिनिधित्व करता है कि ओपी क्या पूरा करने की कोशिश कर रहा है, क्योंकि पाइथन में पॉइंटर्स नहीं हैं। इसके अलावा इसे "स्केल" के साथ-साथ सी ++ संस्करण होना चाहिए। – martineau

+1

यह मेरा मुद्दा था। पायथन में पॉइंटर्स या एकाधिक प्रेषण नहीं है, इसलिए मैं वही * उद्देश्य * पूरा करने का एक और बेवकूफ तरीका उम्मीद करूंगा। यह सब कुछ करने के गलत तरीके को मजबूत करता है। –

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