Python. Refactoring a function to increase its capabilities
I can't comment much on the questions you asked about the functions that haven't been implemented yet, other than to say that passing an argument down through multiple function calls is perfectly fine.  If your code cleanly declares what arguments it expects and what each argument does it shouldn't be a problem.  I did my best to clean up the code you provided, mostly just fixing PEP8 style stuff and trying my best to fix the typing (although it's hard without having any of your dependencies to check against, I tried to tidy up stuff like having profile_data go from dict to list back to dict).  I also replaced the janky in-place dictionary modification with a comprehension.

from typing import Dict, Optional


def show_profile(
    user_id: str,
    profile_data: Optional[Dict[str, str]] = None,
    photo: Optional[str] = None
) -&gt; Message:  # fixme: what's the actual type of this?
    """
    A profile is a message object with a photo, text (caption), and markup.
    If no profile data is specified it will be loaded from the db.
    If no photo is specified, it will be loaded from the db, 
    or DEFAULT_PHOTO will be used.
    """
    # db_execute - manually created function,
    # the short version of cursor.execute (pymysql)"""
    if profile_data is None:
        goal, age, gender, country, city, comment = db_execute(
            'SELECT goal, age, gender, country, city, comment '
            'FROM users '
            'WHERE user_id = %s',
            user_id, fetchone=True, get_tuple=True
        )
        profile_data = {
            'Goal': goal,
            'Age': age,
            'Gender': gender
            'Country': country,
            'City': city,
            'Comment': comment
        }

    if photo is None:
        photo = db_execute(
            'SELECT photo '
            'FROM photos '
            'WHERE user_id = %s and id = (SELECT MIN(id) FROM photos)',
            user_id, fetchone=True
        ) or DEFAULT_PHOTO[0]

    # Get first and last name of the user.
    username = bot.get_chat(user_id).username

    # add link to user inside a message
    caption = f'Имя - &lt;a href="tg://user?id={user_id}"&gt;{username}&lt;/a&gt;.\n'

    # Remove None data from profile
    profile_data = {k: v for k, v in profile_data.items() if v is not None}
    # Add it to the caption
    for k, v in profile_data.items():
        caption += f'{key} - {value}\n'

    return bot.send_photo(
        user_id,
        photo,
        caption=caption,
        parse_mode=ParseMode.HTML,
        reply_markup=get_scrolling_profile_keyboard(user_id)
    )


def get_scrolling_photos_keyboard(shower_id: str) -&gt; InlineKeyboardMarkup:
    return InlineKeyboardMarkup([[
        InlineKeyboardButton('&lt;', callback_data=f'back_photo {shower_id}'),
        InlineKeyboardButton('&gt;', callback_data=f'next_photo {shower_id}')]])


def get_scrolling_profiles_keyboard(shower_id: str) -&gt; InlineKeyboardMarkup:
    """
    Add more buttons for scrolling, group of photos and group of profiles
    (the profile is still just a message object with photo, text, and buttons)
    (The second missing feature)
    """
    keyboard_obj = get_scrolling_photos_keyboard(shower_id)
    buttons = keyboard_obj.inline_keyboard  # Get list from object
    buttons.append(InlineKeyboardButton('Back', callback_data=f'back_profile'))
    buttons.append(InlineKeyboardButton('Next', callback_data=f'next_profile'))
    return InlineKeyboardMarkup(buttons)