2012-04-13 16 views
13

टीएल; डीआर: प्रत्येक संपत्ति() 'डी परिवर्तनीय बेकार के लिए गेटर्स और सेटर्स का एक अद्वितीय सेट परिभाषित करने के लिए। क्या मैं सामान्य गेटर्स और सेटर्स को परिभाषित कर सकता हूं और उन्हें जो भी वैरिएबल चाहता हूं उसका उपयोग कर सकता हूं?पायथन: जेनेरिक गेटर्स और सेटर्स

मान लें कि मैं कुछ अच्छा getters और setters के साथ एक वर्ग बनाने:

class Foo 
    def getter(self): 
     return _bar+' sasquatch' 

    def setter(self, value): 
     _bar = value+' unicorns' 

    bar = property(getter, setter) 

सुंदर महान, है ना?

अब मान लें कि मैंने "बाज़" नामक एक और चर डाला है और मैं नहीं चाहता कि इसे इस सॉसक्वैच/यूनिकॉर्न मजे से बाहर छोड़ा जाए। ठीक है, मुझे लगता है मैं getters और setters का एक और सेट कर सकता है:

class Foo 
    def bar_getter(self): 
     return _bar+' sasquatch' 

    def bar_setter(self, value): 
     _bar = value+' unicorns' 

    bar = property(bar_getter, bar_setter) 

    def baz_getter(self): 
     return _baz+' sasquatch' 

    def baz_setter(self, value): 
     _baz = value+' unicorns' 

    baz = property(baz_getter, baz_setter) 

लेकिन वह बहुत शुष्क और बेकार में clutters मेरी कोड नहीं है। मुझे लगता है मैं यह थोड़ा ड्रायर बना सकता है:

class Foo 
    def unicornify(self, value): 
     return value+' unicorns' 

    def sasquatchify(self, value): 
     return value+' sasquatch' 

    def bar_getter(self): 
     return self.sasquatchify(_bar) 

    def bar_setter(self, value): 
     _bar = self.unicornify(_bar) 

    bar = property(bar_getter, bar_setter) 

    def baz_getter(self): 
     return self.sasquatchify(_baz) 

    def baz_setter(self, value): 
     _baz = self.unicornify(_baz) 

    baz = property(baz_getter, baz_setter) 

हालांकि यह है कि मेरे कोड ड्रायर कर सकता है, यह आदर्श नहीं है। अगर मैं दो और चरों को unicornify और sasquatchify करना चाहता था, तो मुझे चार और कार्यों को जोड़ना होगा!

ऐसा करने का एक बेहतर तरीका होना चाहिए। क्या मैं एकाधिक चरों में एक जेनेरिक गेटर और/या सेटर का उपयोग कर सकता हूं?

यूनिकॉर्न कम और sasquatch कम वास्तविक दुनिया कार्यान्वयन: मैं SQLAlchemy ORM उपयोग कर रहा हूँ, और जब भंडारण और डेटाबेस से यह पुन: प्राप्त करने डेटा के कुछ बदलना चाहते हैं। कुछ परिवर्तन एक से अधिक चर पर लागू होते हैं, और मैं अपने वर्गों को गेटर्स और सेटर्स के साथ अव्यवस्थित नहीं करना चाहता हूं।

उत्तर

12

कैसे बस के बारे में:

def sasquatchicorn(name): 
    return property(lambda self: getattr(self, name) + ' sasquatch', 
        lambda self, val: setattr(self, name, val + ' unicorns')) 

class Foo(object): 
    bar = sasquatchicorn('_bar') 
    baz = sasquatchicorn('_baz') 

कुछ अधिक सामान्य रूप से:

def sasquatchify(val): 
    return val + ' sasquatch' 

def unicornify(val): 
    return val + ' unicorns' 

def getset(name, getting, setting): 
    return property(lambda self: getting(getattr(self, name)), 
        lambda self, val: setattr(self, name, setting(val))) 

class Foo(object): 
    bar = getset('_bar', sasquatchify, unicornify) 
    baz = getset('_baz', sasquatchify, unicornify) 

या, मुश्किल से अधिक काम के साथ, आप पूर्ण वर्णनकर्ता प्रोटोकॉल, agf's answer में वर्णित के रूप में उपयोग कर सकते हैं।

class Sasicorn(object):        
    def __init__(self, attr):       
     self.attr = "_" + attr      
    def __get__(self, obj, objtype):     
     return getattr(obj, self.attr) + ' sasquatch' 
    def __set__(self, obj, value):     
     setattr(obj, self.attr, value + ' unicorns') 

class Foo(object):         
    def __init__(self, value = "bar"):    
     self.bar = value        
     self.baz = "baz"        
    bar = Sasicorn('bar')        
    baz = Sasicorn('baz')        

foo = Foo()           
foo2 = Foo('other')         
print foo.bar           
# prints bar unicorns sasquatch 
print foo.baz           
# prints baz unicorns sasquatch 
print foo2.bar          
# prints other unicorns sasquatch 

जबकि एक कारखाने समारोह अपने खिलौना उदाहरण के लिए ठीक हो सकता है में property, यह हो सकता है की तरह लगता है आप अपने वास्तविक उपयोग के मामले के लिए और अधिक नियंत्रण की जरूरत है:

+1

लेकिन lambdas एक भी भाव को setters और getters की सीमा है, जो कि मैं क्या करने की जरूरत है के लिए उपयुक्त नहीं है कर। –

+0

@TheronLuhn तो वही काम करें लेकिन सामान्य कार्यों के साथ (या तो 'sasquatchicorn' के आंतरिक कार्यों के रूप में परिभाषित किया गया है या जो एक तर्क के रूप में नाम लेता है)। या [एएसएफ] (http://stackoverflow.com/a/10149431/344821) के जवाब में पूर्ण वर्णनकर्ता सौदा करें। – Dougal

+0

या मेरे संपादन में चीज करें, जो एक पूर्ण वर्णनकर्ता करने से थोड़ा कम काम हो सकता है? शायद? :) – Dougal

5

यह descriptor protocolproperty पर के लिए है क्या आधारित है ।

+0

मैं थोड़ी देर के लिए इसके साथ संघर्ष कर रहा हूं, और मैं गलत हो सकता हूं, लेकिन ऐसा लगता है कि यह वास्तव में कक्षा के सभी उदाहरणों के बीच साझा किए गए वर्ग-स्तर "संपत्ति" को परिभाषित करेगा। यह उत्तर सहायक है, लेकिन यह व्यवहार निश्चित रूप से मेरे लिए नहीं है। – krs013

+1

@ krs013 आप सही हैं, जबकि यह वर्णनकर्ता प्रोटोकॉल दिखाता है, यह बहुत उपयोगी नहीं था। मैंने कक्षा के बजाए उदाहरण पर मूल्य को स्टोर करने के लिए इसे अद्यतन किया है। – agf

+0

धन्यवाद, यह वह व्यवहार है जिसे मैं ढूंढ रहा था। कहीं और मैंने इसे देखा होगा जहां वर्णनकर्ता वस्तु के '__dict__' को सीधे एक्सेस करता है, लेकिन मुझे लगता है कि यह क्लीनर दिखता है। – krs013

1

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

class Foo(object): 
    def setter(var): 
     def set(self, value): 
      setattr(self, var, value+' unicorn') 
     return set 

    def getter(var): 
     def get(self): 
      return getattr(self, var)+' sasquatch' 
     return get 

    bar = property(getter('_bar'), setter('_bar')) 

f = Foo() 
f.foo = 'hi' 
print f.foo 

लेकिन आप सभी अपने जवाब :)

+1

यह अनिवार्य रूप से डगल के उत्तर के समान ही है, लेकिन लैम्बडास के बजाय कार्यों का उपयोग करता है। – Darthfett

+0

क्या यह है? क्षमा करें, मैं पाइथन के लिए नया-आश हूं। मैं डगल के स्वीकार करूंगा। –

1

getattribute और setattr का उपयोग करते हुए सब अतीत और भविष्य के लिए जिम्मेदार बताते हैं तो आप इस परिभाषित कर सकते हैं के लिए धन्यवाद देता हूं।

class Foo(object):                               

    x = 3 

    def __getattribute__(self, attr): 
    return str(object.__getattribute__(self, attr)) + ' sasquatch' 

    def __setattr__(self, attr, value): 
    object.__setattr__(self, attr, str(value) + ' unicorn') 

print Foo.x 
f = Foo() 
print f.x 
f.y = 4 
print f.y 

यह प्रिंट:

3 
3 sasquatch 
4 unicorn sasquatch 
-1
# coding=utf-8 
__author__ = 'Ahmed Şeref GÜNEYSU' 


class Student(object): 
    def __init__(self, **kwargs): 
     for k, v in kwargs.iteritems(): 
      self.__setattr__(k, v) 

if __name__ == '__main__': 
    o = Student(first_name='Ahmed Şeref', last_name='GÜNEYSU') 
    print "{0} {1}".format(o.first_name, o.last_name) 
    print o.email 

देता

Ahmed Şeref GÜNEYSU 
    File "/Users/ahmed/PycharmProjects/sanbox/abstract_classes/object_initializer/__init__.py", line 13, in <module> 
    print o.email 
AttributeError: 'Student' object has no attribute 'email' 

Process finished with exit code 137 
संबंधित मुद्दे