How to chain attribute lookups that might return None in Python?

前端 未结 6 1044
小鲜肉
小鲜肉 2021-01-07 17:07

My problem is a general one, how to chain a series of attribute lookups when one of the intermediate ones might return None, but since I ran into this problem t

6条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-07 17:48

    One solution would be to wrap the outer object inside a Proxy that handles None values for you. See below for a beginning implementation.

    import unittest

    class SafeProxy(object):
    
        def __init__(self, instance):
            self.__dict__["instance"] = instance
    
        def __eq__(self, other):
            return self.instance==other
    
        def __call__(self, *args, **kwargs):
            return self.instance(*args, **kwargs)
    
        # TODO: Implement other special members
    
        def __getattr__(self, name):
            if hasattr(self.__dict__["instance"], name):
                return SafeProxy(getattr(self.instance, name))
    
            if name=="val":
                return lambda: self.instance
    
            return SafeProxy(None)
    
        def __setattr__(self, name, value):
            setattr(self.instance, name, value)
    
    
    # Simple stub for creating objects for testing
    class Dynamic(object):
        def __init__(self, **kwargs):
            for name, value in kwargs.iteritems():
                self.__setattr__(name, value)
    
        def __setattr__(self, name, value):
            self.__dict__[name] = value
    
    
    class Test(unittest.TestCase):
    
        def test_nestedObject(self):
            inner = Dynamic(value="value")
            middle = Dynamic(child=inner)
            outer = Dynamic(child=middle)
            wrapper = SafeProxy(outer)
            self.assertEqual("value", wrapper.child.child.value)
            self.assertEqual(None, wrapper.child.child.child.value)
    
        def test_NoneObject(self):
            self.assertEqual(None, SafeProxy(None))
    
        def test_stringOperations(self):
            s = SafeProxy("string")
            self.assertEqual("String", s.title())
            self.assertEqual(type(""), type(s.val()))
            self.assertEqual()
    
    if __name__=="__main__":
        unittest.main()
    

    NOTE: I am personally not sure wether I would use this in an actual project, but it makes an interesting experiment and I put it here to get people thoughts on this.

提交回复
热议问题