-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
py: Add simple mechanism for linear native inheritance, use it to simplify stream classes #4360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Will work for types that have a locals dict and use single inheritance.
Total change in code size for this patch: bare-arm: +8 minimal x86: +16 unix x64: -336 [incl -160(data)] unix nanbox: -344 [incl -288(data)] stm32: -64 cc3200: -88 esp8266: -168 esp32: -108 [incl -120(data)]
I tried this on the Unix build with the following outcome. (Samples work on CPython 3.7.1).
It isn't clear (to me) how to create a constructor:
|
Yeah, I definitely thought that it needs to be implement finally too, but just thinking about it for a bit, I'm sure how it's implemented in this patch (the most obvious way, which first comes to mind) is the best way.
That leads to the obvious idea that this extension should be implemented on the level of local_dict's. E.g., the last entry would have a special value for qstr, and a pointer to parent locals_dict. Anything like that should still be done while thinking for possible optimizations to native types locals_dict entries:
Actually, looking into that stuff, one immediately starts to wonder why method array is wrapped in into an instance of All these points combined lead to the following idea:
E.g.
becomes
|
I guess I misunderstood the purpose of this PR, and it's not intended to expose native class inheritance at the Python level. |
That is correct, it is purely at the C level. |
See tools/cc1 which turns native
To define a user type, you pass in a dict, and that gets stored directly into |
It could eventually be made into a first-class parent type, with instance checks etc (if it could be done efficiently).
But this doesn't attempt to solve the issue of native inheritance, and if that is to be solved eventually it can be built upon the technique proposed here, rather than having a separate technique for extending locals_dict.
This might be a nice idea, but would require checking each use of locals_dict to see if it was from a native type, or a user defined type (or convert the dict of a user defined type upon construction). |
I doubt that what happens there (re: "That's why"). That might be like you describe 5 years ago, but it's no longer the case. uPy type system allows to completely override attribute/method lookup in an object using ->attr vmethod. And that's what instance type enjoy - they implement completely different, and self-contained, algorithm. (The reason of that is of course that such a lookup for instance types is much more complex (==slower) than for native types). So "why it's a full dict object" is because native and instance type shared the algorithm initially. But now they don't, and as a whole algorithms are self-contained, they each may be optimized to use the data structures the most efficient for each of them.
The operation on the (very) critical path is lookup, and that's why I propose to optimize it. And it's already a virtual method of a type. What other operations we have which operate on method tables? dir() and help()? Sure, those would need to be updated, but they aren't on critical path. |
But is there an issue there to solve?
Sure, both methods could be blended to work nice together, a particular usecase may choose to use either a special "parent" marker in locals_dict, or full-fledged parent type in ->parent. But again, nothing so far calls for the need of such explicit parents. |
@dpgeorge - Lines 1065 to 1080 in 454977f
Without it, I need to either include all parent methods in every child, or implement my own attr that duplicates that code, just for this purpose.
Any chance of getting this merged? |
…ld stop when reaching mp_lv object, not base object. mp_lv object can be identified by its get_buffer member which is common to all mp_lv objects native object inheritance is enabled by implementing attr as call_parent_methods, at least until micropython/micropython#4360 is implemented started to fix advanced_demo.py for v.7: struct function members and missing styles update lvgl and example binding
That's now possible since #6253. Otherwise, I'll close this PR. It's really just a code size optimisation and things have moved on a lot since it was made (how types are defined) so it'd need to be redone anyway. |
This implements simple linear native inheritance (ie doesn't support multiple inherintance at the C level). It does this by just looping over the search through
locals_dict
, searching all parents of the type.The other two commits here use this to combine all common stream methods (read, readinto, readline, readlines, write, close) into a single C type which is a parent type for all other stream classes.
This allows for native inheritance (see issue #1159) and reduces code size for ports that have stream based objects.