best way to distribute keyword arguments?












4














What's the approved programming pattern for distributing keyword arguments among called functions?



Consider this contrived (and buggy) example:



def create_box(**kwargs):
box = Box()
set_size(box, **kwargs)
set_appearance(box, **kwargs)

def set_size(box, width=1, height=1, length=1):
...

def set_appearance(box, material='cardboard', color='brown'):
...


Obviously the set_size() method will object to receiving material or color keyword arguments, just as set_appearance() will object to receiving width, height, or length arguments.



There's a valid argument that create_box() should make all of the keyword and defaults explicit, but the obvious implementation is rather unwieldy:



def create_box(width=1, height=1, length=1, material='cardboard', color='brown'):
box = Box()
set_size(box, width=width, height=height, length=length)
set_appearance(box, material=material, color=color)


Is there a more Pythonic way to approach this?










share|improve this question






















  • IMO the kind of runtime bugs you can get by trying to hide a long list of args inside a kwargs can often be more unwieldy than just listing out the arguments explicitly
    – DaveBensonPhillips
    Nov 12 at 15:05


















4














What's the approved programming pattern for distributing keyword arguments among called functions?



Consider this contrived (and buggy) example:



def create_box(**kwargs):
box = Box()
set_size(box, **kwargs)
set_appearance(box, **kwargs)

def set_size(box, width=1, height=1, length=1):
...

def set_appearance(box, material='cardboard', color='brown'):
...


Obviously the set_size() method will object to receiving material or color keyword arguments, just as set_appearance() will object to receiving width, height, or length arguments.



There's a valid argument that create_box() should make all of the keyword and defaults explicit, but the obvious implementation is rather unwieldy:



def create_box(width=1, height=1, length=1, material='cardboard', color='brown'):
box = Box()
set_size(box, width=width, height=height, length=length)
set_appearance(box, material=material, color=color)


Is there a more Pythonic way to approach this?










share|improve this question






















  • IMO the kind of runtime bugs you can get by trying to hide a long list of args inside a kwargs can often be more unwieldy than just listing out the arguments explicitly
    – DaveBensonPhillips
    Nov 12 at 15:05
















4












4








4







What's the approved programming pattern for distributing keyword arguments among called functions?



Consider this contrived (and buggy) example:



def create_box(**kwargs):
box = Box()
set_size(box, **kwargs)
set_appearance(box, **kwargs)

def set_size(box, width=1, height=1, length=1):
...

def set_appearance(box, material='cardboard', color='brown'):
...


Obviously the set_size() method will object to receiving material or color keyword arguments, just as set_appearance() will object to receiving width, height, or length arguments.



There's a valid argument that create_box() should make all of the keyword and defaults explicit, but the obvious implementation is rather unwieldy:



def create_box(width=1, height=1, length=1, material='cardboard', color='brown'):
box = Box()
set_size(box, width=width, height=height, length=length)
set_appearance(box, material=material, color=color)


Is there a more Pythonic way to approach this?










share|improve this question













What's the approved programming pattern for distributing keyword arguments among called functions?



Consider this contrived (and buggy) example:



def create_box(**kwargs):
box = Box()
set_size(box, **kwargs)
set_appearance(box, **kwargs)

def set_size(box, width=1, height=1, length=1):
...

def set_appearance(box, material='cardboard', color='brown'):
...


Obviously the set_size() method will object to receiving material or color keyword arguments, just as set_appearance() will object to receiving width, height, or length arguments.



There's a valid argument that create_box() should make all of the keyword and defaults explicit, but the obvious implementation is rather unwieldy:



def create_box(width=1, height=1, length=1, material='cardboard', color='brown'):
box = Box()
set_size(box, width=width, height=height, length=length)
set_appearance(box, material=material, color=color)


Is there a more Pythonic way to approach this?







python keyword-argument






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 at 14:53









fearless_fool

20.7k1694158




20.7k1694158












  • IMO the kind of runtime bugs you can get by trying to hide a long list of args inside a kwargs can often be more unwieldy than just listing out the arguments explicitly
    – DaveBensonPhillips
    Nov 12 at 15:05




















  • IMO the kind of runtime bugs you can get by trying to hide a long list of args inside a kwargs can often be more unwieldy than just listing out the arguments explicitly
    – DaveBensonPhillips
    Nov 12 at 15:05


















IMO the kind of runtime bugs you can get by trying to hide a long list of args inside a kwargs can often be more unwieldy than just listing out the arguments explicitly
– DaveBensonPhillips
Nov 12 at 15:05






IMO the kind of runtime bugs you can get by trying to hide a long list of args inside a kwargs can often be more unwieldy than just listing out the arguments explicitly
– DaveBensonPhillips
Nov 12 at 15:05














3 Answers
3






active

oldest

votes


















4














You could add **kwargs as the last argument to the functions that would otherwise become annoyed.



def create_box(**kwargs):
box = Box()
set_size(box, **kwargs)
set_appearance(box, **kwargs)

def set_size(box, width=1, height=1, length=1, **kwargs):
...

def set_appearance(box, material='cardboard', color='brown', **kwargs):
...





share|improve this answer





























    3














    Assuming you can't alter set_size or set_appearance, you could filter kwargs depending on the expected keword arguments, I'm not sure if this is the most pythonic way though...



    import inspect

    def create_box(**kwargs):
    box = None
    set_size_args = inspect.getargspec(set_size).args
    set_size(box, {k:v for k,v in kwargs.items() if k in set_size_args})
    set_appearance_args = inspect.getargspec(set_appearance).args
    set_appearance(box, {k:v for k,v in kwargs.items() if k in set_appearance_args})


    def set_size(box, width=1, height=1, length=1):
    pass

    def set_appearance(box, material='cardboard', color='brown'):
    pass

    create_box(width=1, height=1, length=1, material='', color='')


    (use inspect.signature() for Python 3)






    share|improve this answer































      1














      Hm, personally I would pass an object containing all of the params I needed. That way you're only passing one param all along.



      Example:



      class BoxDefinition:
      def __init__(self, width=1, height=1, length=1, material='cardboard', color='brown'):
      self.width = width
      self.height = height
      # and so on for the rest of the params ...


      Internally in the each method you can read from this object:



      def create_box(box_definition):
      box = Box()
      set_size(box, box_definition)
      set_appearance(box, box_definition)

      def set_size(box, box_definition):
      width = box_definition.width

      def set_appearance(box, box_definition):
      color = box_definition.color


      Then you can call it like this:



      definition = BoxDefinition(width=2, height=3, length=4)
      create_box(definition)


      In fact, you can even make BoxDefinition and attribute of the Box class, and then the only thing you'd have to pass is Box.






      share|improve this answer





















      • This can get unwieldy if you have functions sharing the same kwarg but with different default values.
        – Idlehands
        Nov 12 at 15:19










      • Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
        – LeKhan9
        Nov 12 at 15:41











      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53264680%2fbest-way-to-distribute-keyword-arguments%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      4














      You could add **kwargs as the last argument to the functions that would otherwise become annoyed.



      def create_box(**kwargs):
      box = Box()
      set_size(box, **kwargs)
      set_appearance(box, **kwargs)

      def set_size(box, width=1, height=1, length=1, **kwargs):
      ...

      def set_appearance(box, material='cardboard', color='brown', **kwargs):
      ...





      share|improve this answer


























        4














        You could add **kwargs as the last argument to the functions that would otherwise become annoyed.



        def create_box(**kwargs):
        box = Box()
        set_size(box, **kwargs)
        set_appearance(box, **kwargs)

        def set_size(box, width=1, height=1, length=1, **kwargs):
        ...

        def set_appearance(box, material='cardboard', color='brown', **kwargs):
        ...





        share|improve this answer
























          4












          4








          4






          You could add **kwargs as the last argument to the functions that would otherwise become annoyed.



          def create_box(**kwargs):
          box = Box()
          set_size(box, **kwargs)
          set_appearance(box, **kwargs)

          def set_size(box, width=1, height=1, length=1, **kwargs):
          ...

          def set_appearance(box, material='cardboard', color='brown', **kwargs):
          ...





          share|improve this answer












          You could add **kwargs as the last argument to the functions that would otherwise become annoyed.



          def create_box(**kwargs):
          box = Box()
          set_size(box, **kwargs)
          set_appearance(box, **kwargs)

          def set_size(box, width=1, height=1, length=1, **kwargs):
          ...

          def set_appearance(box, material='cardboard', color='brown', **kwargs):
          ...






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 12 at 15:00









          Rob Bricheno

          2,315218




          2,315218

























              3














              Assuming you can't alter set_size or set_appearance, you could filter kwargs depending on the expected keword arguments, I'm not sure if this is the most pythonic way though...



              import inspect

              def create_box(**kwargs):
              box = None
              set_size_args = inspect.getargspec(set_size).args
              set_size(box, {k:v for k,v in kwargs.items() if k in set_size_args})
              set_appearance_args = inspect.getargspec(set_appearance).args
              set_appearance(box, {k:v for k,v in kwargs.items() if k in set_appearance_args})


              def set_size(box, width=1, height=1, length=1):
              pass

              def set_appearance(box, material='cardboard', color='brown'):
              pass

              create_box(width=1, height=1, length=1, material='', color='')


              (use inspect.signature() for Python 3)






              share|improve this answer




























                3














                Assuming you can't alter set_size or set_appearance, you could filter kwargs depending on the expected keword arguments, I'm not sure if this is the most pythonic way though...



                import inspect

                def create_box(**kwargs):
                box = None
                set_size_args = inspect.getargspec(set_size).args
                set_size(box, {k:v for k,v in kwargs.items() if k in set_size_args})
                set_appearance_args = inspect.getargspec(set_appearance).args
                set_appearance(box, {k:v for k,v in kwargs.items() if k in set_appearance_args})


                def set_size(box, width=1, height=1, length=1):
                pass

                def set_appearance(box, material='cardboard', color='brown'):
                pass

                create_box(width=1, height=1, length=1, material='', color='')


                (use inspect.signature() for Python 3)






                share|improve this answer


























                  3












                  3








                  3






                  Assuming you can't alter set_size or set_appearance, you could filter kwargs depending on the expected keword arguments, I'm not sure if this is the most pythonic way though...



                  import inspect

                  def create_box(**kwargs):
                  box = None
                  set_size_args = inspect.getargspec(set_size).args
                  set_size(box, {k:v for k,v in kwargs.items() if k in set_size_args})
                  set_appearance_args = inspect.getargspec(set_appearance).args
                  set_appearance(box, {k:v for k,v in kwargs.items() if k in set_appearance_args})


                  def set_size(box, width=1, height=1, length=1):
                  pass

                  def set_appearance(box, material='cardboard', color='brown'):
                  pass

                  create_box(width=1, height=1, length=1, material='', color='')


                  (use inspect.signature() for Python 3)






                  share|improve this answer














                  Assuming you can't alter set_size or set_appearance, you could filter kwargs depending on the expected keword arguments, I'm not sure if this is the most pythonic way though...



                  import inspect

                  def create_box(**kwargs):
                  box = None
                  set_size_args = inspect.getargspec(set_size).args
                  set_size(box, {k:v for k,v in kwargs.items() if k in set_size_args})
                  set_appearance_args = inspect.getargspec(set_appearance).args
                  set_appearance(box, {k:v for k,v in kwargs.items() if k in set_appearance_args})


                  def set_size(box, width=1, height=1, length=1):
                  pass

                  def set_appearance(box, material='cardboard', color='brown'):
                  pass

                  create_box(width=1, height=1, length=1, material='', color='')


                  (use inspect.signature() for Python 3)







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 12 at 15:12

























                  answered Nov 12 at 15:06









                  Chris_Rands

                  15.3k53869




                  15.3k53869























                      1














                      Hm, personally I would pass an object containing all of the params I needed. That way you're only passing one param all along.



                      Example:



                      class BoxDefinition:
                      def __init__(self, width=1, height=1, length=1, material='cardboard', color='brown'):
                      self.width = width
                      self.height = height
                      # and so on for the rest of the params ...


                      Internally in the each method you can read from this object:



                      def create_box(box_definition):
                      box = Box()
                      set_size(box, box_definition)
                      set_appearance(box, box_definition)

                      def set_size(box, box_definition):
                      width = box_definition.width

                      def set_appearance(box, box_definition):
                      color = box_definition.color


                      Then you can call it like this:



                      definition = BoxDefinition(width=2, height=3, length=4)
                      create_box(definition)


                      In fact, you can even make BoxDefinition and attribute of the Box class, and then the only thing you'd have to pass is Box.






                      share|improve this answer





















                      • This can get unwieldy if you have functions sharing the same kwarg but with different default values.
                        – Idlehands
                        Nov 12 at 15:19










                      • Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
                        – LeKhan9
                        Nov 12 at 15:41
















                      1














                      Hm, personally I would pass an object containing all of the params I needed. That way you're only passing one param all along.



                      Example:



                      class BoxDefinition:
                      def __init__(self, width=1, height=1, length=1, material='cardboard', color='brown'):
                      self.width = width
                      self.height = height
                      # and so on for the rest of the params ...


                      Internally in the each method you can read from this object:



                      def create_box(box_definition):
                      box = Box()
                      set_size(box, box_definition)
                      set_appearance(box, box_definition)

                      def set_size(box, box_definition):
                      width = box_definition.width

                      def set_appearance(box, box_definition):
                      color = box_definition.color


                      Then you can call it like this:



                      definition = BoxDefinition(width=2, height=3, length=4)
                      create_box(definition)


                      In fact, you can even make BoxDefinition and attribute of the Box class, and then the only thing you'd have to pass is Box.






                      share|improve this answer





















                      • This can get unwieldy if you have functions sharing the same kwarg but with different default values.
                        – Idlehands
                        Nov 12 at 15:19










                      • Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
                        – LeKhan9
                        Nov 12 at 15:41














                      1












                      1








                      1






                      Hm, personally I would pass an object containing all of the params I needed. That way you're only passing one param all along.



                      Example:



                      class BoxDefinition:
                      def __init__(self, width=1, height=1, length=1, material='cardboard', color='brown'):
                      self.width = width
                      self.height = height
                      # and so on for the rest of the params ...


                      Internally in the each method you can read from this object:



                      def create_box(box_definition):
                      box = Box()
                      set_size(box, box_definition)
                      set_appearance(box, box_definition)

                      def set_size(box, box_definition):
                      width = box_definition.width

                      def set_appearance(box, box_definition):
                      color = box_definition.color


                      Then you can call it like this:



                      definition = BoxDefinition(width=2, height=3, length=4)
                      create_box(definition)


                      In fact, you can even make BoxDefinition and attribute of the Box class, and then the only thing you'd have to pass is Box.






                      share|improve this answer












                      Hm, personally I would pass an object containing all of the params I needed. That way you're only passing one param all along.



                      Example:



                      class BoxDefinition:
                      def __init__(self, width=1, height=1, length=1, material='cardboard', color='brown'):
                      self.width = width
                      self.height = height
                      # and so on for the rest of the params ...


                      Internally in the each method you can read from this object:



                      def create_box(box_definition):
                      box = Box()
                      set_size(box, box_definition)
                      set_appearance(box, box_definition)

                      def set_size(box, box_definition):
                      width = box_definition.width

                      def set_appearance(box, box_definition):
                      color = box_definition.color


                      Then you can call it like this:



                      definition = BoxDefinition(width=2, height=3, length=4)
                      create_box(definition)


                      In fact, you can even make BoxDefinition and attribute of the Box class, and then the only thing you'd have to pass is Box.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 12 at 15:04









                      LeKhan9

                      921112




                      921112












                      • This can get unwieldy if you have functions sharing the same kwarg but with different default values.
                        – Idlehands
                        Nov 12 at 15:19










                      • Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
                        – LeKhan9
                        Nov 12 at 15:41


















                      • This can get unwieldy if you have functions sharing the same kwarg but with different default values.
                        – Idlehands
                        Nov 12 at 15:19










                      • Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
                        – LeKhan9
                        Nov 12 at 15:41
















                      This can get unwieldy if you have functions sharing the same kwarg but with different default values.
                      – Idlehands
                      Nov 12 at 15:19




                      This can get unwieldy if you have functions sharing the same kwarg but with different default values.
                      – Idlehands
                      Nov 12 at 15:19












                      Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
                      – LeKhan9
                      Nov 12 at 15:41




                      Fair point, I figured in the OPs scenario this would not be the case as the sets of kwargs are unique among functions
                      – LeKhan9
                      Nov 12 at 15:41


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53264680%2fbest-way-to-distribute-keyword-arguments%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      List item for chat from Array inside array React Native

                      Thiostrepton

                      Caerphilly