2008-10-28 14 views
31

क्या पाइथन में एक ही कक्षा के दो (पहले से मौजूद) उदाहरणों के बीच सभी गुणों की प्रतिलिपि बनाने के लिए कोई लाइब्रेरी विधि है? मेरा मतलब है, अपाचे कॉमन्स प्रॉपर्टी यूटिलस बीन कॉपप्रॉपर्टीज()पायथन में ऑब्जेक्ट के सभी गुणों को दूसरी ऑब्जेक्ट में कॉपी करने के लिए कैसे?

धन्यवाद!

उत्तर

26

अपने वर्ग विशेष गुण का उपयोग अपने सभी विशेषताओं __dict__ में जमा हो जाती लिए __getitem__ या __setitem__ संशोधित नहीं करता है यदि ऐसा है तो आप कर सकते हैं:

nobj.__dict__ = oobj.__dict__.copy() # just a shallow copy 

आप अजगर गुण का उपयोग करते हैं आप inspect.getmembers() को देखो और बाहर फ़िल्टर करना चाहिए जिन्हें आप प्रतिलिपि बनाना चाहते हैं।

44

destination.__dict__.update(source.__dict__) आज़माएं।

+1

मीठे! अब मैं argparse तर्कों को पारित कर सकता हूं और नामस्थान वस्तु के स्थान पर इसे आपूर्ति करने के बजाय उन्हें '__init__' में एक बार ऑब्जेक्ट में कॉपी कर सकता हूं और उसके बाद एक और' init' कॉल कर सकता हूं। क्या कोई स्रोत नहीं है ''vars()' 'स्रोत के बजाय' vars (स्रोत) 'के रूप में' vars() 'का उपयोग न करें .__ dict__'? – mlt

+0

@mlt: प्रलेखन में विवरण पढ़ना, न कि मुझे पता है। –

+0

मुझे यह पसंद है क्योंकि यह 'गंतव्य' के मौजूदा गुणों को फेंक नहीं देगा जब' स्रोत 'में कोई समान गुण नहीं है। – ArtOfWarfare

2

मैं आपको नीचे-संशोधित प्रतिलिपि जानता हूं, लेकिन मैं असहमत हूं। dict मैनिपुलेशन के साथ मौजूदा इन-प्लेस को संशोधित करने की तुलना में एक और प्रतिलिपि बनाने के लिए और अधिक स्पष्ट है, क्योंकि अन्य ने सुझाव दिया है (यदि आप परिवर्तनीय को पुन: असाइन करके मौजूदा प्रति खो देते हैं, तो उसे तुरंत कचरा इकट्ठा किया जाएगा)। पायथन तेजी से नहीं होने वाला है, इसका मतलब पठनीय होना है (हालांकि मुझे वास्तव में विश्वास है कि प्रतिलिपि() अन्य तरीकों से तेज होगी)।

+0

मैं मानता हूं, एक प्रति स्पष्ट है, लेकिन "उपयोग केस" जिस पर मैं काम कर रहा हूं, जगह में संशोधन की आवश्यकता है .. हालांकि आपकी राय के लिए धन्यवाद :) – Joril

0

संशोधित होने के जोखिम पर, एक सभ्य इस के लिए कोई उपयोग-मामला है?

जब तक हम जानते हैं कि यह वास्तव में क्या है, हम समझदारी से इसे "टूटा" के रूप में नहीं समझ सकते हैं।

शायद यह प्रयास करें:

firstobject.an_attribute = secondobject.an_attribute 
firstobject.another_attribute = secondobject.another_attribute 

उदाहरणों के बीच नकल चीजों की समझदार तरीका है कि।

+1

मुझे पता है कि मैं प्रत्येक संपत्ति को हाथ से कॉपी कर सकता हूं, मैं पूछ रहा था कि क्या है इसे स्वचालित रूप से करने का एक तरीका :) उपयोग के मामले के रूप में, मैं एक refresh_from_persistence (obj) विधि को लागू करने का प्रयास कर रहा था जो ऑब्जेक्ट इन-प्लेस को अपडेट करेगा, वर्तमान में स्मृति में प्रत्येक संदर्भ को अपडेट करने से बचें। – Joril

+0

आह, मुझे लगता है कि मैं देखता हूं। यह एक बुरा उपयोग मामला है, क्योंकि यदि आप एक नई वस्तु चाहते हैं, तो एक नई वस्तु (आईएमओ) का उपयोग करें। हालांकि मैं एक उचित जवाब दूंगा;) –

2

आपको ऐसा करने की है, तो मुझे लगता है कि सबसे अच्छा तरीका है एक वर्ग की तरह कुछ विशेषता है:

Class Copyable(object): 
    copyable_attributes = ('an_attribute', 'another_attribute') 

फिर उन्हें स्पष्ट रूप से पुनरावृति और setattr(new, attr, getattr(old, attr)) का उपयोग करें। मुझे अभी भी विश्वास है कि इसे बेहतर डिजाइन के साथ हल किया जा सकता है, और इसकी अनुशंसा नहीं करते हैं।

0

इस का उपयोग करते हुए आप लगभग सब कुछ कॉपी कर सकते हैं एक वस्तु से दूसरे करने के लिए:

import sys 

_target_object = sys.stderr 
_target_object_class_type = type(_target_object) 

class TargetCopiedObject(_target_object_class_type): 
    """ 
     Which special methods bypasses __getattribute__ in Python? 
     https://stackoverflow.com/questions/12872695/which-special-methods-bypasses 
    """ 

    if hasattr(_target_object, "__abstractmethods__"): 
     __abstractmethods__ = _target_object.__abstractmethods__ 

    if hasattr(_target_object, "__base__"): 
     __base__ = _target_object.__base__ 

    if hasattr(_target_object, "__bases__"): 
     __bases__ = _target_object.__bases__ 

    if hasattr(_target_object, "__basicsize__"): 
     __basicsize__ = _target_object.__basicsize__ 

    if hasattr(_target_object, "__call__"): 
     __call__ = _target_object.__call__ 

    if hasattr(_target_object, "__class__"): 
     __class__ = _target_object.__class__ 

    if hasattr(_target_object, "__delattr__"): 
     __delattr__ = _target_object.__delattr__ 

    if hasattr(_target_object, "__dict__"): 
     __dict__ = _target_object.__dict__ 

    if hasattr(_target_object, "__dictoffset__"): 
     __dictoffset__ = _target_object.__dictoffset__ 

    if hasattr(_target_object, "__dir__"): 
     __dir__ = _target_object.__dir__ 

    if hasattr(_target_object, "__doc__"): 
     __doc__ = _target_object.__doc__ 

    if hasattr(_target_object, "__eq__"): 
     __eq__ = _target_object.__eq__ 

    if hasattr(_target_object, "__flags__"): 
     __flags__ = _target_object.__flags__ 

    if hasattr(_target_object, "__format__"): 
     __format__ = _target_object.__format__ 

    if hasattr(_target_object, "__ge__"): 
     __ge__ = _target_object.__ge__ 

    if hasattr(_target_object, "__getattribute__"): 
     __getattribute__ = _target_object.__getattribute__ 

    if hasattr(_target_object, "__gt__"): 
     __gt__ = _target_object.__gt__ 

    if hasattr(_target_object, "__hash__"): 
     __hash__ = _target_object.__hash__ 

    if hasattr(_target_object, "__init__"): 
     __init__ = _target_object.__init__ 

    if hasattr(_target_object, "__init_subclass__"): 
     __init_subclass__ = _target_object.__init_subclass__ 

    if hasattr(_target_object, "__instancecheck__"): 
     __instancecheck__ = _target_object.__instancecheck__ 

    if hasattr(_target_object, "__itemsize__"): 
     __itemsize__ = _target_object.__itemsize__ 

    if hasattr(_target_object, "__le__"): 
     __le__ = _target_object.__le__ 

    if hasattr(_target_object, "__lt__"): 
     __lt__ = _target_object.__lt__ 

    if hasattr(_target_object, "__module__"): 
     __module__ = _target_object.__module__ 

    if hasattr(_target_object, "__mro__"): 
     __mro__ = _target_object.__mro__ 

    if hasattr(_target_object, "__name__"): 
     __name__ = _target_object.__name__ 

    if hasattr(_target_object, "__ne__"): 
     __ne__ = _target_object.__ne__ 

    if hasattr(_target_object, "__new__"): 
     __new__ = _target_object.__new__ 

    if hasattr(_target_object, "__prepare__"): 
     __prepare__ = _target_object.__prepare__ 

    if hasattr(_target_object, "__qualname__"): 
     __qualname__ = _target_object.__qualname__ 

    if hasattr(_target_object, "__reduce__"): 
     __reduce__ = _target_object.__reduce__ 

    if hasattr(_target_object, "__reduce_ex__"): 
     __reduce_ex__ = _target_object.__reduce_ex__ 

    if hasattr(_target_object, "__repr__"): 
     __repr__ = _target_object.__repr__ 

    if hasattr(_target_object, "__setattr__"): 
     __setattr__ = _target_object.__setattr__ 

    if hasattr(_target_object, "__sizeof__"): 
     __sizeof__ = _target_object.__sizeof__ 

    if hasattr(_target_object, "__str__"): 
     __str__ = _target_object.__str__ 

    if hasattr(_target_object, "__subclasscheck__"): 
     __subclasscheck__ = _target_object.__subclasscheck__ 

    if hasattr(_target_object, "__subclasses__"): 
     __subclasses__ = _target_object.__subclasses__ 

    if hasattr(_target_object, "__subclasshook__"): 
     __subclasshook__ = _target_object.__subclasshook__ 

    if hasattr(_target_object, "__text_signature__"): 
     __text_signature__ = _target_object.__text_signature__ 

    if hasattr(_target_object, "__weakrefoffset__"): 
     __weakrefoffset__ = _target_object.__weakrefoffset__ 

    if hasattr(_target_object, "mro"): 
     mro = _target_object.mro 

    def __init__(self): 
     """ 
      Override any super class `type(_target_object)` constructor, 
      so we can instantiate any kind of replacement object. 

      Assures all properties were statically replaced just above. This 
      should happen in case some new attribute is added to the python 
      language. 

      This also ignores the only two methods which are not equal, 
      `__init__()` and `__getattribute__()`. 

      How do you programmatically set an attribute? 
      https://stackoverflow.com/questions/285061/how-do-you-programmatically 
     """ 
     different_methods = set(["__init__", "__getattribute__"]) 
     attributes_to_check = set(dir(object) + dir(type)) 
     attributes_to_copy = dir(_target_object) 

     # Check for missing magic built-ins methods on the class static initialization 
     for attribute in attributes_to_check: 

      if attribute not in different_methods \ 
        and hasattr(_target_object, attribute): 

       base_class_attribute = self.__getattribute__(attribute) 
       target_class_attribute = _target_object.__getattribute__(attribute) 

       if base_class_attribute != target_class_attribute: 
        sys.stdout.write(
          " The base class attribute `%s` is different from the " 
          "target class:\n%s\n%s\n\n" % (attribute, 
                base_class_attribute, 
                target_class_attribute)) 
     # Finally copy everything it can 
     different_methods.update(attributes_to_check) 

     for attribute in attributes_to_copy: 

      if attribute not in different_methods: 
       print("Setting:", attribute) 

       try: 
        target_class_attribute = _target_object.__getattribute__(attribute) 
        setattr(self, attribute, target_class_attribute) 

       except AttributeError as error: 
        print("Error coping the attribute `%s`: %s" % (attribute, error)) 


o = TargetCopiedObject() 
print("TargetCopiedObject:", o) 

हालांकि, अगर आप कोड के ऊपर चलाने के लिए, आप इन त्रुटियों को देखेंगे:

python test.py 
Setting: _CHUNK_SIZE 
Setting: __del__ 
Setting: __enter__ 
Setting: __exit__ 
Setting: __getstate__ 
Setting: __iter__ 
Setting: __next__ 
Setting: _checkClosed 
Setting: _checkReadable 
Setting: _checkSeekable 
Setting: _checkWritable 
Setting: _finalizing 
Setting: buffer 
Error coping the attribute `buffer`: readonly attribute 
Setting: close 
Setting: closed 
Error coping the attribute `closed`: attribute 'closed' of '_io.TextIOWrapper' objects is not writable 
Setting: detach 
Setting: encoding 
Error coping the attribute `encoding`: readonly attribute 
Setting: errors 
Error coping the attribute `errors`: attribute 'errors' of '_io.TextIOWrapper' objects is not writable 
Setting: fileno 
Setting: flush 
Setting: isatty 
Setting: line_buffering 
Error coping the attribute `line_buffering`: readonly attribute 
Setting: mode 
Setting: name 
Error coping the attribute `name`: attribute 'name' of '_io.TextIOWrapper' objects is not writable 
Setting: newlines 
Error coping the attribute `newlines`: attribute 'newlines' of '_io.TextIOWrapper' objects is not writable 
Setting: read 
Setting: readable 
Setting: readline 
Setting: readlines 
Setting: seek 
Setting: seekable 
Setting: tell 
Setting: truncate 
Setting: writable 
Setting: write 
Setting: writelines 
TargetCopiedObject: <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'> 

आप केवल कॉपी कर सकते हैं क्लास स्थैतिक प्रारंभिकरण पर इसे पढ़ने के द्वारा इन पढ़ने-योग्य गुणों, जैसे अन्य अंतर्निहित जादू पायथन विधियों की तरह __str__ ऊपर:

import sys 

_target_object = sys.stderr 
_target_object_class_type = type(_target_object) 

class TargetCopiedObject(_target_object_class_type): 
    """ 
     Which special methods bypasses __getattribute__ in Python? 
     https://stackoverflow.com/questions/12872695/which-special-methods-bypasses 
    """ 

    if hasattr(_target_object, "__abstractmethods__"): 
     __abstractmethods__ = _target_object.__abstractmethods__ 

    if hasattr(_target_object, "__base__"): 
     __base__ = _target_object.__base__ 

    if hasattr(_target_object, "__bases__"): 
     __bases__ = _target_object.__bases__ 

    if hasattr(_target_object, "__basicsize__"): 
     __basicsize__ = _target_object.__basicsize__ 

    if hasattr(_target_object, "__call__"): 
     __call__ = _target_object.__call__ 

    if hasattr(_target_object, "__class__"): 
     __class__ = _target_object.__class__ 

    if hasattr(_target_object, "__delattr__"): 
     __delattr__ = _target_object.__delattr__ 

    if hasattr(_target_object, "__dict__"): 
     __dict__ = _target_object.__dict__ 

    if hasattr(_target_object, "__dictoffset__"): 
     __dictoffset__ = _target_object.__dictoffset__ 

    if hasattr(_target_object, "__dir__"): 
     __dir__ = _target_object.__dir__ 

    if hasattr(_target_object, "__doc__"): 
     __doc__ = _target_object.__doc__ 

    if hasattr(_target_object, "__eq__"): 
     __eq__ = _target_object.__eq__ 

    if hasattr(_target_object, "__flags__"): 
     __flags__ = _target_object.__flags__ 

    if hasattr(_target_object, "__format__"): 
     __format__ = _target_object.__format__ 

    if hasattr(_target_object, "__ge__"): 
     __ge__ = _target_object.__ge__ 

    if hasattr(_target_object, "__getattribute__"): 
     __getattribute__ = _target_object.__getattribute__ 

    if hasattr(_target_object, "__gt__"): 
     __gt__ = _target_object.__gt__ 

    if hasattr(_target_object, "__hash__"): 
     __hash__ = _target_object.__hash__ 

    if hasattr(_target_object, "__init__"): 
     __init__ = _target_object.__init__ 

    if hasattr(_target_object, "__init_subclass__"): 
     __init_subclass__ = _target_object.__init_subclass__ 

    if hasattr(_target_object, "__instancecheck__"): 
     __instancecheck__ = _target_object.__instancecheck__ 

    if hasattr(_target_object, "__itemsize__"): 
     __itemsize__ = _target_object.__itemsize__ 

    if hasattr(_target_object, "__le__"): 
     __le__ = _target_object.__le__ 

    if hasattr(_target_object, "__lt__"): 
     __lt__ = _target_object.__lt__ 

    if hasattr(_target_object, "__module__"): 
     __module__ = _target_object.__module__ 

    if hasattr(_target_object, "__mro__"): 
     __mro__ = _target_object.__mro__ 

    if hasattr(_target_object, "__name__"): 
     __name__ = _target_object.__name__ 

    if hasattr(_target_object, "__ne__"): 
     __ne__ = _target_object.__ne__ 

    if hasattr(_target_object, "__new__"): 
     __new__ = _target_object.__new__ 

    if hasattr(_target_object, "__prepare__"): 
     __prepare__ = _target_object.__prepare__ 

    if hasattr(_target_object, "__qualname__"): 
     __qualname__ = _target_object.__qualname__ 

    if hasattr(_target_object, "__reduce__"): 
     __reduce__ = _target_object.__reduce__ 

    if hasattr(_target_object, "__reduce_ex__"): 
     __reduce_ex__ = _target_object.__reduce_ex__ 

    if hasattr(_target_object, "__repr__"): 
     __repr__ = _target_object.__repr__ 

    if hasattr(_target_object, "__setattr__"): 
     __setattr__ = _target_object.__setattr__ 

    if hasattr(_target_object, "__sizeof__"): 
     __sizeof__ = _target_object.__sizeof__ 

    if hasattr(_target_object, "__str__"): 
     __str__ = _target_object.__str__ 

    if hasattr(_target_object, "__subclasscheck__"): 
     __subclasscheck__ = _target_object.__subclasscheck__ 

    if hasattr(_target_object, "__subclasses__"): 
     __subclasses__ = _target_object.__subclasses__ 

    if hasattr(_target_object, "__subclasshook__"): 
     __subclasshook__ = _target_object.__subclasshook__ 

    if hasattr(_target_object, "__text_signature__"): 
     __text_signature__ = _target_object.__text_signature__ 

    if hasattr(_target_object, "__weakrefoffset__"): 
     __weakrefoffset__ = _target_object.__weakrefoffset__ 

    if hasattr(_target_object, "mro"): 
     mro = _target_object.mro 

    # Copy all the other read only attributes 
    if hasattr(_target_object, "buffer"): 
     buffer = _target_object.buffer 

    if hasattr(_target_object, "closed"): 
     closed = _target_object.closed 

    if hasattr(_target_object, "encoding"): 
     encoding = _target_object.encoding 

    if hasattr(_target_object, "errors"): 
     errors = _target_object.errors 

    if hasattr(_target_object, "line_buffering"): 
     line_buffering = _target_object.line_buffering 

    if hasattr(_target_object, "name"): 
     name = _target_object.name 

    if hasattr(_target_object, "newlines"): 
     newlines = _target_object.newlines 

    def __init__(self): 
     """ 
      Override any super class `type(_target_object)` constructor, 
      so we can instantiate any kind of replacement object. 

      Assures all properties were statically replaced just above. This 
      should happen in case some new attribute is added to the python 
      language. 

      This also ignores the only two methods which are not equal, 
      `__init__()` and `__getattribute__()`. 

      How do you programmatically set an attribute? 
      https://stackoverflow.com/questions/285061/how-do-you-programmatically 
     """ 

     # Add the copied read only atribute to the ignored list, so they 
     # do not throw new errors while trying copy they dynamically 
     different_methods = set\ 
     ([ 
      "__init__", 
      "__getattribute__", 
      "buffer", 
      "closed", 
      "encoding", 
      "errors", 
      "line_buffering", 
      "name", 
      "newlines", 
     ]) 

     attributes_to_check = set(dir(object) + dir(type)) 
     attributes_to_copy = dir(_target_object) 

     # Check for missing magic built-ins methods on the class static initialization 
     for attribute in attributes_to_check: 

      if attribute not in different_methods \ 
        and hasattr(_target_object, attribute): 

       base_class_attribute = self.__getattribute__(attribute) 
       target_class_attribute = _target_object.__getattribute__(attribute) 

       if base_class_attribute != target_class_attribute: 
        sys.stdout.write(
          " The base class attribute `%s` is different from the " 
          "target class:\n%s\n%s\n\n" % (attribute, 
                base_class_attribute, 
                target_class_attribute)) 
     # Finally copy everything it can 
     different_methods.update(attributes_to_check) 

     for attribute in attributes_to_copy: 

      if attribute not in different_methods: 
       print("Setting:", attribute) 

       try: 
        target_class_attribute = _target_object.__getattribute__(attribute) 
        setattr(self, attribute, target_class_attribute) 

       except AttributeError as error: 
        print("Error coping the attribute `%s`: %s" % (attribute, error)) 


o = TargetCopiedObject() 
print("TargetCopiedObject:", o) 

अब इस नए संस्करण पूरी तरह से मुकाबला करने के लिए सब कुछ काम करता है:

python test.py 
Setting: _CHUNK_SIZE 
Setting: __del__ 
Setting: __enter__ 
Setting: __exit__ 
Setting: __getstate__ 
Setting: __iter__ 
Setting: __next__ 
Setting: _checkClosed 
Setting: _checkReadable 
Setting: _checkSeekable 
Setting: _checkWritable 
Setting: _finalizing 
Setting: close 
Setting: detach 
Setting: fileno 
Setting: flush 
Setting: isatty 
Setting: mode 
Setting: read 
Setting: readable 
Setting: readline 
Setting: readlines 
Setting: seek 
Setting: seekable 
Setting: tell 
Setting: truncate 
Setting: writable 
Setting: write 
Setting: writelines 
TargetCopiedObject: <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'> 

यह नुकसान यह है कि आप केवल पढ़ने के लिए जिम्मेदार बताते हैं काबू पाने के लिए मैन्युअल रूप से अजगर कोड लिखने की जरूरत है।तो

  1. Python: How to generate the code on the fly?
  2. https://en.wikipedia.org/wiki/Metaprogramming

, अगर आप इस प्रारंभिक कोड पर बस ऊपर काम करते हैं, आप एक स्क्रिप्ट जो उत्पन्न करता है लिख सकते हैं: लेकिन, आप अजगर कोड मक्खी पर metaprogramming साथ लिख सकते हैं कोड की जरूरत है। इसलिए, आप किसी भी पायथन ऑब्जेक्ट को गतिशील रूप से कॉपी कर सकते हैं।

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

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