Python: Generic getters and setters

前端 未结 5 460
天命终不由人
天命终不由人 2021-02-04 06:11

TL;DR: Having to define a unique set of getters and setters for each property()\'d variable sucks. Can I define generic getters and setters and use them with whatever

相关标签:
5条回答
  • 2021-02-04 06:39
    # 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
    

    Gives

    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
    
    0 讨论(0)
  • 2021-02-04 06:42

    A colleague of mine suggested using closures to return getter and setter functions, which is what I've decided to use.

    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
    

    But thank you all for your answers :)

    0 讨论(0)
  • 2021-02-04 06:48

    This is what the descriptor protocol property is based on is for:

    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
    

    While property in a factory function may be fine for your toy example, it sounds like maybe you need more control for your real use case.

    0 讨论(0)
  • 2021-02-04 06:58

    How about just:

    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')
    

    Somewhat more generically:

    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)
    

    Or, with barely more work, you can use the full descriptor protocol, as described in agf's answer.

    0 讨论(0)
  • 2021-02-04 07:00

    Using getattribute and setattr you can define this for all attributes past and future.

    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 
    

    This prints:

    3
    3 sasquatch
    4 unicorn sasquatch
    
    0 讨论(0)
提交回复
热议问题