I’ve used Python (or more specifically IronPython) in the past to use Python as a scripting engine for my app. but never really bothered with Python beyond that. However, I decided I need to spend a little more time with Python, so am going to post a few “getting started” posts, starting with this one…
Note: This post any others on Python are aimed at developers coming from another language, such as C#, Java or C++. So I will not be going over every capability of the language but will aim to cover those main areas of syntax etc. to simply get things working in Python.
Python basics
Python files are usually saved with the .py extension and is interpreted, although there are apps for compiling the scripts to executables.
Python is a dynamic language, hence we do not need to declare the type of a variable.
Python uses whitespace and indentation to denote blocks of code, i.e. in C#, Java etc. we’d use curly braces { } to denote a block of code whereas Python expects the code blocks to be tabbed, for example in C# we might have
public int Pi() { return 3.14; }
the same function in Python would be
def pi(): return 3.14
This also demonstrates creating a function in Python (see Functions, below for more information on function definitions).
Also notice that Python does not use line termination like the semi-colon in C#. Java etc. This means if we need to extend our code onto another line we can use the backslash, i.e.
def pi(): return \ 3.14
Types
Python is a dynamically typed language which has good and bad points. This basically means when we declare a variable name it’s automatically created and it’s type is automatically declared based upon it’s usage. The type can change as we assign different types to the variable, for example
value = "Hello World" # value is of type str value = 123 # value is now of type int
Note: # is used for a single line comment, we can use “”” to start and end a block of code to use as multi-line comments, although technically speaking these denote multi-line strings.
Python types include the usual types, such as a string (str), int, long, float, boolean along with complex types, tuples and more.
If we need to find the type at runtime then we can use the type method, for example
value = (1, "Hello") print(type(value))
In this code, the first line creates a tuple and the next line outputs (to the console) the type of the value variable, in this case the output will be
<class 'tuple'>
Enumerations
Enumerations are declared via the Enum type, we need to import the enum module and then we can declare our Enum subclassed type as follows
import enum class Gender(enum.Enum): Male = 1, Female = 2 # in use g = Gender.Female
Functions
Python allows us to define function using the def keyword, here the example we introduced earlier
def pi(): return 3.14
def is used to declare or define our function, arguments may be passed within the parenthesis, in this instance no arguments exist. Finally we end the function declaration using the colon. The actual statements that are executed within the function are then below the declaration and the code is indented.
Executing functions uses pretty standard syntax, i.e.
value = pi()
Although Python does a good job of type inference when we have code like the following
def add(a, b): return a + b
we have a situation where both of the following bits of code work
strValue = add("2", "3") intValue = add(2, 3)
but in the first instance we get the string “23” and in the second we get the int 5.
Obviously if our intent of that the add function it for numerical types then we will need to give type hints, for example
def add(a: float, b: float) -> float: return a + b
The strange thing here (if you’re used to similar techniques in F#, for example) is that running the previous example of the add function with strings and ints will still work, i.e. still returns “23” and 5. So it’s debatable how useful hints are. Certainly PyCharm will display a “hint” over the string arguments and tell us the expected type, but ultimately we can still pass in a different types for the add function arguments.
If you want to include type hints but not show them in your source or if you want to hint on existing code that you do not (or cannot) edit. Then you can include a .pyi file along with the .py file including the type/function etc. and separate the hints from the actual implementation. So for example our .py file might have
def add(a, b): return a + b
and the file with the same name but .pyi extension would have
def add(a: float, b: float) -> float: ...
Object Orientated
Python allows us to define classes uses the class keyword, for example
import http.client class WebClient: def __init__(self): self.url = "www.google.co.uk" self.method = "GET" def submit(self): connection = http.client.HTTPConnection(self.url) connection.request(self.method, "/") response = connection.getresponse() data = response.read() print(response.status, response.reason) print(data) client = WebClient()
The __init__ function is the equivalent of a constructor and self is analogous to this in C#. Within the __init__ we have declared new variables along with some default values, i.e. the url and method variables.
In the case where we do not have anything to setup/initialize in the __init__ function we can use the pass keyword. Here’s an example of this along with how we can derived/subclass a type
class Animal: def __init__(self): pass class Dog(Animal): def __init__(self): self.legs = 4
A good old, OO example whereby Animal is the base class and Dog subclasses this and adds functionality/fields etc.
As you’ve probably already noticed, Python doesn’t include a new keyword to create an instance of a class we simply use
animal = Dog()
Importing modules & packages
Like most languages, we can create reusable source code modules (and packages) that can then be imported into our source code, for example let’s import a Python standard library for connecting to an HTTP endpoint
import http.client connection = http.client.HTTPConnection("www.google.co.uk") connection.request("GET", "/") response = connection.getresponse() data = response.read()
In the code above, we import the http.client library and then create an HTTPConnection instance which we then use to connect to google.co.uk.
We can import multiple modules using comma separated values, i.e.
import http.client, sys
Creating modules & packages
Modules are simply ways to define reusable code within separate files. Packages are is essence namespaces which can contain multiple packages and modules.
To create a module, we simply create a file, for example web.py and include our functions and types etc. within that file, so web.py looks like this
import http.client class WebClient: def __init__(self): self.url = "www.google.co.uk" self.method = "GET" def submit(self): connection = http.client.HTTPConnection(self.url) connection.request(self.method, "/") response = connection.getresponse() data = response.read() print(response.status, response.reason) print(data)
and it our file that uses this module, we have the following
import web client = web.WebClient() client.submit()
Packages now take this a little further. Still using the file based approach. Packages are simply directories with one or more module file, but every package must include a file named __init__.py which can be empty. This __init__.py file may contain an __all__ variable which defines what modules are exported, i.e. non-exported modules can be internal or private to the package or exported and visible to those using the package. For example our __init__.py file might look like this
__all__ = ['WebClient'] # example within multiple exports __all__ = ['WebClient', 'SomethingElse']
However the above only seems to be used when using the alternate import syntax, for example
from web import *
See the answers to Can someone explain __all__ in Python? for much more information on the use of __all__.