How to add property to a class dynamically?

前端 未结 24 2166
梦毁少年i
梦毁少年i 2020-11-22 12:44

The goal is to create a mock class which behaves like a db resultset.

So for example, if a database query returns, using a dict expression, {\'ab\':100, \'cd\'

24条回答
  •  一向
    一向 (楼主)
    2020-11-22 13:17

    Extending the idea from kjfletch

    # This is my humble contribution, extending the idea to serialize
    # data from and to tuples, comparison operations and allowing functions
    # as default values.
    
    def Struct(*args, **kwargs):
        FUNCTIONS = (types.BuiltinFunctionType, types.BuiltinMethodType, \
                     types.FunctionType, types.MethodType)
        def init(self, *iargs, **ikwargs):
            """Asume that unamed args are placed in the same order than
            astuple() yields (currently alphabetic order)
            """
            kw = list(self.__slots__)
    
            # set the unnamed args
            for i in range(len(iargs)):
                k = kw.pop(0)
                setattr(self, k, iargs[i])
    
            # set the named args
            for k, v in ikwargs.items():
                setattr(self, k, v)
                kw.remove(k)
    
            # set default values
            for k in kw:
                v = kwargs[k]
                if isinstance(v, FUNCTIONS):
                    v = v()
                setattr(self, k, v)
    
        def astuple(self):
            return tuple([getattr(self, k) for k in self.__slots__])
    
        def __str__(self):
            data = ['{}={}'.format(k, getattr(self, k)) for k in self.__slots__]
            return '<{}: {}>'.format(self.__class__.__name__, ', '.join(data))
    
        def __repr__(self):
            return str(self)
    
        def __eq__(self, other):
            return self.astuple() == other.astuple()
    
        name = kwargs.pop("__name__", "MyStruct")
        slots = list(args)
        slots.extend(kwargs.keys())
        # set non-specific default values to None
        kwargs.update(dict((k, None) for k in args))
    
        return type(name, (object,), {
            '__init__': init,
            '__slots__': tuple(slots),
            'astuple': astuple,
            '__str__': __str__,
            '__repr__': __repr__,
            '__eq__': __eq__,
        })
    
    
    Event = Struct('user', 'cmd', \
                   'arg1', 'arg2',  \
                   date=time.time, \
                   __name__='Event')
    
    aa = Event('pepe', 77)
    print(aa)
    raw = aa.astuple()
    
    bb = Event(*raw)
    print(bb)
    
    if aa == bb:
        print('Are equals')
    
    cc = Event(cmd='foo')
    print(cc)
    

    Output:

    
    
    Are equals
    
    

提交回复
热议问题