├── README.rst ├── docs ├── Makefile ├── _static │ └── fonts │ │ ├── Lato-BoldItalic.ttf │ │ └── Lato-Italic.ttf ├── about.rst ├── classes │ └── index.rst ├── conditionals │ └── index.rst ├── conf.py ├── functions │ ├── hello_world_typing.py │ └── index.rst ├── hello_world │ ├── REPL.png │ ├── REPL_open.png │ ├── REPL_state.png │ ├── hello_world_basic.py │ ├── hello_world_main.py │ ├── hello_world_minimum.py │ └── index.rst ├── index.rst ├── make.bat ├── packages │ └── index.rst ├── sequences │ └── index.rst ├── setup │ └── index.rst └── variables │ └── index.rst ├── kotlin_for_python.iml ├── requirements.txt ├── run_livereload.py └── src └── hello_world ├── hello_world.kt └── hello_world2.kt /README.rst: -------------------------------------------------------------------------------- 1 | Kotlin for Python 2 | ================= 3 | 4 | Documentation and tutorials for explaining Kotlin to Python developers. 5 | 6 | .. note:: 7 | 8 | This is not an official JetBrains project, just an experiment I was 9 | doing as a personal side project. 10 | 11 | - IntelliJ project 12 | 13 | - Docs in Sphinx 14 | 15 | - Live reload server during authoring via 16 | 17 | Installation 18 | ============ 19 | 20 | These docs are done in Sphinx, the Python documentation system. Content 21 | is under docs. 22 | 23 | 1) Make a virtual env, e.g. in ``.venv`` 24 | 25 | 2) ``.venv/bin/pip3 install -r requirements.txt`` 26 | 27 | Running 28 | ======= 29 | 30 | 1) ``.venv/bin/python ./run_livereload.py`` (or make a run config) 31 | 32 | 2) Edit docs 33 | 34 | 3) URL reloads 35 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = KotlinforPythonDevelopers 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/_static/fonts/Lato-BoldItalic.ttf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | fonts/Lato-BoldItalic.ttf at master · google/fonts · GitHub 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
102 | Skip to content 103 |
104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 181 | 182 | 183 |
184 | 185 |
186 | 187 |
188 |
189 | 190 | 191 | 192 |
193 |
194 |
195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
204 |
205 | 206 | 250 | 251 |

252 | 253 | /fonts 256 | 257 |

258 | 259 |
260 | 261 | 299 | 300 | 301 |
302 | 303 |
304 |
305 | 306 | 307 | Permalink 308 | 309 | 310 | 311 |
312 | 313 |
314 | 320 | 321 |
322 | 323 |
324 |
325 | 326 | Switch branches/tags 327 |
328 | 329 |
330 |
331 | 332 |
333 |
334 | 342 |
343 |
344 | 345 | 424 | 425 |
426 |
427 | 428 | 429 |
430 | 431 |
Nothing to show
432 |
433 | 434 |
435 |
436 |
437 | 438 |
439 | 443 | Find file 444 | 445 | 446 |
447 | 450 |
451 | 452 | 453 | 454 |
455 | Fetching contributors… 456 |
457 | 458 |
459 | 460 | Cannot retrieve contributors at this time 461 |
462 |
463 | 464 |
465 |
466 |
467 | 468 |
469 | Download 470 | History 471 |
472 | 473 | 474 |
475 | 479 |
480 | 481 |
482 | 682 KB 483 |
484 |
485 | 486 | 487 | 488 |
489 |
490 | View Raw 491 |
492 |
493 | 494 |
495 | 496 | 497 | 502 | 503 |
504 | 505 |
506 | 507 |
508 |
509 | 510 |
511 | 512 | 513 | 538 | 539 | 540 | 541 |
542 | 543 | 546 | You can't perform that action at this time. 547 |
548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 |
559 | 560 | You signed in with another tab or window. Reload to refresh your session. 561 | You signed out in another tab or window. Reload to refresh your session. 562 |
563 | 572 | 573 | 574 | 575 | 576 | 577 | -------------------------------------------------------------------------------- /docs/_static/fonts/Lato-Italic.ttf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | fonts/Lato-Italic.ttf at master · google/fonts · GitHub 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
102 | Skip to content 103 |
104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 181 | 182 | 183 |
184 | 185 |
186 | 187 |
188 |
189 | 190 | 191 | 192 |
193 |
194 |
195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
204 |
205 | 206 | 250 | 251 |

252 | 253 | /fonts 256 | 257 |

258 | 259 |
260 | 261 | 299 | 300 | 301 |
302 | 303 |
304 |
305 | 306 | 307 | Permalink 308 | 309 | 310 | 311 |
312 | 313 |
314 | 320 | 321 |
322 | 323 |
324 |
325 | 326 | Switch branches/tags 327 |
328 | 329 |
330 |
331 | 332 |
333 |
334 | 342 |
343 |
344 | 345 | 424 | 425 |
426 |
427 | 428 | 429 |
430 | 431 |
Nothing to show
432 |
433 | 434 |
435 |
436 |
437 | 438 |
439 | 443 | Find file 444 | 445 | 446 |
447 | 450 |
451 | 452 | 453 | 454 |
455 | Fetching contributors… 456 |
457 | 458 |
459 | 460 | Cannot retrieve contributors at this time 461 |
462 |
463 | 464 |
465 |
466 |
467 | 468 |
469 | Download 470 | History 471 |
472 | 473 | 474 |
475 | 479 |
480 | 481 |
482 | 706 KB 483 |
484 |
485 | 486 | 487 | 488 |
489 |
490 | View Raw 491 |
492 |
493 | 494 |
495 | 496 | 497 | 502 | 503 |
504 | 505 |
506 | 507 |
508 |
509 | 510 |
511 | 512 | 513 | 538 | 539 | 540 | 541 |
542 | 543 | 546 | You can't perform that action at this time. 547 |
548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 |
559 | 560 | You signed in with another tab or window. Reload to refresh your session. 561 | You signed out in another tab or window. Reload to refresh your session. 562 |
563 | 572 | 573 | 574 | 575 | 576 | 577 | -------------------------------------------------------------------------------- /docs/about.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | About This Guide 3 | ================ 4 | 5 | In no time at all, Kotlin has become an important language to learn, 6 | with videos and tutorials and examples and...everything you could 7 | want. 8 | 9 | Unless you're a Python dev. Kotlin is "better Java", but most 10 | resources presume you know Java and its ecosystem. It sure would be 11 | nice if this shiny new toy was explained in Python terms. 12 | 13 | That's what we're doing in this guide. Assuming you know nothing about 14 | Java, Gradle, etc., we're going to get you productive in Kotlin and 15 | IntelliJ. If you're not a Python developer, you will likely still 16 | find this guide useful. 17 | 18 | Why You'll Like This Guide 19 | ========================== 20 | 21 | - Explained in terms of Python 22 | 23 | - Presumes no Java knowledge 24 | 25 | - Hand-holding and hands-on 26 | 27 | - Text, code, and video 28 | 29 | - Co-written by Hadi Hariri, a leading spokesperson for Kotlin 30 | 31 | Contributing 32 | ============ 33 | 34 | We want this guide to be community-oriented and collaborative. Did we 35 | do something stupid? File a ticket or even send us a pull request. 36 | -------------------------------------------------------------------------------- /docs/classes/index.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Classes 3 | ======= 4 | 5 | 6 | 1) Defining a class with a method but no constructor, P has “self” 7 | 8 | 2) Creating instance of class does NOT require new in either 9 | 10 | 3) Class variables access in P via self or class name 11 | 12 | 4) P can assign instance attributes whenever it wants (within __ limitations), change types whenever, no concept of public/private 13 | 14 | 5) Constructors 15 | 16 | 6) Binding of constructor arguments to instance attributes (assignment, usage) 17 | 18 | ? - What happens if I don’t do var in the constructor? It’s unresolved later, but where does it go? 19 | 20 | 21 | In fact, Kotlin has a rich, multi-layered approach to 22 | construction. Our class attribute ``greeting`` is marked as immutable 23 | (and *should* be marked with the optional ``private``) as well. 24 | 25 | In some ways, Python is clunkier in this example. We have the magic of 26 | "dunder" names on important methods, such as the "constructor". The symbol 27 | of ``self`` is sprinkled in to give the instance scope a placeholder. And 28 | quite obviously, Kotlin's primary constructor -- right after the class 29 | name -- is terse and doesn't require assigning each value to "self". 30 | 31 | .. note:: 32 | 33 | Python's ``__init__`` is called a constructor, but as its name implies, 34 | it is actually an initializer. The ``__new__`` method is the factory. 35 | 36 | 8) Kotlin does some magic behind-the-scenes creation of Java classes 37 | named from the file name, because Java needs classes 38 | 39 | -------------------------------------------------------------------------------- /docs/conditionals/index.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Conditionals 3 | ============ 4 | 5 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Kotlin for Python Developers documentation build configuration file, created by 5 | # sphinx-quickstart on Fri Aug 25 09:57:46 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | # import os 21 | # import sys 22 | # sys.path.insert(0, os.path.abspath('.')) 23 | 24 | import sphinx_rtd_theme 25 | 26 | 27 | # -- General configuration ------------------------------------------------ 28 | 29 | # If your documentation needs a minimal Sphinx version, state it here. 30 | # 31 | # needs_sphinx = '1.0' 32 | 33 | # Add any Sphinx extension module names here, as strings. They can be 34 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 35 | # ones. 36 | extensions = ['sphinx.ext.intersphinx'] 37 | 38 | # Add any paths that contain templates here, relative to this directory. 39 | templates_path = ['_templates'] 40 | 41 | # The suffix(es) of source filenames. 42 | # You can specify multiple suffix as a list of string: 43 | # 44 | # source_suffix = ['.rst', '.md'] 45 | source_suffix = '.rst' 46 | 47 | # The master toctree document. 48 | master_doc = 'index' 49 | 50 | # General information about the project. 51 | project = 'Kotlin for Python Developers' 52 | copyright = '2017, Paul Everitt ' 53 | author = 'Paul Everitt ' 54 | 55 | # The version info for the project you're documenting, acts as replacement for 56 | # |version| and |release|, also used in various other places throughout the 57 | # built documents. 58 | # 59 | # The short X.Y version. 60 | version = '1.0.0' 61 | # The full version, including alpha/beta/rc tags. 62 | release = '1.0.0' 63 | 64 | # The language for content autogenerated by Sphinx. Refer to documentation 65 | # for a list of supported languages. 66 | # 67 | # This is also used if you do content translation via gettext catalogs. 68 | # Usually you set "language" from the command line for these cases. 69 | language = None 70 | 71 | # List of patterns, relative to source directory, that match files and 72 | # directories to ignore when looking for source files. 73 | # This patterns also effect to html_static_path and html_extra_path 74 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 75 | 76 | # The name of the Pygments (syntax highlighting) style to use. 77 | pygments_style = 'sphinx' 78 | 79 | # If true, `todo` and `todoList` produce output, else they produce nothing. 80 | todo_include_todos = False 81 | 82 | 83 | # -- Options for HTML output ---------------------------------------------- 84 | 85 | # The theme to use for HTML and HTML Help pages. See the documentation for 86 | # a list of builtin themes. 87 | # 88 | #html_theme = 'alabaster' 89 | 90 | html_theme = "sphinx_rtd_theme" 91 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 92 | 93 | # Theme options are theme-specific and customize the look and feel of a theme 94 | # further. For a list of options available for each theme, see the 95 | # documentation. 96 | # 97 | # html_theme_options = {} 98 | 99 | # Add any paths that contain custom static files (such as style sheets) here, 100 | # relative to this directory. They are copied after the builtin static files, 101 | # so a file named "default.css" will overwrite the builtin "default.css". 102 | html_static_path = ['_static'] 103 | 104 | # Custom sidebar templates, must be a dictionary that maps document names 105 | # to template names. 106 | # 107 | # This is required for the alabaster theme 108 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 109 | html_sidebars = { 110 | '**': [ 111 | 'about.html', 112 | 'navigation.html', 113 | 'relations.html', # needs 'show_related': True theme option to display 114 | 'searchbox.html', 115 | 'donate.html', 116 | ] 117 | } 118 | 119 | 120 | # -- Options for HTMLHelp output ------------------------------------------ 121 | 122 | # Output file base name for HTML help builder. 123 | htmlhelp_basename = 'KotlinforPythonDevelopersdoc' 124 | 125 | 126 | # -- Options for LaTeX output --------------------------------------------- 127 | 128 | latex_elements = { 129 | # The paper size ('letterpaper' or 'a4paper'). 130 | # 131 | # 'papersize': 'letterpaper', 132 | 133 | # The font size ('10pt', '11pt' or '12pt'). 134 | # 135 | # 'pointsize': '10pt', 136 | 137 | # Additional stuff for the LaTeX preamble. 138 | # 139 | # 'preamble': '', 140 | 141 | # Latex figure (float) alignment 142 | # 143 | # 'figure_align': 'htbp', 144 | } 145 | 146 | # Grouping the document tree into LaTeX files. List of tuples 147 | # (source start file, target name, title, 148 | # author, documentclass [howto, manual, or own class]). 149 | latex_documents = [ 150 | (master_doc, 'KotlinforPythonDevelopers.tex', 'Kotlin for Python Developers Documentation', 151 | 'Paul Everitt \\textless{}paul.everitt@jetbrains.com\\textgreater{}', 'manual'), 152 | ] 153 | 154 | 155 | # -- Options for manual page output --------------------------------------- 156 | 157 | # One entry per manual page. List of tuples 158 | # (source start file, name, description, authors, manual section). 159 | man_pages = [ 160 | (master_doc, 'kotlinforpythondevelopers', 'Kotlin for Python Developers Documentation', 161 | [author], 1) 162 | ] 163 | 164 | 165 | # -- Options for Texinfo output ------------------------------------------- 166 | 167 | # Grouping the document tree into Texinfo files. List of tuples 168 | # (source start file, target name, title, author, 169 | # dir menu entry, description, category) 170 | texinfo_documents = [ 171 | (master_doc, 'KotlinforPythonDevelopers', 'Kotlin for Python Developers Documentation', 172 | author, 'KotlinforPythonDevelopers', 'One line description of project.', 173 | 'Miscellaneous'), 174 | ] 175 | 176 | 177 | 178 | 179 | # Example configuration for intersphinx: refer to the Python standard library. 180 | #intersphinx_mapping = {'https://docs.python.org/': None} 181 | -------------------------------------------------------------------------------- /docs/functions/hello_world_typing.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from typing import List 3 | 4 | 5 | def main(args: List[str]): 6 | print("Hello World") 7 | 8 | 9 | if __name__ == '__main__': 10 | main(sys.argv) 11 | -------------------------------------------------------------------------------- /docs/functions/index.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Functions 3 | ========= 4 | 5 | 6 | Looking at the Kotlin code itself: 7 | 8 | - This special ``main`` function has a contract...it's going to be 9 | passed an argument 10 | 11 | - We see the first hint of typing. It's mandatory in Kotlin...sort of. 12 | In this case we have an array of strings. With Python 3.6 variable 13 | annotations for optional type hinting, this would be: 14 | 15 | .. literalinclude:: hello_world_typing.py 16 | :linenos: 17 | 18 | - Whereas Python terminates the function line with a colon and uses 19 | indentation for the block, Kotlin uses the standard curly braces 20 | syntax 21 | 22 | Python's weird ``if __name__`` block is ugly, and reveals a certain 23 | something about packaging being added after-the-fact, but shows 24 | that Python is ready to just let you do damn fool stupid stuff at 25 | module scope. For instance, run your program. Kotlin has a bit of a 26 | formal contract to meet when executing an "entry point". 27 | 28 | .. note:: 29 | 30 | Don't like typing the boilerplate? PyCharm has a Live 31 | Template ``main`` for generating the run block at the 32 | bottom. So does Kotlin. We'll show this in the video 33 | for this segment. 34 | 35 | Kotlin has another syntactic convenience: you aren't required to 36 | say that the function returns nothing. 37 | 38 | Function expressions 39 | 40 | 41 | If using Python 3.5+ type hinting, that would be: 42 | 43 | .. code-block:: python 44 | :linenos: 45 | 46 | def sum(a: int, b:int) -> int: 47 | return a + b 48 | 49 | 50 | Not too shabby. This will be a recurring point: we'll compare Kotlin not 51 | just with "normal" Python, but also against type-hinted-Python. 52 | 53 | - Function argument typing and return value typing 54 | -------------------------------------------------------------------------------- /docs/hello_world/REPL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauleveritt/kotlin_for_python/0c7e830a07025ef1b30ca508f6edbb28ca24a450/docs/hello_world/REPL.png -------------------------------------------------------------------------------- /docs/hello_world/REPL_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauleveritt/kotlin_for_python/0c7e830a07025ef1b30ca508f6edbb28ca24a450/docs/hello_world/REPL_open.png -------------------------------------------------------------------------------- /docs/hello_world/REPL_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauleveritt/kotlin_for_python/0c7e830a07025ef1b30ca508f6edbb28ca24a450/docs/hello_world/REPL_state.png -------------------------------------------------------------------------------- /docs/hello_world/hello_world_basic.py: -------------------------------------------------------------------------------- 1 | # Python 2 | def main(): 3 | print("Hello World") 4 | 5 | 6 | main() 7 | -------------------------------------------------------------------------------- /docs/hello_world/hello_world_main.py: -------------------------------------------------------------------------------- 1 | # Python 2 | def main(): 3 | print("Hello World") 4 | 5 | 6 | if __name__ == '__main__': 7 | main() 8 | -------------------------------------------------------------------------------- /docs/hello_world/hello_world_minimum.py: -------------------------------------------------------------------------------- 1 | # Python 2 | print("Hello World") 3 | -------------------------------------------------------------------------------- /docs/hello_world/index.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Hello World 3 | =========== 4 | 5 | Java is installed, our IDE has a project open, we're ready to write some 6 | code. In this step we breeze through a light treatment of many Kotlin 7 | concepts, all from the Python perspective. 8 | 9 | The REPL 10 | ======== 11 | 12 | Python has an interactive interpreter, aka REPL, which makes it easy to 13 | play around and learn. It's a dynamic language, so this makes sense. As 14 | it turns out, Kotlin (in IntelliJ) has a REPL also. 15 | 16 | Opening the Kotlin REPL is easy. You can use the ``Tools | Kotlin`` menu 17 | or search for the action: 18 | 19 | .. image:: REPL_open.png 20 | 21 | In Python we have the ``Python Console`` tool window, which opens the 22 | Python interpreter in the context of your project. The Kotlin REPL is 23 | the same idea. 24 | 25 | Let's type in some code: 26 | 27 | .. image:: REPL.png 28 | 29 | Here we typed a line of Kotlin code and executed it with ``Cmd-Enter`` (macOS.) 30 | We could have clicked the green play button, which triggers the run action 31 | just like ``Cmd-Enter``. Kotlin evaluated our line, letting Kotlin/Java do 32 | a mountain of machinery behind the scenes. 33 | 34 | The REPL can handle multiple lines: 35 | 36 | .. image:: REPL_state.png 37 | 38 | As this is our first foray into Kotlin, let's analyze this small bit of 39 | code from the Python perspective: 40 | 41 | .. code-block:: kotlin 42 | :linenos: 43 | 44 | val msg = "Hello Kotlin" 45 | print(msg) 46 | 47 | - We declare variables with ``var`` (which allows re-assignment) or 48 | ``val`` (which is like a constant). Python doesn't have ``var``. 49 | 50 | - Double quotes for strings 51 | 52 | - No semicolons! 53 | 54 | - A print *function* (like Python 3, but unlike Python 2) 55 | 56 | All in all...other than ``var``, it's exactly like Python. 57 | 58 | Click the red X to close the REPL and let's start writing some Kotlin code. 59 | 60 | .. raw:: html 61 | 62 | 65 | 66 | 67 | First File 68 | ========== 69 | 70 | In Python, we'd make a ``.py`` file and start typing in some code. From 71 | Python's semantics, there are almost no rules about the file itself -- name, 72 | location, etc. For example, here is a minimum ``hello_world.py``: 73 | 74 | .. literalinclude:: hello_world_minimum.py 75 | :linenos: 76 | 77 | We can start the same in Kotlin. IntelliJ has created a ``src`` directory 78 | for you. Right-click on that and create a file at 79 | ``src/hello_world/hello_world.kt``: 80 | 81 | .. literalinclude:: ../../src/hello_world/hello_world.kt 82 | :language: kotlin 83 | :linenos: 84 | 85 | Here's the equivalent Python file to mimic a main function: 86 | 87 | .. literalinclude:: hello_world_basic.py 88 | :linenos: 89 | 90 | Python uses ``def`` to define a function, Kotlin uses ``fun``. We'll talk 91 | more about this in :doc:`../functions/index`. 92 | 93 | The Kotlin file shows the standard Kotlin "entry point": by convention, 94 | the file being executed must have a function named ``main`` which accepts 95 | a single argument, an array of strings. Kotlin itself then calls this 96 | main function. This is a *bit* similar to the common (but not required) 97 | Python run block. For example, this file in Python might look like this: 98 | 99 | .. literalinclude:: hello_world_main.py 100 | :linenos: 101 | 102 | In this Python example, we had to both detect that the module was 103 | being run (instead of imported) and then call the appropriate "main" 104 | function. 105 | 106 | We saw strong typing in the Kotlin function definition. Python of course 107 | has typing, but it is at run time and is inferred. (We'll discuss 108 | type hinting in the section on :doc:`../variables/index`.) 109 | 110 | Time to run this, which really means, compile and execute. If you're 111 | familiar with PyCharm run configurations and gutter icons, it's 112 | similar. Click the Kotlin symbol in the gutter for line 1 and select 113 | ``Run``: 114 | 115 | [TODO screenshot of running it] 116 | 117 | .. note:: 118 | 119 | IntelliJ prompted us to ``Run 'Hello_worldKT'``. What's 120 | ``Hello_worldKT``? Answer: To make Java happy, Kotlin generated 121 | a Java class behind the scenes. 122 | 123 | When you clicked this, there was a lag that you don't get in Python. 124 | This the build/compile phases from Java. It's incremental, so it 125 | is faster after the first time. 126 | 127 | Now that we've run our program, let's breeze through some 128 | head-to-head comparisons on a few programming language basics. 129 | 130 | Braces 131 | ====== 132 | 133 | This is the most obvious point: like most other programming languages, 134 | Kotlin delimits blocks with braces. Python uses indentation. 135 | 136 | Quotation Marks 137 | =============== 138 | 139 | Switching between languages, or even projects, means swinging back 140 | and forth between single versus double quotes for strings. For example, 141 | TypeScript prefers double quotes, but ReactJS ES6 applications prefer 142 | single quotes. And they are both (sort of) JavaScript! 143 | 144 | Python's ``PEP 8`` style guide doesn't prefer one or the other, but 145 | most Python projects seem to use single quotes. In fact, Python has 146 | triple quoted strings! 147 | 148 | .. code-block:: python 149 | :linenos: 150 | 151 | # Python 152 | hello = 'world' # best 153 | hello = "world" # ok 154 | hello = """ 155 | world""" # triple 156 | 157 | Java (and Kotlin) use a single quote for a single character value and 158 | double quotes for strings. Triple-quotes indicates a 159 | `raw string `_: 160 | 161 | .. code-block:: kotlin 162 | :linenos: 163 | 164 | // Kotlin 165 | val c = 'C' // character 166 | val hello = "hello" // string 167 | val raw_string = """ 168 | line 1 169 | line 2 170 | """ 171 | 172 | Comments 173 | ======== 174 | 175 | Kotlin supports the two familiar styles of comments: end-of-line and 176 | block comments: 177 | 178 | .. code-block:: kotlin 179 | :linenos: 180 | 181 | val hello = "world" // Kotlin line comment 182 | /* 183 | Let's leave out 184 | these lines 185 | */ 186 | 187 | IntelliJ (and thus PyCharm) as an IDE makes it easy to comment and uncomment 188 | lines and selections with ``Cmd-/``. 189 | 190 | Python, of course, only uses hash ``#`` as the comment symbol, 191 | with no block comments: 192 | 193 | .. code-block:: python 194 | :linenos: 195 | 196 | # 197 | # Python multiline commments 198 | # have a lot of hashes. 199 | 200 | hello = 'world' # Python comment 201 | 202 | Variables 203 | ========= 204 | 205 | Python doesn't have any special syntax for declaring a variable. You 206 | just assign something: 207 | 208 | .. code-block:: python 209 | :linenos: 210 | 211 | # Python 212 | hello = 'world' 213 | 214 | Kotlin, though, does. In fact Kotlin has two keywords: one to declare 215 | a read-only *immutable* value, and one for a *mutable* variable: 216 | 217 | .. code-block:: kotlin 218 | :linenos: 219 | 220 | // Kotlin 221 | val hello = "world" // Read-only, val == value 222 | var hello = "world" // Can be re-assigned, var == variable 223 | 224 | Where's the Java-style type noise? Good news -- Kotlin can infer the type. 225 | The above is the same as being explicit: 226 | 227 | .. code-block:: kotlin 228 | :linenos: 229 | 230 | // Kotlin 231 | val hello: String = "hello" 232 | 233 | Also, like Python, you can initialize a variable without 234 | assigning it: 235 | 236 | .. code-block:: kotlin 237 | :linenos: 238 | 239 | // Kotlin 240 | var hello 241 | 242 | Of course with Python 3.6 variable annotations, we can make Python look 243 | much more like Kotlin. We cover this in the section on :doc:`../variables/index`. 244 | 245 | String Templates 246 | ================ 247 | 248 | Python -- the "there should be one way to do things" language -- 249 | actually has *several* ways to do string templates: 250 | 251 | .. code-block:: python 252 | :linenos: 253 | 254 | # Python 255 | msg = 'World' 256 | print('Hello %s' % msg) # Original 257 | print('Hello {msg}'.format(msg=msg)) # Python 3 (then 2) 258 | print(f'Hello {msg}') # Python 3.6 259 | print(f'Hello {msg.upper()}') # Expressions 260 | 261 | Kotlin also has string templates with expressions: 262 | 263 | .. code-block:: kotlin 264 | :linenos: 265 | 266 | // Kotlin 267 | msg = "World" 268 | print("Hello $msg") 269 | print("Hello ${msg.toUpperCase()}") 270 | 271 | Functions 272 | ========= 273 | 274 | Python functions can be very simple: 275 | 276 | .. code-block:: python 277 | :linenos: 278 | 279 | # Python 280 | def four(): 281 | return 2 + 2 282 | 283 | No curly braces, just indentation. Kotlin's simplest case is pretty close: 284 | 285 | .. code-block:: kotlin 286 | :linenos: 287 | 288 | // Kotlin 289 | fun four(): Int { 290 | return 2 + 2 291 | } 292 | 293 | Kotlin adds the curly braces and has to define the return type (which can 294 | be omitted if there is no return value.) 295 | 296 | But watch this -- a function *expression*: 297 | 298 | .. code-block:: kotlin 299 | :linenos: 300 | 301 | // Kotlin 302 | fun four() = 2 + 2 303 | 304 | Admit it, that's pretty sexy. Function expressions are a big new idea 305 | which we'll cover in the section on :doc:`../functions/index`. 306 | 307 | Passing in function arguments is straightforward in Python: 308 | 309 | .. code-block:: python 310 | :linenos: 311 | 312 | # Python 313 | def combine(x, y): 314 | return x + y 315 | 316 | How does that compare to Kotlin? 317 | 318 | .. code-block:: kotlin 319 | :linenos: 320 | 321 | // Kotlin 322 | fun sum(a: Int, b: Int): Int { 323 | return a + b 324 | } 325 | 326 | You have to provide the type information on the function arguments and 327 | return value. 328 | 329 | Conditionals 330 | ============ 331 | 332 | Let's take a quick look at things like conditionals and looping. In 333 | Python, an ``if/then/else`` is straightforward, with use of indentation: 334 | 335 | .. code-block:: python 336 | :linenos: 337 | 338 | # Python 339 | if a > b: 340 | return a 341 | else: 342 | return b 343 | 344 | Kotlin looks quite similar, adding parenthesis (optional in Python) and 345 | braces: 346 | 347 | .. code-block:: kotlin 348 | :linenos: 349 | 350 | // Kotlin 351 | if (a > b) { 352 | return a 353 | } else { 354 | return b 355 | } 356 | 357 | We'll cover more on this in :doc:`../conditionals/index`. 358 | 359 | Looping 360 | ======= 361 | 362 | Let's compare looping over sequences. Simple Python example: 363 | 364 | .. code-block:: python 365 | :linenos: 366 | 367 | # Python 368 | items = ('apple', 'banana', 'kiwi') 369 | for item in items: 370 | print(item) 371 | 372 | Here we've created an immutable sequence (a tuple) in ``items``. We looped 373 | over it in the most basic way possible. 374 | 375 | In Kotlin, we have a different construct for making the sequence. Looping 376 | is similar, though we use a parentheses after ``for``: 377 | 378 | .. code-block:: kotlin 379 | :linenos: 380 | 381 | // Kotlin 382 | val items = listOf("apple", "banana", "kiwi") 383 | for (item in items) { 384 | println(item) 385 | } 386 | 387 | In this case we used ``println``. In Python, the ``print`` function always 388 | makes a newline unless you ask it not to. 389 | 390 | Both Python and Kotlin have rich and interesting control structures, 391 | giving both power and terseness. We'll see more in :doc:`../sequences/index`. 392 | 393 | Classes 394 | ======= 395 | 396 | Lots to cover later on this, so for now, let's just view the simplest couple 397 | of cases. The minimum in Python: 398 | 399 | .. code-block:: python 400 | :linenos: 401 | 402 | # Python 403 | class Message: 404 | pass 405 | 406 | In Kotlin: 407 | 408 | .. code-block:: kotlin 409 | :linenos: 410 | 411 | // Kotlin 412 | class Message 413 | 414 | It's hard to tell which of those have the smaller conceptual density. And 415 | who cares -- they're both tiny! Let's add a constructor, some variables, 416 | and methods. First in Python: 417 | 418 | .. code-block:: python 419 | :linenos: 420 | 421 | # Python 422 | class Message: 423 | greeting = 'Hello' 424 | 425 | def __init__(self, person): 426 | self.person = person 427 | 428 | def say_hello(self): 429 | return f'{self.greeting} {self.person}' 430 | 431 | This class has a "constructor" with one argument, which is assigned as an 432 | instance attribute. The class attribute of ``greeting`` is used in a 433 | method ``say_hello`` which returns an evaluated f-string. 434 | 435 | How about the type hinting flavor for Python 3.5+? 436 | 437 | .. code-block:: python 438 | :linenos: 439 | 440 | # Python 441 | class Message: 442 | greeting = 'Hello' 443 | 444 | def __init__(self, person: str): 445 | self.person = person 446 | 447 | def say_hello(self) -> str: 448 | return f'{self.greeting} {self.person}' 449 | 450 | 451 | Let's see this in Kotlin: 452 | 453 | .. code-block:: kotlin 454 | :linenos: 455 | 456 | // Kotlin 457 | class Message(val person: String) { 458 | val greeting = "Hello" 459 | 460 | fun sayHello(): String { 461 | return "$greeting $person" 462 | } 463 | } 464 | 465 | That constructor syntax, right in the middle of the class name line, is 466 | unusual and cool. It helps to reduce the typing versus Python's constructor. 467 | We'll go into more depth on this in the section on :doc:`../classes/index`. -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Kotlin for Python Developers 2 | ============================ 3 | 4 | Kotlin: it's new, it's hot, it's exciting! If you're a Python developer, 5 | you might be interested in Kotlin for Android development. If you're 6 | a PyCharm user, you might want to write an IDE plugin, using Kotlin. 7 | 8 | In both cases, you're looking to add Kotlin to your programming arsenal. 9 | This documentation teaches Kotlin -- from the perspective of a Python 10 | developer who knows nothing about Kotlin, Java, Gradle, or the JVM. 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | 15 | about 16 | setup/index 17 | hello_world/index 18 | variables/index 19 | conditionals/index 20 | sequences/index 21 | functions/index 22 | classes/index 23 | packages/index 24 | 25 | 26 | Indices and tables 27 | ================== 28 | 29 | * :ref:`genindex` 30 | * :ref:`modindex` 31 | * :ref:`search` 32 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=KotlinforPythonDevelopers 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/packages/index.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Packages and Imports 3 | ==================== 4 | 5 | Java Packages, imports, namespaces 6 | 7 | Installing Python packages 8 | 9 | 1) Creating a package, then creating a class in that package 10 | 11 | 2) Package namespaces 12 | 13 | 3) Importing from a package/non-package 14 | 15 | ? - What are the magic places that com.hello might find class World? In src, src/main/kotlin ? 16 | 17 | 4) Installing packages 18 | 19 | 5) Sharing packages 20 | 21 | 6) Making “executables" 22 | -------------------------------------------------------------------------------- /docs/sequences/index.rst: -------------------------------------------------------------------------------- 1 | ===================== 2 | Sequences and Looping 3 | ===================== 4 | 5 | 1) 1..5 vs. range(5) (and “a”..”z”) 6 | 7 | 2) 2 in range(5) (the in operator) 8 | 9 | 3) if else vs. if then 10 | 11 | 4) if “expressions” (Python doesn’t have this) var maxValue:Int = if (a > b) a else b but multiple lines (only the last value is used in the block) 12 | 13 | 5) when (aka switch)…Python doesn’t have this:: 14 | 15 | when (x) { 16 | !in 1..20 -> println(“x is 1”) 17 | 21,22 -> println(“x is 22 or 23”) 18 | else -> { 19 | // Some set of lines in a block 20 | println(“x is greater than 22”) 21 | } 22 | } 23 | 24 | 6) etc. 25 | 26 | generators, iterators 27 | -------------------------------------------------------------------------------- /docs/setup/index.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Setup 3 | ===== 4 | 5 | Before jumping into features of the language, let's get ourselves setup. 6 | Both 7 | `Kotlin `_ 8 | and 9 | `Python `_ 10 | have sites that let you enter and evaluate code in 11 | a browser. For our purposes, let's compare getting a real, local setup for 12 | each language. 13 | 14 | The Language 15 | ============ 16 | 17 | Getting Python and Java installed are similar exercise, but with different 18 | obstacles. For Python, while two of the major platforms ship a Python, 19 | everybody on earth will beat you over the head if you use "the system 20 | Python". For Java, it is not installed by default on most platforms. 21 | 22 | Thus, both Python and Java mean an initial, joyful step into the "How do I 23 | install it?" thicket. 24 | 25 | This is covered in depth elsewhere, so we'll skip it. From a Pythonista's 26 | perspective, it's pretty similar. You have to make some choices about which 27 | Java distribution, but we have some dirty laundry here as well -- 2 vs. 3, 28 | python.org vs. platform-y Homebrew etc. vs. Anaconda, PyPy vs. Jython vs. 29 | weird experiment of the week. 30 | 31 | Call this one a tie. 32 | 33 | The IDE 34 | ======= 35 | 36 | We're JetBrains: we're going to use the IDE as the entry point for 37 | making a project. For both Python and Kotlin, you might make your new 38 | project environment from the command line and then open it. 39 | 40 | Let's use the IDE make our project, following along with the very-useful 41 | `Getting Started with IntelliJ IDEA `_ 42 | documentation. 43 | 44 | The Project 45 | =========== 46 | 47 | In PyCharm, you fire it up and have 3 choices: create a new project from 48 | scratch, open a directory on disk, or get a clone from a VCS system. In the 49 | first, you can choose from some project templates, but you then have the 50 | important part regarding this article: 51 | 52 | [screenshot of create new project] 53 | 54 | In Python, we're encouraged to put each project in isolation using 55 | *virtual environments*. Yet because it is optional, people forget to, and 56 | create a world of hurt for themselves. Or they decide to do it, and are 57 | confronted with choices and complexity which hurt their brain. PyCharm 58 | helps make some of that pain go away: 59 | 60 | [screenshot of new interpeter screen] 61 | 62 | With two decisions -- project type and project interpreter -- you now have a 63 | new project and environment. PyCharm made some decisions for you, the level 64 | of magic is one degree away. 65 | 66 | When creating a Kotlin project, you'll confront some technologies that you 67 | are unfamiliar with. These are important decisions. Let's walk through 68 | them. 69 | 70 | *Go through step by step: SDK, facets, Gradle, class paths -- all from a 71 | Python perspective* 72 | 73 | Virtual environments and 74 | :doc:`package management <../packages/index>` 75 | are places where Python is behind. At the same time, the complexity is 76 | limited. Java (and for that matter, NodeJS) have stronger stories, but you 77 | can't take a step in without feeling pretty dumb about the huge concepts 78 | that you don't know. 79 | 80 | I wanted to be impartial and call this one against Python. I can't. It's a 81 | draw. 82 | 83 | Project Layout 84 | ============== 85 | 86 | In Python, that's about it. You could, at this point, just make a ``.py`` 87 | file and nobody would complain. Maybe a ``.gitignore``. 88 | 89 | You could, of course, be a grown-up and make a Python *package*. You'd then 90 | be teleported into a world of confusion: ``setup.py`` vs. 91 | ``requirements.txt`` (vs. ``Pipfile`` vs. ``buildout.cfg``), ``MANIFEST.in``, 92 | ``setup.cfg``, do I put my sources under ``project_name`` or 93 | ``src/project_name``. But those are university politics, not state-ordered 94 | mandates. 95 | 96 | Talk about: src/main/kotlin/someFile.kt and whether that path matters, 97 | vs. com.pauleveritt.projectname and how that affects choices. 98 | -------------------------------------------------------------------------------- /docs/variables/index.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | Variables and Types 3 | =================== 4 | 5 | JavaScript ES6 and TypeScript do (``let`` and ``const``.) 6 | 7 | 8 | As we'll see 9 | later, Kotlin lets you skip the syntax by inferring type information, 10 | but it is still at compile time. 11 | 12 | Kotlin will let you know to use a val when you use a var unnecessarily 13 | 14 | - Inferred types versus explicit 15 | 16 | - The compiler will fail on re-assignment of val 17 | 18 | - Scope: top-level versus local 19 | 20 | Class variables: properties and fields covered in classes 21 | 22 | - Types on variables 23 | 24 | - Basic types https://kotlinlang.org/docs/reference/basic-types.html#basic-types 25 | -------------------------------------------------------------------------------- /kotlin_for_python.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 25 | 26 | 28 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | livereload 3 | git+git://github.com/rtfd/sphinx_rtd_theme/@master -------------------------------------------------------------------------------- /run_livereload.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Automatically re-build Sphinx docs while editing, serve docs on an 4 | HTTP port, and also reload any browsers pointed to the docs. 5 | 6 | """ 7 | 8 | import glob 9 | 10 | from livereload import Server, shell 11 | from livereload.watcher import Watcher 12 | 13 | sphinx = ".venv/bin/python3 .venv/bin/sphinx-build -E -b html docs docs/_build" 14 | 15 | 16 | class CustomWatcher(Watcher): 17 | """ Handle recursive globs with Python 3.5+ globbing """ 18 | 19 | def is_glob_changed(self, path, ignore=None): 20 | for f in glob.glob(path, recursive=True): 21 | if self.is_file_changed(f, ignore): 22 | return True 23 | return False 24 | 25 | 26 | server = Server(watcher=CustomWatcher()) 27 | server.watch('docs/**', shell(sphinx), 28 | ignore=lambda s: '_build' in s) 29 | server.watch('src/kaybee/**.py', shell(sphinx)) 30 | server.serve(root='docs/_build', live_css=False) 31 | -------------------------------------------------------------------------------- /src/hello_world/hello_world.kt: -------------------------------------------------------------------------------- 1 | fun main(args: Array) { 2 | print("Hello World") 3 | } 4 | -------------------------------------------------------------------------------- /src/hello_world/hello_world2.kt: -------------------------------------------------------------------------------- 1 | class Message(val person: String) { 2 | val greeting = "Hello" 3 | 4 | fun sayHello(): String { 5 | return "$greeting $person" 6 | } 7 | } 8 | 9 | fun main(args: Array) { 10 | val m = Message("Mary") 11 | println(m.sayHello()) 12 | } --------------------------------------------------------------------------------