akonsu a écrit :
hello,

i need to add properties to instances  dynamically during run time.
this is because their names are determined by the database contents.
so far i found a way to add methods on demand:

class A(object) :
    def __getattr__(self, name) :
        if name == 'test' :
            def f() : return 'test'
            setattr(self, name, f)
            return f
        else :
            raise AttributeError("'%s' object has no attribute '%s'" %
(self.__class__.__name__, name))
> this seems to work and i can invoke method test() on an object.

Nope. This adds per-instance *function* attributes - not *methods*.

class A(object) :
    def __getattr__(self, name) :
        if name == 'test' :
            def f(self) :
                return "%s.test" % self
            setattr(self, name, f)
            return f
        else :
            raise AttributeError(
                "'%s' object has no attribute '%s'" \
                % (self.__class__.__name__, name)
                )


a = A()
a.test()
=> Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: f() takes exactly 1 argument (0 given)


To add methods on a per-instance basis, you have to manually invoke the descriptor protocol's implementation of function objects:

class A(object) :
    def __getattr__(self, name) :
        if name == 'test' :
            def f(self) :
                return "%s.test" % self
            m = f.__get__(self, type(self))
            setattr(self, name, m)
            return m
        else :
            raise AttributeError(
                "'%s' object has no attribute '%s'" \
                % (self.__class__.__name__, name)
                )


it
would be nice to have it as property though.   so i tried:

class A(object) :
    def __getattr__(self, name) :
        if name == 'test' :
            def f() : return 'test'
            setattr(self, name, property(f))
            return f
        else :
            raise AttributeError("'%s' object has no attribute '%s'" %
(self.__class__.__name__, name))

but this does not work, instance.test returns a callable but does not
call it.

Properties must be class attributes. The only way (the only way I know) to get them to work as instance-attributes is to overload __getattribute__, which is tricky and may have pretty bad impact on lookup perfs - and ruins the whole point of using properties FWIW.

i am not an expert in python, would someone please tell me what i am
doing wrong?

Wrong solution to your problem, I'd say. Let's start again:

"""
> i need to add properties to instances dynamically during run time.
> this is because their names are determined by the database contents.
"""

Care to elaborate ? I may be wrong, but I suspect you're trying to roll your own python/database mapper. If so, there are quite a couple Python ORMs around. Else, please tell us more.
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to