@Flash90

Как сделать класс вызываемым?

Задача более познавателного характера. Хочу, что бы при создании экземпляра класса, можно было на ходу создавать атрибуты, пример:
class A(object):
{...}
a1 = A(x=10)
a1.x => 10
Так , как реализованно в django orm :
class Chel(models.Model):
name = models.CharField(max_length=10)
guy = Chel(name='xxx')
Логично в методе __init__ сделать **kwargs, а далее перебор ключей и setattr(self, key, kwargs[name]). Но захотелось сделать что то более интересное. Подумал исползовать метаклассы - определить метод __call__ и новый класс будет одновременно и вызываемым, что вроде этого:
class Meta(type):

def __call__(self, *args, **kwargs):
obj = type.__call__(self, *args)
for name in kwargs:
setattr(obj, name, kwargs[name])
return obj
class A(object):

__metaclass__ = Meta
Но при вызове:
a = A(x=1)
выдает ошибку:
TypeError: object() takes no parameters
и даже если :
a = A()(x=1)
TypeError: 'A' object is not callable
Подскажите пожалуйста , что не так или сама идея абсурд.
  • Вопрос задан
  • 453 просмотра
Пригласить эксперта
Ответы на вопрос 1
@Flash90 Автор вопроса
ссори,
class Chel(models.Model):
    name = models.CharField(max_length=10)
guy = Chel(name='xxx')


class Meta(type):
    def __call__(self, *args, **kwargs):
        obj = type.__call__(self, *args)
        for name in kwargs:
            setattr(obj, name, kwargs[name])
        return obj

class A(object):
    __metaclass__ = Meta

a = A(x=1)
TypeError: object() takes no parameters
a = A()(x=1)
TypeError: 'A' object is not callable

Решение я нашел, не правильно создавал последний класс :
A = type.__new__(Meta, 'A', (object,), {})
#и теперь при создании экземпляров можно определять атрибуты:
a1 = A(attr1=1, attr2="test")
print(a1.attr1, a1.attr2) 
1    test
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы