260 lines
15 KiB
HTML
260 lines
15 KiB
HTML
<head>
|
||
<title>Evan Pratten</title>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||
|
||
<!-- Begin Jekyll SEO tag v2.6.1 -->
|
||
<title>Doing Python OOP the wrong way | Evan Pratten</title>
|
||
<meta name="generator" content="Jekyll v3.8.6" />
|
||
<meta property="og:title" content="Doing Python OOP the wrong way" />
|
||
<meta property="og:locale" content="en_US" />
|
||
<meta name="description" content="In the name of science!" />
|
||
<meta property="og:description" content="In the name of science!" />
|
||
<link rel="canonical" href="http://0.0.0.0:4000/blog/2019/09/07/wrong-python" />
|
||
<meta property="og:url" content="http://0.0.0.0:4000/blog/2019/09/07/wrong-python" />
|
||
<meta property="og:site_name" content="Evan Pratten" />
|
||
<meta property="og:type" content="article" />
|
||
<meta property="article:published_time" content="2019-09-07T09:13:00-04:00" />
|
||
<script type="application/ld+json">
|
||
{"datePublished":"2019-09-07T09:13:00-04:00","dateModified":"2019-09-07T09:13:00-04:00","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"http://0.0.0.0:4000/blog/2019/09/07/wrong-python"},"url":"http://0.0.0.0:4000/blog/2019/09/07/wrong-python","description":"In the name of science!","headline":"Doing Python OOP the wrong way","@context":"https://schema.org"}</script>
|
||
<!-- End Jekyll SEO tag -->
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||
<link rel="stylesheet" href="/assets/css/main.css">
|
||
<link rel="stylesheet" href="/assets/css/github-syntax.css">
|
||
<link href="https://fonts.googleapis.com/css?family=IBM+Plex+Mono:400,400i|IBM+Plex+Sans:100,100i,400,400i,700,700i" rel="stylesheet">
|
||
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<div class="site-ctr">
|
||
<!-- Navbar -->
|
||
<nav class="navbar navbar-dark sticky-top bg-dark navbar-expand-lg">
|
||
<!-- Navbar content -->
|
||
<!-- <div class="container"> -->
|
||
<a class="navbar-brand" href="/">Evan Pratten</a>
|
||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup"
|
||
aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
|
||
<div class="navbar-nav ml-auto">
|
||
<a class="nav-item nav-link" href="/blog">Blog</a>
|
||
<a class="nav-item nav-link" href="/projects">Projects</a>
|
||
<!-- <a class="nav-item nav-link" href="/documentation">Documentation</a> -->
|
||
<a class="nav-item nav-link" href="/about">About</a>
|
||
</div>
|
||
<!-- </div> -->
|
||
</div>
|
||
</nav>
|
||
<!-- <div style="height:5vh"></div> -->
|
||
|
||
<!-- Header -->
|
||
<!-- <div class="header">
|
||
<div class="container">
|
||
<div class="content">
|
||
</div>
|
||
</div>
|
||
<div class="header-gap"></div>
|
||
</div> -->
|
||
|
||
<div class="reactive-bg">
|
||
<div class="post container">
|
||
<h1>Doing Python OOP the wrong way
|
||
|
||
</h1>
|
||
<h4>In the name of science!
|
||
|
||
</h4>
|
||
<hr>
|
||
<p><em>2019-09-07 09:13:00 -0400
|
||
|
||
</em></p>
|
||
|
||
<br>
|
||
|
||
<p>If you know me, you probably know of the many weird things I do with python. Most recent of which being this <a href="https://en.wikipedia.org/wiki/Fizz_buzz">FizzBuzz</a> implementation in one line of python code:</p>
|
||
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_</span><span class="o">=</span><span class="p">[</span><span class="k">print</span><span class="p">(</span><span class="s">"FizzBuzz"</span><span class="p">[</span><span class="n">_</span><span class="o">*</span><span class="n">_</span><span class="o">%</span><span class="mi">3</span><span class="o">*</span><span class="mi">4</span><span class="p">:</span><span class="mi">8</span><span class="o">--</span><span class="n">_</span><span class="o">**</span><span class="mi">4</span><span class="o">%</span><span class="mi">5</span><span class="p">]</span> <span class="ow">or</span> <span class="n">_</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">101</span><span class="p">)]</span>
|
||
</code></pre></div></div>
|
||
|
||
<p>This installment of “weird things I do with python” will not focus on one-liners (that’s going on my todo list though). But instead, playing with Python’s classes and object system.</p>
|
||
|
||
<h2 id="a-quick-introduction-to-classes">A quick introduction to classes</h2>
|
||
<p>Im going to assume that you, the reader, have some reasonable knowledge of how computers work, and OOP concepts. If you do not, there are <a href="https://medium.com/swlh/5-free-object-oriented-programming-online-courses-for-programmers-156afd0a3a73">many great online resources</a> to help you out.</p>
|
||
|
||
<p>As a quick refresher, this is the Python syntax for a basic class:</p>
|
||
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span>
|
||
|
||
<span class="c1"># This is the constructor. __init__ is an overridable python built-in
|
||
</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg1</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
|
||
|
||
<span class="c1"># Here we set the class' scoped my_number to arg1
|
||
</span> <span class="bp">self</span><span class="o">.</span><span class="n">my_number</span> <span class="o">=</span> <span class="n">arg1</span>
|
||
|
||
<span class="k">def</span> <span class="nf">printMyNumber</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">my_number</span><span class="p">)</span>
|
||
</code></pre></div></div>
|
||
|
||
<p>This is really just a fancy setter and getter. Here is some example usage:</p>
|
||
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">my_object</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
|
||
<span class="n">my_object</span><span class="o">.</span><span class="n">printMyNumber</span><span class="p">()</span> <span class="c1"># Prints 10
|
||
</span></code></pre></div></div>
|
||
|
||
<h2 id="noticing-something-odd">Noticing something odd</h2>
|
||
<p>Before reading the following, keep in mind that (as of now) I have not actually looked at the Python interpreter’s source code enough to know about their memory system. The following is just an educated guess.</p>
|
||
|
||
<p>Looking at any python class, you may notice that <strong>at least</strong> 1 argument is required. <code class="highlighter-rouge">self</code> is used to access the class’ data from itself. This is not present in most other languages I know, which means there might be something interesting happening behind the scenes. Here is a re-implementation of <code class="highlighter-rouge">MyClass</code> from above in java:</p>
|
||
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyClass</span> <span class="o">{</span>
|
||
<span class="kt">int</span> <span class="n">my_int</span><span class="o">;</span>
|
||
|
||
<span class="kd">public</span> <span class="nf">MyClass</span><span class="o">(</span><span class="kt">int</span> <span class="n">arg1</span><span class="o">){</span>
|
||
<span class="n">my_int</span> <span class="o">=</span> <span class="n">arg1</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">printMyNumber</span><span class="o">(){</span>
|
||
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">my_int</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</code></pre></div></div>
|
||
|
||
<p>Notice the fact that there is no <code class="highlighter-rouge">self</code>? Yet Java methods can still access class data.</p>
|
||
|
||
<h2 id="implementing-objects-in-a-non-object-oriented-language">Implementing objects in a non-object oriented language</h2>
|
||
<p>In a non-OOP language (like C), objects can be faked by creating <a href="https://en.wikipedia.org/wiki/Struct_(C_programming_language)">structures</a> and some standard functions. These functions then take a pointer to their “parent” structure. Confusing? yes. But it works, and I see it used all over the place. Here a pseudocode example:</p>
|
||
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct MyClass {
|
||
int my_int; // Scpoed int
|
||
}
|
||
|
||
fn printMyNumber(MyClass* self){
|
||
print(self.my_int);
|
||
}
|
||
|
||
</code></pre></div></div>
|
||
|
||
<p><code class="highlighter-rouge">printMyNumber</code> takes a pointer to it’s “parent class”, called <code class="highlighter-rouge">self</code>. Look familiar? This is how Python works.</p>
|
||
|
||
<h2 id="lets-do-some-python">Let’s do some Python</h2>
|
||
<p>Alright.. Time for some “broken” Python. Here is yet another implementation of <code class="highlighter-rouge">MyClass</code>, except this time, each function is globally scoped:</p>
|
||
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
|
||
<span class="c1"># Private, globally scoped functions
|
||
</span><span class="k">def</span> <span class="nf">_init_myclass</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg1</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">my_number</span> <span class="o">=</span> <span class="n">arg1</span>
|
||
|
||
<span class="k">def</span> <span class="nf">_myclass_printMyNumber</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">my_number</span><span class="p">)</span>
|
||
|
||
|
||
<span class="c1"># struct-like class containing function pointers
|
||
</span><span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span>
|
||
|
||
<span class="n">__init__</span> <span class="o">=</span> <span class="n">_init_myclass</span>
|
||
<span class="n">printMyNumber</span> <span class="o">=</span> <span class="n">_myclass_printMyNumber</span>
|
||
|
||
</code></pre></div></div>
|
||
|
||
<p>This code will still function like a normal class. Unlike a regular class definition, the above code defines the constructor and <code class="highlighter-rouge">printMyNumber</code> methods in the global scope (marked as private with an underscore). A class is then created with function pointers to each of the global functions. This means that calling <code class="highlighter-rouge">MyClass.printMyNumber</code> will point to, and execute <code class="highlighter-rouge">_myclass_printMyNumber</code>. The interpreter still treats the underscore functions as members of <code class="highlighter-rouge">MyClass</code>, and passes the <code class="highlighter-rouge">self</code> argument along to them.</p>
|
||
|
||
<h2 id="why">Why?</h2>
|
||
<p>I have absolutely no idea why this would ever be useful. If you think you should start doing this in your code, <strong>don’t</strong>. It leads to very messy and confusing code, and is bad practice in just about every way.</p>
|
||
|
||
<p>The point of this post is to show yet another instance of the Python interpreter saying “<a href="https://www.urbandictionary.com/define.php?term=idgaf">idgaf</a>”, and letting us have a little fun.</p>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<!-- <div id="particles-js"></div> -->
|
||
|
||
<div class="container foot" style="text-align:center;">
|
||
<br>
|
||
<span class="site-info">
|
||
Site design by: <a href="https://retrylife.ca">Evan Pratten</a> |
|
||
|
||
This site was last updated at: 2019-11-30 11:30:39 -0500
|
||
</span>
|
||
</div>
|
||
|
||
<!-- Brython -->
|
||
<script src="/assets/js/brython.js"></script>
|
||
<script src="/assets/js/brython_stdlib.js"></script>
|
||
|
||
<script>
|
||
function startPY(){
|
||
|
||
brython();
|
||
console.log("Started Python")
|
||
}
|
||
|
||
window.onload = startPY;
|
||
</script>
|
||
|
||
|
||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
|
||
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
|
||
crossorigin="anonymous"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
|
||
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
|
||
crossorigin="anonymous"></script>
|
||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
|
||
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
||
crossorigin="anonymous"></script>
|
||
|
||
<!-- Offsets for links -->
|
||
<script>
|
||
(function ($, window) {
|
||
var adjustAnchor = function () {
|
||
|
||
var $anchor = $(':target'),
|
||
fixedElementHeight = 100;
|
||
|
||
if ($anchor.length > 0) {
|
||
|
||
window.scrollTo(0, $anchor.offset().top - fixedElementHeight);
|
||
}
|
||
|
||
};
|
||
|
||
$(window).on('hashchange load', function () {
|
||
adjustAnchor();
|
||
});
|
||
|
||
})(jQuery, window);
|
||
</script>
|
||
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-74118570-2"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() { dataLayer.push(arguments); }
|
||
gtag('js', new Date());
|
||
|
||
gtag('config', 'UA-74118570-2');
|
||
</script>
|
||
|
||
|
||
<!-- particles -->
|
||
<script>
|
||
var body = document.body
|
||
|
||
var particles = document.getElementById("particles-js")
|
||
|
||
particles.style.height = body.scrollHeight + "px"
|
||
|
||
console.log(body.scrollHeight)
|
||
</script>
|
||
<script src="/assets/js/particles.min.js"></script>
|
||
<script>
|
||
particlesJS.load('particles-js', '/assets/js/particles.json', function () {
|
||
console.log('callback - particles.js config loaded');
|
||
});
|
||
</script>
|
||
|
||
<!-- Twitter embeds -->
|
||
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||
|
||
|
||
</body> |