Style
naming
UpperCamelCase: Types and Extensions
lowerCamelCase: identifiers and constants
lowecase_underscore: libraries, packages, directories
_leadingUnderscore: private variable or method
filenames
lowercase_with_underscores.dart
indentation
indent 2 spaces
prefer spaces to tabs
use dartfmt to correctly format
naming
lowercase_underscore: functions, variables, modules
CamelCase: classes
UPPER_CASE: constants
lowercase: packages (no underscores)
filenames
lowercase_underscored.py
indentation
use 4 consecutive spaces
prefer spaces over tabs
note: python is whitespace sensitive
naming
UpperCamelCase: Types and Protocols
lowerCamelCase: everything else
filenames
MyType.swift
MyType+MyProtocol.swift
indentation
prefer spaces to tabs
use xcode ctrl-I to automatically indent
Basics: Variables, Types, and Operators
types
int, double, bool, String, dynamic, Object
List, Set, Map
if (emp is Person) { ... }
// following could throw
(myShape as Circle).radius = 5
variables
var myAge = 35;
final myBirthYear = 1985;
cont pi = 3.14;
int myAge = 35;
// strongly typed with type inferrence
// automatic type converstion
operators
assignment: a = b
arithmetic: +, -, *, /, %
compound assignment: +=, -=, *=, /=
comparison: ==, !=, >, <, >=, <=
logical: !, &&, ||
increment/decrement
print(++a) // increment, then print
print(a++) // print, then increment
comments
// single line commeng
/* multiline
comment */
/// doc comment
ranges
n/a
types
int, float, bool, str, byte
list, set, dict, tuple
type(my_int) # <class 'int'>
isinstance(my_int, int)
variables
myAge = 35
CONSTANT_BIRTH_YEAR = 1985
# dynamically typed
# no automatic type conversion
operators
assignment: a = b
arithmetic: +, -, *, /, %
compound assignment: +=, -=, *=, /=
comparison: ==, !=, >, <, >=, <=
logical: not, and, or
increment/decrement
n/a
comments
# inline comments
""" docstring """
ranges
range(6) # 0 to 5
range(1, 11, 2) # 1, 3, 5, 7, 9
array[:4] # indexes 0 to 3
array[4:] # indexes 4 to end
tuples
httpError = (404, "Not Found")
(code, errMsg) = httpError
code = httpError[0]
myTuple[2:5] # access via range of indexes
for x in myTuple
if "exists" in myTuple
len(myTuple)
# tuples are immutable
types
Int, Double, Bool, String, Data, Any, AnyObject
Array, Set, Dictionary, Tuples
if item is Int { ... }
if let mySquare = rectangle as? Square { ... }
variables
var mutableAge = 35
let constantBirthYear = 1985
var myAge: Int = 35
// strongly typed, and inferred
// no automatic type converstion
operators
assignment: a = b
arithmetic: +, -, *, /, %
compound assignment: +=, -=, *=, /=
comparison: ==, !=, >, <, >=, <=
logical: !, &&, ||
increment/decrement
n/a
comments
// single line commeng
/* multiline
comment */
/// doc comment
ranges
i in 1...5 // includes 1 and 5
i in 1..<5 // includes 1, not 5
array[..<4] // indexes 0 to 3
array[4...] // indexes 4 to end
tuples
let httpError = (404, "Not found")
let (code, errMsg) = httpError
let code = httpError.0
let (_, errMsg) = httpError
Nullability
value
define
// all objects can be null
String name;
safe access
let x = User?.name;
var msg = err ?? "No Errors";
var msg ??= err
forced access
n/a
value
None
define
x = None
safe access
if x is None:
# do not use == or !=
forced access
n/a
value
nil
define
// must be explicitly declared
"var optString: String?"
safe access
if let x = optString?.count { ... }
let x = optString?.count ?? 0
let x = optString?.count // x is optional
let x = optionalVar ?? otherVar
forced access
let x = optString!.count
let optString: String! = "Implicitly Unwrapped"
let x = optString // no need for ? or !
Strings
instantiation
final aString = 'A string constant';
var mutableString = 'Change';
concatination
mutableString += ' me';
mutableString = 'Change' ' me';
interpolation
print('The value of myInt is $myInt');
multiline
var multiLineString = """
Multiline strings can "quote"
parts of the content.
""";
raw
var raw = r'use $myVar to print objects';
grapheme clusters
import 'package:characters/characters.dart';
var laugh = 'laughing emoji: 😆';
var lastCharacter = $laugh.characters.last;
instantiation
A_STRING = "A string constant"
mutableString = "Change"
concatination
mutableString += " me"
interpolation
print("The value of my_int is {0}".format(my_int))
multiline
multilineString = '''
Multiline strings can "quote"
parts of the content.
'''
# can also use double quotes
raw
rawString = r'use /n to print a newline'
grapheme clusters
# strings are arrays, no character object
laugh = "laughing emoji: 😆"
lastCharacter = laugh[-1]
instantiation
let aString = "A string constant"
var mutableString = "Change"
concatination
mutableString += " me"
interpolation
print("The value of myInt is \(myInt)")
multiline
let multiLineString = """
Multiline strings can "quote"
parts of the content.
"""
raw
let raw = #"use \(myVar) to print objects"#
let rawInterpolation = #"myVar: \#(myVar)"#
grapheme clusters
var laugh = "laughing emoji: 😆"
if let lastCharacter = laugh.last { ... }"
Control Flow
conditionals
if x == 5 {
// x is 5
} else if x < 5 {
// x less than 5
} else {
// x greater than 5
}
ternary operator
x > 5 ? print("True") : print("False");
var xLessThanFive = x > 5 ? true : false;
loops
for (item in myArray) { ... }
myArray.forEach((item) => print(item));
for (var i = 1; i <= 10; i++) {
continue; // move to next iteration of loop
break; // end loop
}
while i < 10 { ... }
do { ... } while i < 10;
switch
var age = 35;
switch (age) {
case 40:
print("you are over the hill");
break;
case 18:
case 21:
print("you can now vote or drink");
break;
case 1...17:
case 2:
...
case 17:
print("you are a minor");
break;
case 0:
// case must have at least one statement
break;
default:
print("you are an adult");
}
conditionals
if x == 5:
# x is 5
elif x < 5:
# x less than 5
else:
# x > than 5
ternary operator
print("True") if x > 5 else print("False")
loops
for item in myList:
for i in range(1, 10):
continue # move to next interation of loop
break # end loops
pass # do nothing, but fills need for statement
while i < 10:
i += 1
else:
# do this once at end; optional
switch
n/a
conditionals
if x == 5 {
// x is 5
} else if x < 5 {
// x less than 5
} else {
// x greater than 5
}
ternary operator
x > 5 ? print("True") : print("False")
let xLessThanFive = x > 5 ? true : false
loops
for item in myArray { ... }
myArray.forEach { print($0) }
for i in 1...10 {
continue // move to next iteration of loop
break // end loop
}
while i < 10 { ... }
do { ... } while i < 10
switch
var age = 35
switch age {
case 40:
print("you are over the hill")
case 18, 21:
print("you can now vote or drink")
case 1...17:
print("you are a minor")
case 0:
// case must have at least one statement
break
default:
print("you are an adult")
}
// Note: switch statements end once a
// matching case is found
// use keyword 'fallthrough' for
// C-like behavior"
Collections
array create
var mutableList = ["One", "Two"];
var emptyList = List<int>();
array access
var index = mutableList.indexOf("Two");
if (index != -1) {
final a = mutableList[index];
}
array modify
mutableList.add("Three");
mutableList.insert(1, "Three");
mutableList += ["Three"]
mutableList[1] = "Three";
mutableList.removeAt(1);
final poppedItem = mutableArray.removeLast()
set create
var mutableSet = {1, 2, 3, 2}; / {1, 2, 3}
var emptySet = <int>{};
set modify
mutableSet.add(4);
bool wasFound = mutableSet.remove(3);
mutableSet.removeAll();
set utility
setA.union(setB);
setA.intersection(setB);
setA.difference(setB);
key-value create
var personMap = {"first": "Joe", "last": "Smith"};
var emptyMap = Map<String, String>();
key-value access
var name = personMap["first"];
key-value modify
personMap["middleInitial"] = "C";
personMap.remove("first");
key-value utility
bool wasFound = personMap.containsKey("last");
bool wasFound = personMap.containsValue("Smith");
all: properties
var numberOfElements = mutableList.length;
bool empty = myMap.isEmpty;
all: iteration
myList.forEach((item) { ... });
myMap.forEach((key, value) { ... });
var nums = [1, 2, 3];
var numStrings = nums.map((n) => n.toString());
numStrings.forEach(print);
more info
all: utility
var isTrue = myArray.contains("Cats");
var isTrue = myDict.isEmpty;
var isTrue = mySet.isNotEmpty;
// map
// numberStrings below is lazily evaluated on access
// to force full integration use map().toList()
var numbers = [1, 2, 3];
var numberStrings = numbers.map((num) => number.toString());
var cars = ['bmw', 'ford', 'tesla'];
bool isElectric(String car) => car == 'tesla';
// get all items that satisfy
var electricCars = cars.where(isElectric);
cars.any(isElectric); // check if any items satisfy
cars.every(isElectric); // check if all items satisfy
array create
mutable_list = ["One","Two"]
empty_list = []
new_list = mutable_list.copy()
new_list = list(mutable_list)
array access
if 1 < len(mutable_list):
a = mutable_list[1]
array modify
mutable_list.append("Three")
mutable_list.insert(1, "Three")
mutable_list += ["Three"]
mutable_list[1] = "Three"
mutable_list.remove("Two")
mutable_list.pop(1)
del mutable_list[1]
set create
mutable_set = {1, 2, 3, 2}
empty_set = set()
set modify
mutable_set.add(4)
mutable_set.remove(5) # will raise error if not in set
mutable_set.discard(5) # will NOT raise error if not in set
mutable_set.clear()
set utility
set_a.union(set_b)
set_a.intersection(set_b)
set_a.difference(set_b)
set_a.issubset(set_b)
set_a.issuperset(set_b)
set_a.isdisjoint(set_b)
key-value create
person_dict = {"first": "Joe", "last": "Smith"}
empty_dict = {}
new_dict = person_dict.copy()
new_dict = dict(person_dict)
key-value access
name = person_dict["first"]
if "middle_initial" in person_dict:
key-value modify
person_dict["middle_initial"] = "C"
person_dict.pop("middle_initial")
person_dict.clear()
key-value utility
# gets value, or sets with provided value
x = person_dict.setDefault["last", "Jones"]
all: properties
count = len(my_collection)
all: iteration
for item in my_list: # all collections
# List specific
for index, item in enumerate(person_dict):
# Dictionary specific
for key, value in person_dict:
all: utility
if "Cat" in my_pets
array create
var mutableArray = ["One", "Two"]
var emptyArray = [Int]() // empty array
var arrayOfPi = Array(repeating: 3.14, count 10)
var newArray = mutableArray // copy-on-write
array access
if let index = mutableArray.firstIndex(of: "Two") {
let a = mutableArray[index]
}
array modify
mutableArray.append("Three")
mutableArray.insert("Three", at: 1)
mutableArray += ["Three"]
mutableArray[1] = "Three"
mutableArray.remove(at: 1)
let poppedItem = mutableArray.removeLast()
set create
let immutableSet: Set = [1, 2, 3, 2] // [1, 2, 3]
var mutableSet: Set = ["One", "Two", "Three"]
var emptySet = Set<String>()
set modify
mutableSet.insert(4)
// returns item or nil
let optionalItem = mutableSet.remove(3)
mutableSet.removeAll()
set utility
setA.union(setB)
setA.intersection(setB)
setA.subtracting(setB)
setA.symmetricDifference(setB)
setA.isSubSet(of: setB)
setA.isSuperset(of: setB)
setA.isDisjoint(with: setB)
key-value create
var personDict = ["first": "Joe", "last": "Smith"]
var emptyDict = [String: String]()
key-value access
let name = personDict["first"]
key-value modify
personDict["middleInitial"] = "C"
let oldValue = personDict.updateValue("Blow", forKey: "last")
personDict["middleInitial"] = nil
let removedValue = personDict.removeValue(forKey: "first")
key-value utility
all: properties
let numberOfElements = mutableArray.count
if myDictionary.isEmpty { ... } // faster check than .count
all: iteration
for item in myArray { ... } // all collections
mySet.forEach { print($0) } // all collections
// Array specific
for (index, item) in myArray.enumerated() { ... }
// Dictionary specific
for (key, value) in myDictionary { ... }
for key in myDictionary.keys { ... }
for value in myDictionary.values { ... }
all: utility
let isTrue = myArray.contains("Cats")
let sortedSet = mySet.sorted() // Sets & Dicts have no order
// map, compactMap, flatMap
let numbers = [1, 2, 3]
let numberStrings = numbers.map {String($0)} // ["1", "2", "3"]
strings[1] = "Cars"
let optionalNumbers = strings.map { Int($0) } // [1, nil, 3]
let onlyNumbers = strings.compactMap { Int($0) } // [1, 3]
let optionalStrings: String? = ["1", nil, "3"]
let result = optionalStrings.map { Int($0) }
// result is type [Int??]
let result = optionalString.flatMap { Int($0) } // [Int?]
Functions
overview
// positional parameter
String sayHello(String name) { ... }
// optional positional parameters
String sayHello(String name, [String greeting]) { ... }

sayHello('Jane', 'Howdy');
// named parameters with default value
// Note - named params are always optional
String sayHello({bool exclaim, String name = 'World'}) { ... }
sayHello(exclaim: false);
// function as parameter
String printMath(int Function(int, int) math, int a, int b) {
return math(a, b);
}
// primitives (int, bool, double, etc) passed by value
// objects passed by reference
closures/lambdas
var add = (int a, int b) { return a + b; }
var add = (int a, int b) => a + b;
overview
# single parameter with default
def say_hello(name = "Joe"):
say_hello("Jane")
# call with named arguments
def say_hello(name, use_exclaim)
say_hello(use_exclaim = True, name = "Jane")
# return values
def say_hello(name):
return "Hello, " + name
greeting = say_hello("John")
overview
// single parameter with default and single return value
func sayHello(name: String = "World") -> String { ... }
print(sayHello(name: "Jane"))
// omit argument labels on call
func sayHello(_ name: String) { ... }
sayHello("Jane")
// multiple return values using tuple
func heightAndWeight(name: String) -> (Int, Int) { ... }
// inout (by reference) parameters
func swapInts(a: inout Int, b: inout Int) { ... }
swapInts(a: &intOne, b: &intTwo)
// zero or more parameters (omitting label)
for calculateSum(_ numbers: Int...) -> Int { ... }
calculateSum(1, 2, 3, 4, 5) // 15
// single statement functions can skip return keyword
func addTwoInts(_ a: Int, _ b: Int) -> Int { a + b }
// function as parameter
func printMath(math: (Int, Int) -> Int, a: Int, b: Int) {
print(math(a, b))
}
doMath(math: addTwoInts, a: 2, b: 3) // prints 5
closures/lambdas
let addClosure: (Int, Int) -> Int = { (a, b) in a + b }
let subtractClosure: (Int, Int) -> Int = { $0 - $1 }
more info
Enumerations
create
enum Color {
red, green, blue
}
var myColor = Color.green;
closures/lambdas
enum Dessert {
brownie, cookie, cake, port
}
var countOfDessertTypes = Dessert.values.length;
Dessert.values.forEach((type) { ... });
associated values
n/a
create
from enum import Enum # new in python 3.4
Art = Enum('Art', 'painting poster sculpture ascii')
new_purchase = Art.ascii
access
Art.poster # Art.poster
Art['painting'] # Art.painting
Art.poster.name # poster
Art.poster.value # 2
raw values
class State(Enum):
utah = "UT"
florida = "FL"
minnisota = "MN"
State.utah.value # UT
associated values
n/a
create
enum VisualArt {
case painting, poster, sculpture, ascii
}
let newPurchase = VisualArt.poster
access
enum Dessert: CaseIterable {
case brownie, cookie, cake, port
}
let countOfDessertTypes = Dessert.allCases.count
for type in Dessert.allCases { ... }
raw values
enum State: String {
case utah = "UT"
case florida = "FL"
case minnisota = "MN"
}
print("Abbreviation for Utah is \(State.utah.rawValue)")
associated values
enum Favorite {
case color(String)
case number(Int)
case none
}
let lucky = Favorite.number(7)
switch lucky {
case .none:
print("No favorites")
case .number(let value):
print("Lucky Number \(value)!")
case .color:
print("So pretty")
}
Structs
create
n/a
instantiate
n/a
create
# use named tuples; immutable
# updated in 3.6
from typing import NamedTuple
class StudentNT(NamedTuple):
name: str
class: int
school: str
# use Data Classes; mutable
# new in 3.7
from dataclasses import dataclass
@dataclass
class StudentDC:
name: str
class: int
school: str = "Middletown High School"
instantiate
joe = StudentNT("Joe", 2019, "Middletown High School")
joe = StudentDC("Joe", 2019)
create
struct Student {
var name: String
var class: Int
var school: String = "Middletown High School"
}
instantiate
let joe = Student(name: "Joe", class: 2019)
let graduationYear = joe.class
Classes
define
class Animal {
String name;
var sound = "Animal noises";
num numberOfFleas = 0; // num covers int and double
bool get needsBath { // computed property
return numberOfFleas > 0;
}
// default constructor
Animal() {
this.name = "Unknown Animal";
}
// named constructor
Animal.named(String name) {
this.name = name;
}
// Animal(this.name); // syntax sugar for above
makeSound() {
print(sound);
}
}
instantiate
var cat = Animal("Cat");
subclass
class Dog extends Animal {
bool isMuddy = true;
Dog([String name = "Dog"]) : super.named(name) {
this.sound = "Bark";
}
@override
bool get needsBath {
return numberOfFleas > 10 && isMuddy;
}
}
var dog = Dog();
define
class Animal:
def __init__(self, name, sound = "Animal noises",
number_of_fleas = 0):
self.name = name
self.sound = sound
self.number_of_fleas = number_of_fleas
# calculated property
@property
def needs_bath(self):
return self.number_of_fleas > 0
def make_sound(self):
print(self.sound)
instantiate
cat = Animal("Cat")
subclass
class Dog(Animal):
def __init__(self, name = "Dog"):
super().__init__(name, "Bark")
self.isMuddy = False
@property
def needs_bath(self):
return self.number_of_fleas > 10
dog = Dog()
dog.make_soound() # Bark
define
class Animal {
let name: String
var sound = "Animal noises"
var numberOfFleas = 0
var needsBath: Bool { // computed property
numberOfFleas > 0
}
init(name: String) {
self.name = name
}
convenience init() {
self.name = "Unknown animal"
}
func makeSound() {
print(sound)
}
}
instantiate
let cat = Animal(name: "Cat")
subclass
class Dog: Animal {
var isMuddy = false
override init(name: String = "Dog") {
super.init(name: name)
self.sound = "Bark"
}
override var needsBath: Bool {
numberOfFleas > 10 && isMuddy
}
}
let dog = Dog()
final class Flea: Animal { ... } // can not subclass
Protocols & Extensions
protocols
extensions
extension NumberParsing on String {
int parseInt() {
return int.parse(this);
}
}
int a = "7".parseInt()
protocols
from abc import ABC
class HealthCheckable(ABC):
def __init__(self, height, weight):
self.height = height
self.weight = weight
super().__init__()
@abstractmethod
def calculate_bmi(self):
pass
class Person(HealthCheckable):
# must implement calculate_bmi or can't be instantiated
def calculate_bmi:
return self.weight / self.height
extensions
n/a
protocols
protocol HealthCheckable {
var height: Int
var weight: Int
func calculateBMI() -> Double
}
struct Person: HealthCheckable { ... }
extensions
// can be used with class, structures, enums, or protocols
extension Int {
func squared() -> Int {
return self * self
}
}
let twoSquared = 2.squared()
Error Handling
define
class OutOfLlamasException implements Exception {
final String msg;
const OutOfLlamasException([this.msg]);
@override
String toString() => msg ?? 'Out of Llamas';
}
handle
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e; rethrowing');
rethrow; // pass on
} finally {
// always do this cleanup code
cleanLlamaStalls();
}
define
class ProgrammerError(Exception):
def __init__(self, msg = None):
if msg is None:
msg = "Programmer made an error"
super(ProgrammerError, self).__init__(msg)
class NeedsCaffineError(ProgrammerError):
def __init__(self):
super(NeedsCaffineError,
self).__init__(msg="Caffine needed")
handle
try:
new_code = write_code()
except NeedsCaffineError as e:
get_coffee()
define
enum ProgrammerError: Error {
case needsCaffine
case notEnoughSleep
case canNotReproduce
}
func writeCode() throws -> String { ... }
handle
let newFunction = try? writeCode()
let newCode: String?
do {
newCode = try writeCode()
// success
} catch ProgrammerError.needsCaffine {
// get coffee
} catch {
newCode = nil
}
Miscellaneous
access scope
var _private = 5; // private to library
class Animal {
...
_privateAnimalMethod() { ... }
}
more info
access scope
# convetion only, python has no access limitations
# name mangling is meant for namespaces
class WideOpen:
def __init__(self):
_private_variable = 5
__mangled_name = "harder to access"
access scope
public
internal // default, limited to defining module
fileprivate // limited to source file
private // limited to enclosing declaration
underscore
// used to ignore an unneeded value. ex:
let (_, errMsg) = httpError
Core Libraries (beyond the language)
date
var now = DateTime.now();
var nowString = now.toString();
var nowISO8610 = now.toIso8601String();
more info
json
import 'dart:convert';
var jsonString = '''
{ "username": "Joe", "id": 5, "lastLoginDate": "2019-04-23" }
''';
// decode into Dart object
var user = jsonDecode(jsonString);
assert(user is Map);
print(user['id']); // 5
// encode into JSON
var encodedJsonString = jsonEncode(user);
print(encodedJsonString);
more info
async/threading
// using async/await
Future checkVersion() async {
var version = await lookUpVersion();
// do something
}
// using Futures
HttpRequest.getString(url).then((String result) {
print(result);
}).catchError((e) {
// Handle or ignore the error.
});
more info
filesystem
data_file = open("data.cvs")
for line in data_line:
# process line
output_file = open("error.log", "w")
output_file.write("Programmer error again")
output_file.close()
network
import urllib.request
result = urllib.request.urlopen("").read()
# also see aiohttp library build on top of asyncio
more info
json
import json
json_str = '''
{ "username": "Joe", "id": 5, "lastLoginDate": "2019-04-23" }
'''
dict_from_json = json.loads(json_str)
encoded_json = json.dumps(dict_from_json)
more info
async/threading
import asyncio
async def main():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
# Python 3.7+
asyncio.run(main())
more info
date
let now = Date()
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
let nowString = formatter.string(from: now)
more info
json
struct AccountInfo: Codable {
let username: String
let id: Int
let lastLoginDate: String // ISO 8601 string
}
// decode from json into swift objects
let jsonString = """
{ "username": "Joe", "id": 5, "lastLoginDate": "2019-04-23" }
"""
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
let accountInfo = try? decoder.decode(AccountInfo.self, from:jsonData)
// encode from swift objects to json
let encoder = JSONEncoder()
if let accountInfoData = try? encoder.encode(accountInfo) {
if let encodedJsonString = String(data: accountInfoData, encoding: .utf8) {
print(encodedJsonString)
}
}
more info
async/threading
DispatchQueue.global(qos: .userInitiated).async {
if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url) {
self.parse(json: data)
return
}
}
}
more info