1

I am learning Python. I have come to the point were my functions, that have loops can't call other functions from within the loop because otherwise I get duplicate results, so I want to create a function that calls each function, gets the data out of them and assigns them to functions that execute after and need that data to work, avoiding looping.

So let's say I have this function :

def get_sound():
    for dirpath, directories, files in os.walk(XPATH):
        for sound_file in files:
            date = artist = album = title = ""
            if sound_file.endswith('.flac'):
                print('Flac file found, getting metadata and renaming...')
                flac_file = os.path.join(dirpath, sound_file)
                from mutagen.flac import FLAC
                metadata = mutagen.flac.Open(flac_file)
                for (key, value) in metadata.items():
                    if key.startswith("date"):
                        date = value[0]
                    if key.startswith("artist"):
                        artist = value[0]
                    if key.startswith("album"):
                        album = value[0]
                    if key.startswith("title"):
                        title = value[0]
                final_name = (date + " - " + artist +
                              " - " + album + " - " + title)
                dest_file = os.path.join(dirpath, final_name)
                os.renames(flac_file, dest_file)
                return (dest_file, final_name, artist, album, title)

From that function, I got a tuple of data. Now, what I want to do is to create a function :

def main():
    get_sound()
    find_key()
    make_video()

get_sound() will return data, find_key() will also return data, and make_video() will use both data to fill certain variables and execute a command with them. As the data returned has no identifier, how do I pass get_sound() and find_key() returned data to make_video ?

2
  • I'm not sure if I understand your question. Just assign it to a variable...? sound = get_sound()? Commented Feb 6, 2016 at 9:54
  • I am returning variables, what I want to do is to pass those variables to make_video() because it will use them ... Commented Feb 6, 2016 at 9:57

2 Answers 2

3

A function call (e.g. get_sound()) represents the value that the function returns. You can assign that value to a variable and use that value in subsequent operations and function calls:

def main():
    sound = get_sound()
    key = find_key()
    make_video(sound, key)

Or you can use the functions in place of their return values within operations and function calls:

def main():
    make_video(get_sound(), find_key())

This assumes that make_video takes two positional arguments, where the first can be a tuple as returned by get_sound. So make_video might look somewhat like this:

def make_video(audio, key):
    audio_destination_file, audio_name, audio_artist, audio_album, audio_title = audio
    # Do something with audio_destination_file, audio_name, audio_artist,
    # audio_album, audio_title and key ...

If instead your make_video function expects the components of the get_sound return value as separate arguments, like so:

def make_video(audio_destination_file, audio_name,
               audio_artist, audio_album, audio_title, key):
    # Do something

... then either explicitly unpack them before the call like x squared suggests or use the splat operator for unpacking when calling:

def main():
    sound = get_sound()
    key = find_key()
    make_video(*sound, key)

or

def main():
    make_video(*get_sound(), find_key())
Sign up to request clarification or add additional context in comments.

7 Comments

Ok, got that. The problem is that get_sound() returns data that will be used also on other functions, meaning that not all that data will used by make_video(). Is this bad design ? For example, make_video() will use only dest_file and final_name. artist, album, title were meant to be used by another function. Do I have to rewrite the code so each function returns only one variable ?
You don't have to rewrite your code so each function returns only one variable. Just use unpacking (dest_file, final_name, artist, album, title = get_sound()), then use the resulting variables as arguments for those other functions. But splitting the function up into smaller, independent parts might indeed be better design.
That being said, don't worry about design too much while you're still learning the basics. While it's never too early to start thinking about good and bad design, try to do one thing at a time: First, get a small part of code to work (and by that, I mean to work correctly), and only then try to get it right (from a design/style perspective), keeping it working correctly. Then proceed to write the next small part of code the same way (make it work, then make it right).
Ok, I understand it now. Thank you so much for your extended answer and the time invested !
When used in a function call (like you would here), the *-operator performs positional argument unpacking, a.k.a. positional expansion. When used in a function definition's signature, it does the reverse: It allows the function to accept an arbitrary number of positional arguments and packs them all into the argument variable it is applied to (usually called args by convention.)
|
2

Depends on how make_video()s parameters look like. If it takes a tuple as argument its:

make_video(get_sound(), find_key())

Or if it takes single arguments you can assign multiple variables with the return value, e.g:

(dest_file, final_name, artist, album, title) = get_sound()
make_video(dest_file, final_name, artist, album, title, find_key())

3 Comments

make_video is an ffmpeg subprocess command and it needs only two of the returned variables. The other variables returned were meant to be used by yet another function. Should I make each function return only the variables that will be used by another function then ?
Ah, I thought make_video() is a function by you. But yeah, it depends on your program which return values make sense. For example you can return everything now and use the last two return values later. Or you split get_sound() into two functions. Both is possible. Although the name of get_sound() is a little misleading, when it also returns the artist and album title.
Thank you for helping x squared !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.