omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Setting Attributes for a Custom View class > best approach?

    Pythonista
    4
    16
    9446
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Phuket2
      Phuket2 @ccc last edited by

      @ccc , what about? No loop, just update the dict

      def make_label(self, **kwargs):
      	defaults = {'background_color': 1,    # create a dict of default values
      	'border_color': 0.6,
      	'border_width': 0.7,
      	'frame': (0, 0, 100, 100)}
      	'''
      	for attr, value in kwargs.items():    # create merged dict overwriting
      		defaults[attr] = value            # default values w/ kwarg values
      	'''
      	defaults.update(kwargs)
      	label = ui.Label()                    # make the label
      	for attr, value in defaults.items():  # for all attrs in merged dict
      		setattr(label, attr, value)       # set them in the iu.Label
      	return label
      
      1 Reply Last reply Reply Quote 1
      • ccc
        ccc last edited by ccc

        Nice! @Phuket2 Combining all optimizations we get...

            def make_label(self, **kwargs):
                defaults = {'background_color': 1,  # create a dict of default values
                            'border_color': 0.6,
                            'border_width': 0.7,
                            'frame': (0, 0, 100, 100)}
                defaults.update(kwargs)             # merge in all kwargs values
                return ui.Label(**defaults)         # return ui.Label w/ merged values
        
        Phuket2 1 Reply Last reply Reply Quote 0
        • Phuket2
          Phuket2 @ccc last edited by

          @ccc, super nice 💋💋💋

          1 Reply Last reply Reply Quote 0
          • dgelessus
            dgelessus last edited by dgelessus

            def make_label(self, **kwargs):
                return ui.Label(
                    background_color=1,
                    border_color=0.6,
                    border_width=0.7,
                    frame=(0, 0, 100, 100),
                    **kwargs
                )
            

            (nevermind, this actually complains about duplicate kwargs... I thought they changed that in Python 3.5...)

            Phuket2 1 Reply Last reply Reply Quote 0
            • Phuket2
              Phuket2 @dgelessus last edited by

              @dgelessus , lol. I wish I had thought of that 😬

              1 Reply Last reply Reply Quote 0
              • dgelessus
                dgelessus last edited by

                Ah, but this works (3.5 only):

                    def make_label(self, **kwargs):
                        return ui.Label(**{
                            'background_color': 1,
                            'border_color': 0.6,
                            'border_width': 0.7,
                            'frame': (0, 0, 100, 100),
                            **kwargs
                        })
                1 Reply Last reply Reply Quote 1
                • cook
                  cook last edited by

                  @Phuket2 @ccc @dgelessus Sorry... I think maybe my point was missed a little. Originally I tried that and then quickly realized I would have a problem.

                  Let's say I have three different ui components to add to my view. But for the class I want to be able to "pass around" the kwargs to set the appropriate attributes for each component. In the example I just had a label, let's say I also have a textview and a slider. Notice that we're also initializing super: super().__init__(**kwargs)

                  This leaves us with four objects that will take a frame keyword argument.
                  If I pass frame as an argument, ViewObject(frame=(0,0,100,100), and then "pass around" the kwargs to other methods for making the other view objects, I will end up with everything having this same frame (or background color etc). That is likely not what I intend to happen have happen.

                  So, I thought to make distinction by using a different keyword (such as 'label_bgcolor') but defining the intended attribute name in the tuple.

                  I hope that makes sense. So... is it a good way? I guess it boils down to: using distinguishable keyword arguments among multiple views in a custom view class.

                  1 Reply Last reply Reply Quote 0
                  • cook
                    cook last edited by

                    @dgelessus that looks like a nice approach, but also not everything can be set in initializing most ui components. (Like I can't set a button action like ui.Button(action=this)

                    Phuket2 1 Reply Last reply Reply Quote 0
                    • ccc
                      ccc last edited by ccc

                      @cook I don't like the approach of mixing the attrs in a single dict but here is the code:

                          def make_label(self, **kwargs):
                              defaults = {'background_color': 1,  # create a dict of default values
                                          'border_color': 0.6,
                                          'border_width': 0.7,
                                          'frame': (0, 0, 100, 100)}
                              for attr, value in kwargs.items():
                                  if attr.startswith('label_'):
                                      defaults[attr[len('label_'):]] = value
                              return ui.Label(**defaults)         # return ui.Label w/ merged values
                      
                      1 Reply Last reply Reply Quote 1
                      • Phuket2
                        Phuket2 @cook last edited by

                        @cook , sorry yes I think that went a little off track.
                        I have an idea, maybe not good idea. The other guys can way in.
                        But you could use the named args to pass though dicts that you would use the same as kwargs for your objects, then the real kwargs would be passed through to super(). I didn't write the whole thing out.
                        But I think it's a way. But not sure it's a good way

                        class MyClass(ui.View):
                        	def __init__(self, slider_args, label_args,  *args, **kwargs):
                        		super().__init__(*args, **kwargs)
                        		
                        if __name__ == '__main__':
                        	slider_kw = dict(bg_color = green)
                        	label_kw = dict(frame=(0, 0, 64, 32), bg_color = 'pink')
                        	v = MyClass(slider_args = slider_kw, label_ars = label_kw, bg_color = blue)
                        
                        1 Reply Last reply Reply Quote 1
                        • cook
                          cook last edited by

                          @ccc yes! Looks more 'pythonic'. I also didn't like having this strange dictionary with a tuple but couldn't think at the moment about a different way. startswith is nice. Real nice.

                          Although, just returning ui.Label(**defaults) may be okay for some attributes, but some args can't be passed that way and it seems to vary among the UI components. Example:

                          >>> import ui
                          >>> def hello(sender):
                          ...   pass
                          ...   
                          >>> tf = ui.TextField(action=hello)
                          >>> tf.action                      # << wasn't assigned from the argument!
                          >>> tf.action = hello
                          >>> tf.action
                          <function hello at 0x10a1a1a60>
                          

                          So using setattr can provide someone with more flexibility for kwargs than even the original UI component.

                          @phuket2 I think that's not a bad approach! Would definitely work and save typing in 'label_...' Etc. But it seems just to get one attribute (let's say I want to just set the label background color), I'd have to do a lot of work to get it.

                          Phuket2 1 Reply Last reply Reply Quote 0
                          • cook
                            cook last edited by

                            Really... Thanks for the input guys... !
                            @phuket2 @ccc @dgelessus

                            1 Reply Last reply Reply Quote 1
                            • ccc
                              ccc last edited by

                              @cook I think you now have all the components required to put together your dream solution.

                              1 Reply Last reply Reply Quote 2
                              • Phuket2
                                Phuket2 @cook last edited by

                                @cook , I don't want to complicate things, but to get a attr from any of your objects is just as easy as the reference you provide. The setting of and retrieving of the attrs are not connected.

                                But I think of one thing. The first thread was about share code. Meaning it's a lib for other programmers to use. That is different from creating a private function for use by yourself.
                                So I mean, the more configurable your class can be it has a better chance to serve more people's purposes without modifying the base code.
                                It's tricky. I struggle with it all the time. Of course you need a nice clean API for the programmers to call also. A balancing act.

                                But the good thing is you have done it. If it's the best implementation or not, who cares. You have something that works. Then it's just a matter of refinement after that.
                                Although the above with the kwargs went off track a little to your exact question, still some very good info there.

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post
                                Powered by NodeBB Forums | Contributors