Найти - Пользователи
Полная версия: Создание методов класса на лету
Начало » Python для новичков » Создание методов класса на лету
1
lordwader
Всем привет! Задача следующая: Реализовать простой класс с несколькими методами. При вызове метода которого не существует он должен быть создан на лету и вызван. В качестве результата вызова - имя метода.
Вот мой код:
 class Foo(object):
    def sum(self, arg = 0):
        print(arg + 5)
 
    def minus(self, arg = 0):
        print(10 - arg)
 
    def __getattribute__( self, name ):
        self.cur_name = name
        return self
    
    def __call__( self, *args, **kwargs ):
        func_name = super().__getattribute__( "cur_name" )
        if func_name in dir(Foo):
            return self.func_name()
        print(func_name)
 
f = Foo()
f.sum()
f.minus()
f.bar()
f.ber()
f.bar()
f.bar_1()
f.sum()
__call__ и __getattribute__ перехватывают все методы и не вызывают minus и sum. Подскажите пожалуйста, где я ошибся в коде.
rami
Исправьте на:
 def __getattr__(self, name):
doza_and
lordwader
Подскажите пожалуйста, где я ошибся в коде.
Везде. Добавление нового метода это манипуляции с классом а не с объектом.
Papa_Svin
doza_and
Добавление нового метода это манипуляции с классом а не с объектом.
В питоне нет проблем добавить метод в объект. Надо чтобы автор уточнил, в какую именно сущность он желает добавлять методы
PEHDOM
lordwader
Реализовать простой класс с несколькими методами. При вызове метода которого не существует он должен быть создан на лету и вызван. В качестве результата вызова - имя метода.
это должен быть метод класаа или инстанса?
lordwader
__call__ и __getattribute__ перехватывают все методы и не вызывают minus и sum. Подскажите пожалуйста, где я ошибся в коде.
во первых __call__ вообще не учавствует там никак, он сработает только если сделать f().
__getattribute__ я бы не трогал, лучше переопредели __getattr__ тогда он будет перехватывать только непределенные атрибуты.
както так, в конкретной реализации оно добавляет методы в инстанс, легко переделывается чтобы добавляло методы в класс.
 class Foo(object):
    def sum(self, arg = 0):
        print('summm!!!')
    def minus(self, arg = 0):
        print('minus!!!')
    def make_method(self, name):
        print('creating func:', name)
        def _method():
            print(name)
        _method.__name__ = name
        setattr(self, name, _method)
    def __getattr__(self, key):
        try:
            res = super().__getattribute__(key)
        except AttributeError:
            self.make_method(key)
            res = self.__getattribute__(key)
        return res
f = Foo()
f.sum()
f.minus()
f.bar()
f.ber()
f.bar()
f.bar_1()
f.sum()
print(f.__dict__)
вывод:
>>> 
>>>
summm!!!
minus!!!
creating func: bar
bar
creating func: ber
ber
bar
creating func: bar_1
bar_1
summm!!!
{'ber': <function ber at 0x02EE6540>, 'bar_1': <function bar_1 at 0x02EE6618>, 'bar': <function bar at 0x02EE64B0>}
>>>
>>>

lordwader
Спасибо за подсказки и советы. В общем реализовал так:
 def bind(self, as_name):
        setattr(self, as_name, (lambda pop: print(as_name)).__get__(self, self.__class__))
        
def __getattr__(self, name):
    try:
        func_name = super().__getattribute__(name)
    except AttributeError:
        self.bind(name)
        func_name = self.__getattribute__(name)
    return func_name
Теперь пытаюсь понять, как это переделать, чтобы добавляло методы в класс а не в инстанс.
Rodegast
Зачем такие сложности?
 >>> class A(object):
...     def __getattr__(self, attr):
...         metod = lambda: attr
...         setattr(self, attr, metod)
...         return metod
>>> a = A()
>>> a.aaa()
'aaa'
>>> a.bbb()
'bbb'
<function <lambda> at 0x7efff6be72a8>
Тут конечно не методы, а атрибуты. Если хочешь именно настоящих методов, то их нужно добавлять в класс как собственно уже сказали.
 >>> metod = lambda self: "attr"
>>> setattr(A, "attr", metod)
>>> A.attr(a)
'attr'
>>> A.attr
<unbound method A.<lambda>>
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB