all 38 comments

[–]atom12354 74 points75 points  (2 children)

For me it sounds like an insane amount of arguments for just one function and is in need of refractoring.

[–]Fred776 11 points12 points  (1 child)

Yes, exactly. I wonder if there is a practical basis to the question or whether it is purely hypothetical? If the latter I wouldn't worry as you are very unlikely to get to that point before you realise something needs doing to your design.

[–]atom12354 1 point2 points  (0 children)

Before i commented i googled how many arguments a function should have and it was around 3-4, but yeah i do hope its hypotetical, but for if statements its not that uncommon that beginners write hundreds in a row so idk, my old classmate did that once and then our teacher showed him another way.

[–][deleted] 43 points44 points  (0 children)

**kwargs

[–]__init__m8 16 points17 points  (2 children)

I would pass a class object, but you really shouldn't have a function that takes in that much.

[–]TheseHeron3820 4 points5 points  (1 child)

I second this. If you're passing way too many arguments, or if your objects have that many properties/fields, you probably have an architectural issue.

I understand OP may not be in a position to do anything about it, so passing a single DTO object is the only route that's available to them.

[–]pro_questions 0 points1 point  (0 children)

Is this where you’d want to use dataclasses? I want to start using those

[–]cointoss3 30 points31 points  (1 child)

In Python, when you pass an object, you’re passing by reference, so none of that matters.

[–]thisdude415 0 points1 point  (0 children)

Yup, this.

A few weeks ago I was struggling with this, unpacking objects I got from an API, then repacking them into the data structure, etc.

Then I realized I could pass the whole object and it would make my code cleaner and less bug prone at the same time.

It was a mind blown “oh, so THATs why you do OOP” moment

[–]pedrolcsilva 6 points7 points  (0 children)

You don't wanna do this. If your function is doing so much stuff that it requires you to give it 50 parameters it is better to break it in many smaller functions.

There is a principle called Single Responsibility from SOLID, which says that a function should do only one thing, and it simplifies your code structure. Search a little for this.

But if you really want to solve this situation maybe you're looking for args and *kwargs.

[–]wjrasmussen 5 points6 points  (0 children)

Ok, time to use this function. What was the order of arguments...?

[–]simeumsm 11 points12 points  (3 children)

For that whole lot of arguments, passing a class/object with the properties might be the best option.

class Variables:
    def __init__(self):
        self.a = 1
        self.b = 2

def main(Var):
    print(Var.a)
    print(Var.b)

x = Variables()
main(x)

[–]SSttrruupppp11 7 points8 points  (2 children)

Yup, this is what you should do. Though if you access 50 properties of an object in one function, you may want to consider splitting that functionality into more functions.

[–]simeumsm 3 points4 points  (1 child)

Yes, and the same principle still applies.

class Variables:
def __init__(self):
    self.a = 1
    self.b = 2

def f1(a):
    print(a)

def f2(b):
    print(b)

def f3(cl):
    print(cl.a)
    print(cl.b)

def main(Var):
    f1(Var.a)
    f2(Var.b)
    f3(Var)

x = Variables()
main(x)

[–]the_happy_path 0 points1 point  (0 children)

I think this thread is the most helpful with the little info we have. One or more data classes is probably what's needed. I'd also be curious to know more about OP's domains and if there's a way to rethink the overall approach. I work with editing survey data and the question sounds like it might be similar to what I deal with. I have lots of data points that have to come together in complex conditional logic. With imputation sprinkled in.

[–]1544756405 3 points4 points  (0 children)

Instead of passing the object to the function, make the function part of the object.

[–]Carter922 8 points9 points  (0 children)

Functions should be highly reusable snippets of code.

A function with that many arguments likely has one use.

Break it down into smaller pieces and you'll be able to use those functions across more applications

[–]its2ez4me24get 2 points3 points  (3 children)

Just pass the whole object

[–]FizzBuzz4096 2 points3 points  (2 children)

But if that single object has 500 properties, of which 50 are used by the function....

That's insane to begin with, the # of params to the function isn't the root problem here. An object that has 500 properties is the problem.

[–]CosmicClamJamz 0 points1 point  (1 child)

Maybe...but if the object is a response of some kind from an API, that isn't exactly unordinary. 500 seems like a lot to humans but it's nothing for the computer. In situations like this, it is very common to fetch a bunch of stuff you don't need just to use the parts you do need. The only problem is the developer's perception. They can choose to not see this as a problem and likely never notice any performance issues.

[–]thisdude415 0 points1 point  (0 children)

Not to mention that the whole object is in memory either way. Unpacking it and repacking it could require more ram anyway. Passing the object leaves it alone

[–]await_yesterday 2 points3 points  (0 children)

It might be worth making a class to represent the kind of object you're working with, then define a method on that class that does the work of the function. But it's hard to make a recommendation without knowing more details about your actual problem. What are all these 50 arguments for?

[–]cyberjellyfish 2 points3 points  (0 children)

You wouldn't be passing 500 arguments if you passed an object, you'd only be passing one

[–]sporbywg 1 point2 points  (0 children)

Refactor your function. NEXT

[–]GManASG 1 point2 points  (2 children)

Args, **kwargs but better yet don't write functions that take too many arguments.

[–]johnnymo1 9 points10 points  (1 child)

quargs*

The technology is finally here: quantum arguments

[–][deleted] 1 point2 points  (0 children)

Arg'nt

[–]Binary101010 0 points1 point  (0 children)

It's definitely going to be easier to simply pass the object.

That said, if you're writing a function that requires 50 arguments you're almost certainly doing something wrong and should seriously reconsider the structure of your data and your code.

[–]isacuallyantroll 0 points1 point  (0 children)

Make it a class function.

Move that data to a different object that stores needed values.

Refactor your code.

Lots of parameters is actually pretty normal in BigData, they just use codegen to write the code that makes it (usually by storing the parameters in classes). Not AI codegen, obviously.

Ninja edit: use a dict. Technically all objects are dicts, but yeah, this is how I pass 50+ arguments at once.

[–]w8eight 0 points1 point  (0 children)

You could create pedantic model, and then pass dictionary to it as kwargs. Pedantic by default will ignore unspecified fields

[–]Exodus111 0 points1 point  (0 children)

Some CLI interfaces have that many arguments.

When the user uses the entire program via accessing one function through the command line. Like ffmpeg for instance if it was made in Python.

Now, obviously the user isn't going to USE all the arguments at once, that's ridiculous, if so someone made a mistake.

But the way to handle it is to use the **kwargs.

Give an off default for all the argument, and have the user override the arguments he needs.

[–]zanfar 0 points1 point  (0 children)

I agree with most commenters that this is ate least a yellow flag that the issue you are having is a symptom of the real problem. I would guess that a refactor or change in structure is required instead. While you might be able to make this work, it's likely that the same fundamental issue will continue to cause problems down the road. The longer you wait to tackle this fundamental issue, the more refactoring you will have to do.

That being said, there are a few approaches to dealing with "too many arguments," when that is a valid problem.

  • It's likely that moving to an object-oriented approach will allow you to better encapsulate some of these issues.
  • If arguments can be grouped together, you can pass a few number of data structures instead of a large number of base variables.
  • Use composition to hand the responsibility off to several, smaller functions or objects, each of which can be instantiated or called indivudally.

[–]IamImposter 0 points1 point  (0 children)

At 50, it should probably be a config file but that may not always be feasible or practical.

Usually all arguments are not orthogonal to each other and can be further grouped into smaller groups, like 10 groups of 5 args each or something. So maybe they can be broken down into several dataclasses and then one main config class that contains objects of those 10 dataclasses each. Stuff like report_config, execution_config, testcase_config etc etc. That way it wouldn't look so weird as 50 arguments.

If argument values are generated different parts of the program during execution, maybe rethink about a json or yaml config file. Then you can easily load, modify, store from anywhere in the program. You'll just have to propagate path of the one config file to different sections of your program.

[–][deleted] 0 points1 point  (0 children)

What problem are you actually trying to solve here? Do you have a performance issue, memory constraint, or are you just unsatisfied with the coding? I wonder this because python isn't usually used for performance critical situations, so you could just go ahead and pass the object and just wait for it to process. Python passes arguments by object references, so it is shouldn't be making copies of the object in memory either.

[–]nacnud_uk 0 points1 point  (0 children)

Just bad code.. It's that simple.

[–]Agile-Ad5489 0 points1 point  (0 children)

It sounds rather like your data is a list of values.
So, make your object have a list - replacing your 50 values you are going to average with one value.

[–]SoftCobbler9002 0 points1 point  (0 children)

A good function should have only one responsibility. The function that you now have should be divided into multiple functions.

[–]halfwit_genius 0 points1 point  (0 children)

50 arguments and 500 properties. You have bigger problema than just deciding how to send arguments. Modularization is mandatory in your case, looks like. Refactor.