अपने मूल जवाब में (जो मैं नष्ट कर दिया क्योंकि यह सिर्फ सादा गलत था) मैंने कहा कि मैं इस तरह कर रहा पर विचार करेंगे:
class RandomPerson(Person):
def __init__(self):
rand_person = random.choice((John, Kyle))()
self.__dict__ = rand_person.__dict__
इस तरह पाइथन Borg idiom का एक अनुकूलन है; विचार यह था कि किसी ऑब्जेक्ट के बारे में जो कुछ भी मायने रखता है वह __dict__
में निहित है।
हालांकि, यह केवल तभी काम करता है जब समान वर्ग (जो आप बोर्ग मुहावरे में कर रहे हैं) की ओवरराइटिंग ऑब्जेक्ट्स; ऑब्जेक्ट __dict__
में ऑब्जेक्ट क्लास से संबंधित राज्य जानकारी, ऑब्जेक्ट क्लास नहीं है।
यह तो जैसे एक वस्तु के वर्ग बाहर स्विच करने के लिए संभव है:
class RandomPerson(Person):
def __init__(self):
rand_person = random.choice((John, Kyle))
self.__class__ = rand_person
हालांकि, यह इस तरह से कर रही है मतलब यह होगा कि RandomPerson
करने के लिए कॉल तो प्रति एक उदाहरण के लिए वापस नहीं होगा RandomPerson
के अपने आवश्यकता, लेकिन Kyle
या John
का। तो यह कोई नहीं है।
यहाँ एक तरीका है कि में कार्य करता हैKyle
या John
की तरह एक RandomPerson
वस्तु प्राप्त करने के लिए है, लेकिन नहीं है:
class RandomPerson(Person):
def __new__(cls):
new = super().__new__(cls)
new.__dict__.update(random.choice((Kyle,John)).__dict__)
return new
यह एक - बहुत से यह कर को छोड़कर, बोर्ग मुहावरा के समान उदाहरण वस्तुओं के बजाए कक्षाएं और हम केवल चयनित कक्षा के वर्तमान संस्करण की प्रतिलिपि बना रहे हैं - वास्तव में बहुत बुरा है: हमने RandomPerson
वर्ग को लॉबोटोमाइज्ड किया है और (यादृच्छिक रूप से) Kyle
याके दिमाग को फंस गया है जगह में 0 वर्ग।और वहाँ कोई संकेत नहीं है, दुर्भाग्य से, कि यह हुआ:
>>> rperson = RandomPerson()
>>> assert isinstance(rperson,Kyle) or isinstance(rperson,John)
AssertionError
तो हम अभी भी वास्तव में subclassed नहीं किया है Kyle
या John
। इसके अलावा, यह वास्तव में वास्तव में बुराई है। तो कृपया इसे तब तक न करें जब तक आपके पास वास्तव में कोई अच्छा कारण न हो।
अब, यह सोचते हैं आप वास्तव में एक अच्छा कारण है, इसके बाद के संस्करण समाधान काफी अच्छा होना चाहिए, अगर तुम सब के बाद कर रहे हैं सुनिश्चित करें कि आप Kyle
या John
से किसी भी वर्ग राज्य सूचना (तरीकों और वर्ग विशेषताएँ) का उपयोग कर सकते कर रही है RandomPerson
के साथ। हालांकि, जैसा कि पहले बताया गया है, RandomPerson
अभी भी एक वास्तविक उप-वर्ग नहीं है।
जैसा कि मैं कह सकता हूं कि वास्तव में यादृच्छिक रूप से किसी ऑब्जेक्ट की कक्षा को उपनिवेशित करने का कोई तरीका नहीं है और वर्ग को कई उदाहरण रचनाओं में राज्य बनाए रखने का कोई तरीका नहीं है। आपको इसे नकली करना होगा।
एक तरह से नकली करने के लिए इसे RandomPerson
John
और Kyle
abstract baseclass module and __subclasshook__
का उपयोग कर, और अपने Person
वर्ग को जोड़ने की एक उपवर्ग पर विचार किया जा करने की अनुमति है। ऐसा लगता है कि यह एक अच्छा समाधान होगा क्योंकि Person
कक्षा एक इंटरफ़ेस है और इसका उपयोग सीधे नहीं किया जा रहा है, वैसे भी।
यहाँ ऐसा करने के लिए एक तरह से है: - हालांकि यह तकनीकी रूप से एक उपवर्ग नहीं है -
class Person(object):
__metaclass__ = abc.ABCMeta
def drive(self, f, t):
raise NotImplementedError
@classmethod
def __subclasshook__(cls, C):
if C.identity is cls:
return True
return NotImplemented
class John(Person):
def drive(self, f, t):
print "John drove from %s to %s" % (f,t)
class Kyle(Person):
def drive(self, f, t):
print "Kyle drove from %s to %s" % (f,t)
class RandomPerson(Person):
identity = None
def __new__(cls):
cls.identity = random.choice((John,Kyle))
new = super().__new__(cls)
new.__dict__.update(cls.identity.__dict__)
return new
>>> type(RandomPerson())
class RandomPerson
>>> rperson = RandomPerson()
>>> isinstance(rperson,John) or isinstance(rperson,Kyle)
True
अब RandomPerson
Kyle
या John
का एक उपवर्ग, माना जाता है और यह भी राज्य के शेयरोंKyle
या John
का। वास्तव में, यह दो बार, यादृच्छिक रूप से, प्रत्येक बार एक नया उदाहरण बनाया जाता है (या जब RandomPerson.identity
बदल जाता है) के बीच आगे और पीछे स्विच करेगा। चीजें इस तरह से कर रही है की एक और प्रभाव: यदि आप कई RandomPerson
मामले हैं तो वे सब शेयर की जो कुछ भी RandomPerson
उस क्षण में होने वाला राज्य - यानी, rperson1
Kyle
जा रहा है बाहर शुरू हो सकता है, और फिर rperson2
instantiated है जब , rperson2
और rperson1
दोनों John
हो सकते हैं (या वे Kyle
दोनों हो सकते हैं और फिर पर स्विच कर सकते हैं जब rperson3
बनाया गया है)।
कहने की जरूरत नहीं है, यह बहुत अजीब व्यवहार है। वास्तव में यह बहुत अजीब है, मेरा संदेह यह है कि आपके डिजाइन को एक पूर्ण ओवरहाल की आवश्यकता है। मुझे सच में नहीं लगता कि ऐसा करने के लिए बहुत अच्छा कारण है (शायद किसी पर बुरा मजाक बजाए)।
आप अपने Person
वर्ग में इस व्यवहार मिश्रण नहीं करना चाहते हैं, तो आप भी इसे अलग कर सकता है:
class Person(object):
def drive(self, f, t):
raise NotImplementedError
class RandomPersonABC():
__metaclass__ = abc.ABCMeta
@classmethod
def __subclasshook__(cls, C):
if C.identity is cls:
return True
return NotImplemented
class John(Person, RandomPersonABC):
def drive(self, f, t):
print "John drove from %s to %s" % (f,t)
class Kyle(Person, RandomPersonABC):
def drive(self, f, t):
print "Kyle drove from %s to %s" % (f,t)
class RandomPerson(Person):
identity = None
def __new__(cls):
cls.identity = random.choice((John,Kyle))
new = super().__new__(cls)
new.__dict__.update(cls.identity.__dict__)
return new
एक यादृच्छिक वर्ग से विरासत के लिए, हालांकि पायथन में संभव है, आपकी समस्या का एक बहुत ही सरल समाधान नहीं लगता है: बस एक कारखाने समारोह का उपयोग करें। मैं एक फैक्ट्री फ़ंक्शन के साथ जाऊंगा जो यादृच्छिक रूप से आपके व्यक्ति वर्गों में से एक को तुरंत चालू करता है और उस उदाहरण को लौटाता है, उदा। वर्गों की सूची से यादृच्छिक रूप से कक्षा चुनकर। फ़ैक्टरी फ़ंक्शन पर कॉल आपके रैंडमपर्सन कन्स्ट्रक्टर कॉल की तरह दिखता है। –
यह नहीं कि आपके वास्तविक प्रश्न के साथ इसका कोई संबंध नहीं है, लेकिन आपके पास अलग 'जॉन' और 'केली' ऑब्जेक्ट्स क्यों हैं? जॉन और केली नाम 'व्यक्ति' के गुण हैं (जैसे ऊंचाई/वजन/बालों का रंग/आंखों का रंग, आदि)। –
@jacdeh मेरे लिए एक होमवर्क प्रश्न की तरह लगता है जिसे बुरी तरह से सूचित किया गया है (या तो प्रोफेसर या ओपी द्वारा)। –