{"id":5132,"date":"2023-08-21T02:05:13","date_gmt":"2023-08-21T10:05:13","guid":{"rendered":"https:\/\/wonghoi.humgar.com\/blog\/?p=5132"},"modified":"2025-12-01T02:53:11","modified_gmt":"2025-12-01T10:53:11","slug":"useful-python-tricks","status":"publish","type":"post","link":"https:\/\/wonghoi.humgar.com\/blog\/2023\/08\/21\/useful-python-tricks\/","title":{"rendered":"Useful Python (party?) tricks"},"content":{"rendered":"\n<p>This article is not for Pythonisms (like ContextManager), etc, the way things should normally be done in Python, but the more non-obvious way to solve problems or new features that are available specifically in Python.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use \/ and * argument as separator for different forms of parameter entries!<\/h2>\n\n\n\n<p>There is <a href=\"https:\/\/docs.python.org\/3\/tutorial\/controlflow.html#special-parameters\">special syntax<\/a> to separate positional-only, positional\/keyword, and keyword-only parameters. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"329\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-6-1024x329.png\" alt=\"\" class=\"wp-image-5140\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-6-1024x329.png 1024w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-6-300x96.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-6-768x247.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-6-500x160.png 500w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-6.png 1430w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Make a variant of existing class\/object<\/h2>\n\n\n\n<p>This ninja technique is useful when you want to keep the object mostly the way it is but add\/override a few things you think it didn&#8217;t do right without inheriting or use composition (hide a copy of object as a member) and write a proxy mirror for every member of it. <\/p>\n\n\n\n<p>In C++, this situation is often used when you want to <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2017\/11\/18\/c-annoyances-and-reliefs-operator-in-stl-map-based-containers\/\">modify a concrete class<\/a> that doesn&#8217;t have a virtual destructor, most notoriously STL which you are not supposed to inherit from (or else the client might pass a pointer to the parent\/base so the child object&#8217;s destructors are not called as there are no vtables to keep track of which method to dispatch). In C++, this is often the few use cases that calls for private inheritance. <\/p>\n\n\n\n<p>In Python, because everything is a recursive dict that specially named (magic) functions are recognized, there is a <strong><code>__getattr__<\/code> method that gets called whenever a member is accessed<\/strong>, which is the case when the member is called (in Python you simply get the functor as an attribute, aka value in the key-value pairs, in the dictionary and add brackets to call it). This means <strong>you can re-route what attributes (members) are returned simply by overloading  <code>__getattr__<\/code><\/strong>!<\/p>\n\n\n\n<p>If you can overload __getattr__, it also mean you can redefine the member interface of your entire class! So a strategy to make a class have the same exact interface as another class is to hide a copy\/reference to the underlying class and re-route the __getattr__ to the underlying object&#8217;s __getattr__! Here&#8217;s the gist of it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class M:\n    def __init__(self, underlying_class):\n          self.__obj = underlying_class  \n    def __getattr__(self, attr):\n        return getattr(self.__obj, attr)<\/pre>\n\n\n\n<p>This can be improved a little bit. Just pick a member name that won&#8217;t clash with the underlying object&#8217;s attributes\/members and simply return the &#8216;hidden&#8217; object when specifically requested, not <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">self.__obj.__obj<\/code>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class M:\n    def __init__(self, underlying_class):\n          self.__obj = underlying_class  \n    def __getattr__(self, attr):\n        # Prevent self-calling        \n        if attr != '__obj':\n            return getattr(self.__obj, attr)\n        else:\n            return self.__obj<\/pre>\n\n\n\n<p>MATLAB&#8217;s classes are hard-wired to your class definition .m file, not something you can update on the fly as you please. Any attempts to do so (aka breaking the safeguards) are Undocumented MATLAB territory where you mess with the Java under the hood and change the metadata property to fool the objects to do what you want.<\/p>\n<div class=\"pvc_clear\"><\/div><p id=\"pvc_stats_5132\" class=\"pvc_stats all  \" data-element-id=\"5132\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p><div class=\"pvc_clear\"><\/div>","protected":false},"excerpt":{"rendered":"<p>This article is not for Pythonisms (like ContextManager), etc, the way things should normally be done in Python, but the more non-obvious way to solve problems or new features that are available specifically in Python. Use \/ and * argument &hellip; <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2023\/08\/21\/useful-python-tricks\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_5132\" class=\"pvc_stats all  \" data-element-id=\"5132\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[25,10,29,34],"tags":[],"class_list":["post-5132","post","type-post","status-publish","format-standard","hentry","category-cpp","category-matlab","category-programming","category-python"],"_links":{"self":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/5132","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/comments?post=5132"}],"version-history":[{"count":5,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/5132\/revisions"}],"predecessor-version":[{"id":6757,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/5132\/revisions\/6757"}],"wp:attachment":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/media?parent=5132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/categories?post=5132"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/tags?post=5132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}