2011-05-23 21 views
15

मैं कैसे जांचूं कि कोई संपत्ति पाइथन में सेटटेबल या हटाई जा सकती है या नहीं?जांच कर रहा है कि संपत्ति सेटटेबल/डिलीटेबल

सबसे अच्छा मैं अब तक मिल गया है

type(obj).__dict__["prop_name"].fset is not None 
+4

एक अच्छा सवाल! और आपका समाधान सबसे अच्छा समाधान जैसा दिखता है। –

+2

मैं 'obj .__ वर्ग __। Prop_name.fset' को 'टाइप (ओबीजे) के अपने मुहावरे में लिखना पसंद करूंगा .__ dict __ [" prop_name "]। Fset', लेकिन मुझे लगता है कि दोनों वैध हैं, और मैं बेसिकवॉल्फ से सहमत हूं कि आपका जवाब शायद सबसे अच्छा है। –

उत्तर

8

है यह एक अच्छा मामला है जब आप को दर्शन "यह अनुमति से माफी के लिए पूछें करने के लिए आसान है" सब्सक्राइब करना चाहिए, और सिर्फ मामले संपत्ति में अपवाद को संभालने सेटटेबल/हटाने योग्य नहीं है।

try: 
    x.prop = 42 
except AttributeError: 
    pass 
+2

अच्छा जवाब। मैंने इसे माना, लेकिन मैं स्वचालित रूप से गुणों से यूआई का निर्माण कर रहा हूं और 'ItemIsEditable' ध्वज सेट करने का निर्णय लेने के लिए अपनी" स्थायित्व "का उपयोग कर रहा हूं। मुझे लगता है कि मैं 'x.prop = x.prop' के साथ जांच सकता हूं या अपना डिज़ाइन बदल सकता हूं। –

+2

@Neil: यदि आपने प्रश्न में कोड लिखा है और जानते हैं कि 'x.prop = x.prop' हमेशा सुरक्षित रहेगा, तो यह जांच ठीक रहेगी। हालांकि, संपत्ति सेटर्स अप्रत्याशित चीजें कर सकते हैं जैसे डेटाबेस को हिट करना या काउंटर में वृद्धि करना या अन्यथा आपके सिस्टम की आंतरिक स्थिति बदलना, इसलिए मैं उन्हें तब तक कॉल करने से बचना चाहूंगा जब तक कोई अन्य दृष्टिकोण न हो। आपके प्रश्न में जो समाधान आप उल्लेख करते हैं वह मेरे लिए सबसे अच्छा लगता है। –

1

मुझे नहीं लगता कि बिना कोशिश किए सामने सामने जाने का कोई तरीका है। आप निश्चित रूप से नहीं जान सकते हैं कि किसी ऑब्जेक्ट में अजीब __setattr__ या ऐसा ही है जो उस अबास्ट्रक्शन को तोड़ देगा जिसे आप उपयोग करने का प्रयास कर रहे हैं।

1

निम्न प्रोग्राम यह पता लगाने के लिए डिज़ाइन किए गए तीन कार्यों का परीक्षण करता है कि कक्षा या उदाहरण संपत्ति CRUD संचालन का समर्थन करती है या नहीं। कक्षा या उदाहरण can_* फ़ंक्शंस का पहला तर्क है, और दूसरा तर्क उस संपत्ति का नाम है जिसे चेक किया जाना चाहिए। प्रकार की जांच स्वचालित रूप से यह सुनिश्चित करने के लिए की जाती है कि कार्यों का उपयोग अपेक्षित रूप से किया जा रहा हो। कृपया ध्यान दें कि यह builtins मॉड्यूल से property कक्षा के साथ बनाए गए गुणों के साथ काम करने के लिए डिज़ाइन किया गया है।

#! /usr/bin/env python3 


def main(): 
    for kind in Test, TestG, TestS, TestGS, TestD, TestGD, TestSD, TestGSD: 
     print(kind.__name__, 'Class') 
     print(' can_get:', can_get(kind, 'data')) 
     print(' can_set:', can_set(kind, 'data')) 
     print(' can_del:', can_del(kind, 'data')) 
     print() 
     instance = kind('Hello, world!') 
     print(kind.__name__, 'Instance') 
     print(' can_get:', can_get(instance, 'data')) 
     print(' can_set:', can_set(instance, 'data')) 
     print(' can_del:', can_del(instance, 'data')) 
     print() 


def can_get(obj, key): 
    return _get_property(obj, key).fget is not None 


def can_set(obj, key): 
    return _get_property(obj, key).fset is not None 


def can_del(obj, key): 
    return _get_property(obj, key).fdel is not None 


def _get_property(obj, key): 
    if not isinstance(obj, type): 
     obj = type(obj) 
    pro = vars(obj).get(key) 
    if not isinstance(pro, property): 
     raise TypeError('{.__name__}.{} is not a property'.format(obj, key)) 
    return pro 


class Test: 

    def __init__(self, value): 
     self.__data = value 

    def get_data(self): 
     return self.__data 

    def set_data(self, value): 
     self.__data = value 

    def del_data(self): 
     del self.__data 

    data = property() 


class TestG(Test): 

    data = property(fget=Test.get_data) 


class TestS(Test): 

    data = property(fset=Test.set_data) 


class TestGS(Test): 

    data = property(fget=Test.get_data, fset=Test.set_data) 


class TestD(Test): 

    data = property(fdel=Test.del_data) 


class TestGD(Test): 

    data = property(fget=Test.get_data, fdel=Test.del_data) 


class TestSD(Test): 

    data = property(fset=Test.set_data, fdel=Test.del_data) 


class TestGSD(Test): 

    data = property(fget=Test.get_data, fset=Test.set_data, fdel=Test.del_data) 


if __name__ == '__main__': 
    main() 
+0

यह दृष्टिकोण पहले से ही प्रश्न में दिया गया है। हालांकि, जैसा कि डेनिथ ने अपने जवाब में नोट किया है, यह सामान्य रूप से काम नहीं करता है। –

+0

यह सच हो सकता है, लेकिन जिस कोड के साथ आप काम कर रहे हैं उसके आधार पर, यह विशिष्ट में काम कर सकता है - जो कि कुछ के लिए पर्याप्त हो सकता है। –

+0

हाँ, यह सही है। और इस तरह का समाधान यह है कि मैं अपने कोड में कर रहा था। –

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