Getting the parent of a dynamically method as a function
Sorry, this is more likely a Python question than it is a Pythonista question. But I have searched else where and can not find the answer. It also could be particular to Pythonista, not sure.
What I would like to do is , add a function to a ui Element such as a ui.Button. Then from inside that function at runtime determine the calling classes instance. so self for short.
In the sample code below, I know, I could pass the instance object as a param. Just not ideal....
I think the answer must be in the inspect module. I have tried with stack(), current(), outerframes(), I just can't seem to figure it out.
If you do have a solution to share that would be great, but could you please also comment on how robust you think the solution is.
import ui def test_func(msg): ''' i would like to get a reference to the caller here being the btn. i am pretty sure the answer lies with the inspect module, but i cant figure it out. MAYBE, its even easier than that... well that would be great ''' print msg btn = ui.Button() btn.msg = test_func btn.msg('I am on to something...')
@mikael , yes I understand you can get define a default return for querying a attr. But it just needs more than what I have done at the moment. Need to know the type of what is expected, which is not that difficult. But requires even more knowledge of what attr you are dealing with. For example you can see that the attr requires a tuple. Well that's wide open.
But you mention why I/we need it. Imagine in the ui.designer you couldn't copy and paste elements. In my mind it's the same thing. In the ui.designer you can also copy and paste attributes. Why should we not have this in code? I just think we should have.
Look I know I have some strange ideas. But in all honesty, I can't see why in a perfect world I can't just copy a object in full and or its attributes as you would in a gui. Especially if the copy is done very low level. Then I change a few attrs of the very fast memory copied object.
Just my 2 cents worth.
@Phuket2, crazy ideas push the envelope and occasionally advance the state of the art, so I am all for them. And I can understand the analogy to UI designer.
Copying plain Python objects is just that easy, but unfortunately these ones have an ObjectC monster behind the friendly facade. And copying UIKit instances even in ObjectC is not totally trivial, see this link.
Fixed a simple bug, now self.methods can be called in
import types class Extender(object): def __new__(extender_subclass, target_instance, *args, **kwargs): extender_instance = super(Extender, extender_subclass).__new__(extender_subclass) for key in dir(extender_instance): if key.startswith('__'): continue value = getattr(extender_instance, key) if callable(value): setattr(target_instance, key, types.MethodType(value.__func__, target_instance)) else: setattr(target_instance, key, value) if isinstance(extender_subclass.__init__, types.MethodType): extender_subclass.__init__.__func__(target_instance, *args, **kwargs) return target_instance
@mikael , i am struggling to get my head around your extender concept. I don't mean the way you have written it. Just a bit fancy for me 😱
If I want to add a new class to chain it so to speak, how would I do that? I tried a few things but failed.
@Phuket2, here's a quick, silly and familiar-looking example demonstrating both the subclass inheritance chain and chaining extenders around a button instance. If this is of no use, please share some problematic code.
import ui from extend import Extender class DefaultStyle(Extender): background_color = 'teal' tint_color = 'white' class BorderedStyle(DefaultStyle): border_width = .5 corner_radius = 3 class ButtonAction(Extender): def __init__(self, msg = None): self.msg = msg def action(self, sender): print self.msg button = BorderedStyle(ButtonAction(ui.Button(title = 'Click me'), 'Clicked')) button.present()
@mikael , ok. You mentioned chained before. These are nested Calls right? I am not being smart, I am just not sure of the terminology used in this context.
But even is not that practical, I would hate to nest say 5 calls
@Phuket2, I see what you mean. This version does not chain as much as it nests, that's true. Let me see if I can do something about that.
Here's one way to chain, specifically, if you do not mind "polluting" your ui components with an extra method, named
ehere for brevity.
# coding: utf-8 import ui from extend import Extender class ChainingExtender(Extender): def e(self, cls, *args, **kwargs): return cls(self, *args, **kwargs) class DefaultStyle(ChainingExtender): background_color = 'teal' tint_color = 'white' class BorderedStyle(DefaultStyle): def __init__(self, border_width): self.border_width = border_width self.border_color = 'white' class ButtonAction(ChainingExtender): def __init__(self, new_title = 'Not defined'): self.msg = new_title def action(self, sender): self.title = self.msg button = ButtonAction(ui.Button(title = 'Click me'), 'Clicked').e(BorderedStyle, 10) button.present()
@mikael , 0k I will have to look tomorrow. 1:47am here now 😱 With many black label and sodas 🎉
But I hope you don't mind, my idea is to keep pushing your idea until it breaks. When it can not be broken, not just by me , but then it should be great.