Билдер тела для запросов на Python

Пытаюсь написать билдер для отправки запросов на сервер: Есть вот такое:

class ProfileUpdate:
    def __init__(self):
        self.result = {}

    def set_auth_token(self, auth_token):
        self.result["auth_token"] = auth_token
        return self

    def set_profile(self, name, age):
        self.result["profile"] = Profile(name, age).build_profile()
        return self

    def build_body(self):
        return self.result


class Profile:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.result = {}

    def set_name(self, name):
        self.result["name"] = name
        return self

    def set_age(self, age):
        self.result["age"] = age
        return self

    def build_profile(self):
        return self.result

Если запустить в таком виде:

body = ProfileUpdate().set_auth_token("token").set_profile("alex", "20").build_body()

Получаю:

{'auth_token': 'token', 'profile': {}}

А хотелось:

{'auth_token': 'token', 'profile': {'name': 'alex', 'age': '20'}}

Подскажите, пожалуйста, где я ошибся? И как можно доработать, так что бы можно было не билдить вложенные поля, например на:

body = ProfileUpdate().set_auth_token("token").set_profile("alex").build_body()    

получать:

{'auth_token': 'token', 'profile': {'name': 'alex'}}

Ответы (1 шт):

Автор решения: CrazyElf

Подскажите, пожалуйста, где я ошибся?

В классе Profile вы выставляете поля класса name и age, но никак их не используете. А методы set_name и set_age, изменяющие значения в словаре, который вы потом возвращаете, вы просто не вызываете.

И как можно доработать, так что бы можно было не билдить вложенные поля

Используйте для функции значения по умолчанию. Есть и другие варианты, если вы хотите произвольный набор полей, то можно было бы использовать обобщённое название именованных аргументов **kvargs и работать с ним. Я ограничился вариантом с дефолтными значениями None для фиксированного списка аргументов функции.

Переделанный код:

class ProfileUpdate:
    def __init__(self):
        self.result = {}

    def set_auth_token(self, auth_token):
        self.result["auth_token"] = auth_token
        return self

    def set_profile(self, name=None, age=None):
        self.result["profile"] = Profile(name, age).build_profile()
        return self

    def build_body(self):
        return self.result


class Profile:
    def __init__(self, name, age):
        self.result = {}
        self.set_name(name)
        self.set_age(age)

    def set_name(self, name):
        if name is not None:
            self.result["name"] = name
        return self

    def set_age(self, age):
        if age is not None:
            self.result["age"] = age
        return self

    def build_profile(self):
        return self.result

body = ProfileUpdate().set_auth_token("token").set_profile("alex", "20").build_body()
print(body)

body = ProfileUpdate().set_auth_token("token").set_profile("alex").build_body()
print(body)

Вывод:

{'auth_token': 'token', 'profile': {'name': 'alex', 'age': '20'}}
{'auth_token': 'token', 'profile': {'name': 'alex'}}
→ Ссылка