{"categories":["Principles of Programming Languages"],"contentHtml":"<p>Python is a powerful jack-of-all-trades language that is much less limited than OCaml.</p>\n<h2>Expressions</h2>\n<p>Arithmetic works in a very simple and clear way in Python, basically like a calculator.</p>\n<pre><code>2 # 2\n2 + 4 # 6\n(2 + 5) * (3 - 5) # -20\n</code></pre>\n<p>Unlike in OCaml, operations can be performed between floats and integers with no issues; Python will simply change the types behind the scenes. This is called <strong>type coercion</strong>.</p>\n<pre><code>2 + 3.5 # 5.5\n</code></pre>\n<p>This causes an interesting side effect: what is the return type of this function?</p>\n<pre><code>def add(a, b):\n    return a + b\n</code></pre>\n<p>In OCaml, the equivalent function would have type <code>int -&gt; int -&gt; int</code>, since the operation <code>+</code> is only valid for <code>int</code>. However, this function is actually polymorphic in Python! In OCaml, you would call it type <code>'a</code>. In Python, this type is called <strong>Any</strong>, and operation changes based on what the types are. The reason that this is possible is because <em>everything</em> in Python is an object. Essentially, the variables <code>a</code> and <code>b</code> are just boxes that could contain anything, and Python only checks whether the operation <code>+</code> is defined for the two variables at runtime.</p>\n<h2>Strings</h2>\n<p>String manipulation is a very common operation in Python, so there are some very useful ways to handle strings built into the language.</p>\n<pre><code>\"hello \" + \"world\" # \"hello world\"\n\"hello\" * 3 # \"hellohellohello\"\n</code></pre>\n<p>You can also convert types to strings very easily.</p>\n<pre><code>str(5) # \"5\"\nstr(3.5) # \"3.5\"\n</code></pre>\n<p>And vice versa.</p>\n<pre><code>int(\"5\") # 5\nfloat(\"3.5\") # 3.5\n</code></pre>\n<p>These are special built-in functions to make our lives earlier.</p>\n<h2>Variables</h2>\n<p>Like with OCaml, there is no need to specify types as in Java. Unlike OCaml, Python does not use type inference. Instead, every variable can contain any type in a box as mentioned earlier.</p>\n<pre><code>a = 3\nb = \"hello\"\n</code></pre>\n<p>Variables in Python work differently under the hood than other languages. A variable is essentially just a name for an element.</p>\n<pre><code>c = b\n</code></pre>\n<p><code>c</code> here is not just equal to <code>b</code>... it is actually <code>b</code> itself! And any change you make to <code>b</code> will reflect in <code>c</code> because of that. Actual copies must be explicit.</p>\n<h2>Slices</h2>\n<p><strong>Slices</strong> are one of the most powerful tools in Python. In fact, it might be what Python is most known for and most useful for. Slicing allows for powerful manipulation of list-like data.</p>\n<p>Ordinary list access uses bracket notation with a single number to access a single element. Slice notation works similarly, but it allows returning multiple elements as a sub-list of the original list.</p>\n<pre><code>x = \"hello world\"\nx[1:7] # \"ello w\"\n</code></pre>\n<p>You might notice that I just performed this operation on a string; didn't I just say that slices work on list-like types? In Python, strings are just fancy lists of chars!.</p>\n<h2>Tuples and Lists</h2>\n<p>A tuple is an immutable set of multiple elements, just like in OCaml. Slicing operations work the same way in that they return a subsequence tuple. There's a weird side effect where if you slice in a way that returns a single element, you can get a single-element tuple.</p>\n<p>Lists in Python are much more flexible in OCaml, as they can be heterogenous with any type within. They are also mutable, so elements of lists can be reassigned.</p>\n<p>Slicing can superpower this assignment by reassigning multiple values at once</p>\n<h2>Control</h2>\n<p>The traditional <code>if</code> statements are back, but with a bit of a twist. Python has <em>significant whitespace</em>, which means that the amount that you indent by affects the actual execution of the code. This is quite rare.</p>\n<pre><code>if x == 15:\n    y = 0 # this tab is mandatory!\nx = 3 # this line is outside the if block\n</code></pre>\n<p>There is a special keyword called <code>pass</code> which exists to allow empty blocks. Normally, this construct is forbidden:</p>\n<pre><code>if x == 15:\nx = 3 # error!\n</code></pre>\n<p>But by using <code>pass</code>, this is possible:</p>\n<pre><code>if x == 15:\n    pass # does nothing\nx = 3\n</code></pre>\n<p>Like in C, boolean evaluation is 0 for false, true for everything else. However, you <em>cannot</em> assign a variable in a conditional! So this C construct would not be allowed:</p>\n<pre><code>while ((int x = some_func()) == 0) {\n    // this is allowed in C\n}\n</code></pre>\n<pre><code>while (x = some_func()) == 0:\n    pass # this is not allowed in Python!\n</code></pre>\n<h2>Functions</h2>\n<p>Functions are defined using the <code>def</code> keyword.</p>\n<pre><code>def fac(n):\n    if n &lt; 0:\n        return \"negative!\"\n    elif n == 0:\n        return 1\n    else:\n        return n * fac(n - 1)\n</code></pre>\n<p>Functional programming can be used similarly to OCaml where everything is a function.</p>\n<pre><code>def compose(f, g):\n    def foo(x):\n        return f(g(x))\n    return foo\n</code></pre>\n<pre><code>let compose f g =\n    let foo x =\n        f g x\n    in foo x\n</code></pre>","contentMarkdown":"Python is a powerful jack-of-all-trades language that is much less limited than OCaml.\n\n## Expressions\n\nArithmetic works in a very simple and clear way in Python, basically like a calculator.\n\n```python\n2 # 2\n2 + 4 # 6\n(2 + 5) * (3 - 5) # -20\n```\n\nUnlike in OCaml, operations can be performed between floats and integers with no issues; Python will simply change the types behind the scenes. This is called **type coercion**.\n\n```python\n2 + 3.5 # 5.5\n```\n\nThis causes an interesting side effect: what is the return type of this function?\n\n```python\ndef add(a, b):\n    return a + b\n```\n\nIn OCaml, the equivalent function would have type `int -> int -> int`, since the operation `+` is only valid for `int`. However, this function is actually polymorphic in Python! In OCaml, you would call it type `'a`. In Python, this type is called **Any**, and operation changes based on what the types are. The reason that this is possible is because *everything* in Python is an object. Essentially, the variables `a` and `b` are just boxes that could contain anything, and Python only checks whether the operation `+` is defined for the two variables at runtime.\n\n## Strings\n\nString manipulation is a very common operation in Python, so there are some very useful ways to handle strings built into the language.\n\n```python\n\"hello \" + \"world\" # \"hello world\"\n\"hello\" * 3 # \"hellohellohello\"\n```\n\nYou can also convert types to strings very easily.\n\n```python\nstr(5) # \"5\"\nstr(3.5) # \"3.5\"\n```\n\nAnd vice versa.\n\n```python\nint(\"5\") # 5\nfloat(\"3.5\") # 3.5\n```\n\nThese are special built-in functions to make our lives earlier.\n\n## Variables\n\nLike with OCaml, there is no need to specify types as in Java. Unlike OCaml, Python does not use type inference. Instead, every variable can contain any type in a box as mentioned earlier.\n\n```python\na = 3\nb = \"hello\"\n```\n\nVariables in Python work differently under the hood than other languages. A variable is essentially just a name for an element.\n\n```python\nc = b\n```\n\n`c` here is not just equal to `b`... it is actually `b` itself! And any change you make to `b` will reflect in `c` because of that. Actual copies must be explicit.\n\n## Slices\n\n**Slices** are one of the most powerful tools in Python. In fact, it might be what Python is most known for and most useful for. Slicing allows for powerful manipulation of list-like data.\n\nOrdinary list access uses bracket notation with a single number to access a single element. Slice notation works similarly, but it allows returning multiple elements as a sub-list of the original list.\n\n```python\nx = \"hello world\"\nx[1:7] # \"ello w\"\n```\n\nYou might notice that I just performed this operation on a string; didn't I just say that slices work on list-like types? In Python, strings are just fancy lists of chars!.\n\n## Tuples and Lists\n\nA tuple is an immutable set of multiple elements, just like in OCaml. Slicing operations work the same way in that they return a subsequence tuple. There's a weird side effect where if you slice in a way that returns a single element, you can get a single-element tuple.\n\nLists in Python are much more flexible in OCaml, as they can be heterogenous with any type within. They are also mutable, so elements of lists can be reassigned.\n\nSlicing can superpower this assignment by reassigning multiple values at once\n\n## Control\n\nThe traditional `if` statements are back, but with a bit of a twist. Python has *significant whitespace*, which means that the amount that you indent by affects the actual execution of the code. This is quite rare.\n\n```python\nif x == 15:\n    y = 0 # this tab is mandatory!\nx = 3 # this line is outside the if block\n```\n\nThere is a special keyword called `pass` which exists to allow empty blocks. Normally, this construct is forbidden:\n\n```python\nif x == 15:\nx = 3 # error!\n```\n\nBut by using `pass`, this is possible:\n\n```python\nif x == 15:\n    pass # does nothing\nx = 3\n```\n\nLike in C, boolean evaluation is 0 for false, true for everything else. However, you *cannot* assign a variable in a conditional! So this C construct would not be allowed:\n\n```c\nwhile ((int x = some_func()) == 0) {\n    // this is allowed in C\n}\n```\n\n```python\nwhile (x = some_func()) == 0:\n    pass # this is not allowed in Python!\n```\n\n## Functions\n\nFunctions are defined using the `def` keyword.\n\n```python\ndef fac(n):\n    if n < 0:\n        return \"negative!\"\n    elif n == 0:\n        return 1\n    else:\n        return n * fac(n - 1)\n```\n\nFunctional programming can be used similarly to OCaml where everything is a function.\n\n```python\ndef compose(f, g):\n    def foo(x):\n        return f(g(x))\n    return foo\n```\n\n```ocaml\nlet compose f g =\n    let foo x =\n        f g x\n    in foo x\n```","dataUrl":"https://sharifhsn.dev/api/posts/python-crash-course.json","date":"2022-04-14","datePublished":"2022-04-14","description":"Python is a powerful jack-of-all-trades language that is much less limited than OCaml.","site":"https://sharifhsn.dev","slug":"python-crash-course","source":"Archive","sourceUrl":null,"tags":["Principles of Programming Languages"],"title":"A Crash Course in Python","url":"https://sharifhsn.dev/blog/python-crash-course/","version":"1","wordCount":833}