Learn HTML and CSS for Beginners

In this tutorial, you'll learn the basics of HTML and CSS through a simple project. Learn how to apply CSS to an HTML Page. Using classes and ID's to help target with the CSS.

This is to introduce you to how the pages work with HTML and CSS. You will be able to customize your very own pages based on what you learn in this course. You will not become an HTML and CSS expert by any means however you will get some exposure to see whether or not you actually like to design and make those ideas come alive.

So you'll actually be coding along with two different projects. The first project is more or less an about me page where you will be able to add an image of yourself and some information about yourself just to play around with the HTML and CSS. The next project that you will actually create is a soundboard. We provide you with the JavaScript file as well as the sound bits that will play when you click on buttons for example. Going through this project you will see how you can style items and make it your own.

What you’ll learn

  •        What HTML is
  •        How to apply CSS to an HTML Page
  •        Using classes and ID's to help target with the CSS
  •        Be able to share projects they complete in this course

Are there any course requirements or prerequisites?

  •        No programming experience needed.

Who this course is for:

  •        Very beginners to see if coding is for them

#html #css #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

Learn HTML and CSS for Beginners
Web  Dev

Web Dev

1669435680

Full Stack Ecommerce App with React, Strapi and Stripe

In this Shopping App tutorial, you'll learn how to build and deploy a full-stack E-commerce App with React, Strapi and Stripe. Full-stack React e-commerce app tutorial for beginners.


00:00 Introduction
05:36 Installation  
07:12 React Router Dom v6.4 Tutorial
14:05 React Navbar Design
25:46 React Footer Design
32:11 React Slider Tutorial (without any library)
44:00 Featured Products and Product Card Design
55:21 Grid System Using CSS Flexbox
01:09:13 React Product List Page Design
01:21:07 React Single Product Page Design
01:34:00 React Shopping Cart Design
01:43:15 Strapi Tutorial for Beginners
01:56:20 React Strapi E-commerce App (Connection)
02:07:56 React Strapi E-commerce App (Fetching Items)
02:17:35 React Strapi Rest Api Filtering Tutorial
02:28:35 React E-commerce Fetch a Single Product
02:31:26  React Redux Shopping Cart Tutorial
02:27:40 React Redux Toolkit How to Persist State
02:50:05 Strapi Stripe Payment Using a React App
03:11:40 How to Deploy React app to a Shared Hosting?
03:13:22 How to Deploy Strapi app to a VPS Server?
03:30:15 Outro

Source Code:

https://github.com/safak/youtube2022/tree/e-commerce  ( Coming soon (updating files) )

Deployment source:

https://github.com/safak/youtube/tree/mern-deployment

#react #strapi #stripe #programming #developer #morioh #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

Full Stack Ecommerce App with React, Strapi and Stripe
Poppy Cooke

Poppy Cooke

1669262077

Faster Websites with Web Components

Faster content websites via SSR and progressive hydration of Web Components. We will focus on transmitting less JavaScript. We start with almost zero JavaScript and only load more as the users interacts with the page.

One of the best performance tips is "do less" - transmit less data and do less processing. There are a million details but we will focus on transmitting less JavaScript. We are going to tackle it by doing more work at build time which means we start with almost zero JavaScript and only load more as the users interacts with the page.

Drawing: https://api.react-finland.fi/media/drawings/2022/thomas.png 
Slides: https://docs.google.com/presentation/d/13hshxaN9pVRwIDZBWxH_V8_h7SA40h2k_3M70eCMSHY/edit?usp=sharing 

#webcomponents #javascript #programming #developer #morioh #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

Faster Websites with Web Components
Dylan  Iqbal

Dylan Iqbal

1669190950

Machine Learning for Beginners - Full Course

Learn from basics to advanced Machine Learning concepts. You'll learn: Python for Machine Learning • Role of Statistics in Machine Learning • Introduction to Machine Learning and its types • How does a Machine learning model learn? • Supervised and Unsupervised learning algorithms • Principal component analysis for dimensionality reduction • Application of Machine Learning, and more

Hello and welcome to the Machine Learning Full Course for Beginners using python. In this video, you will learn from basics to advanced machine learning concepts from Great Learning’s top faculties, including professor Mukesh Rao, Bharani Akella & many other leading industry experts. If you are an enthusiast who wants to start with machine learning from scratch, this machine learning beginner video is the best to start with.
 

Agenda:
• Python for Machine Learning
• Role of Statistics in Machine Learning
• Introduction to Machine Learning and its types
• How does a Machine learning model learn?
• Supervised and Unsupervised learning algorithms
• Principal component analysis for dimensionality reduction
• Application of Machine Learning

Topics Covered:
00:01:09 – What Is Machine learning? (Introduction to Machine Learning)
00:03:00 – Why Machine Learning?
00:04:22 – Road Map to Machine Learning 
00:01:09 – How to Use Kaggle (www.kaggle.com)
Machine Learning with Python (Python Libraries for Machine Learning)
00:11:25 - NumPy Python Tutorial (How to Create NumPy Array)
00:14:58 - How to Initialize NumPy Array
00:22:19 - How to check the shape of NumPy arrays
00:24:42 - How to Join NumPy Arrays
00:28:15 - NumPy Intersection & Difference
00:31:50 - NumPy Array Mathematics
00:39:15 - NumPy Matrix
00:42:28 - How to Transpose NumPy Matrix
00:43:21 - NumPy Matrix Multiplication
00:45:45 - NumPy Save & Load
00:47:44 - Python Pandas Tutorial
00:48:09 - Pandas Series Object
00:58:44 - Pandas Dataframe
01:12:00 - Matplotlib Python Tutorial
01:12:12 - Line plot
01:26:32 - Bar plot
01:32:37 - Scatter Plot
01:40:35 - Histogram
01:46:16 - Box Plot 
01:51:03 - Violin Plot  
01:51:57 - Pie Chart
01:56:39 - DoughNut Chart
01:59:04 - SeaBorn Line Plot
02:07:27 - SeaBorn Bar Plot
02:15:15 - SeaBorn ScatterPlot
02:20:25 - SeaBorn Histogram/Distplot
02:26:52 - SeaBorn JointPlot
02:30:23 - SeaBorn BoxPlot
02:38:59 – Role of Mathematics in Data Science
02:40:23 – What is data?
02:42:34 – What is Information?
02:43:21 – What is Statistics?
02:43:58 – What is Population?
02:46:48 – What is Sample?
02:47:33 – What are Parameters?
02:47:55 – Measures of Central Tendency
02:51:10 – Understanding Empirical Rule
02:53:16 – What is Mean, median, and mode?
02:57:04 – Measures of Spread (Understanding Range, Inter Quartile Range & Box-plot)
03:12:56 – Types of Machine Learning (Supervised, Unsupervised & Reinforcement Learning)
03:27:43 – How does a Machine Learning Model Learn?
03:35:31 – Supervised Machine Learning (Mukesh Rao)
04:34:51 – Python for Machine Learning
04:46:40 – Linear Regression Algorithm (Hands-on)
05:21:13 – What is Logistic Regression
05:29:39 – Linear Regression vs Logistic Regression
05:40:15 – Naïve Bayes Algorithm
05:49:32 – Diabetes Prediction using Naïve Bayes
06:15:18 – Decision Tree and Random Forest Algorithm
07:55:01 – Introduction to Support Vector Machines (SVMs)
08:07:08 – Kernel Functions
08:11:56 – Advantages & Disadvantages of SVMs
08:31:37 – K-NN Algorithm (K-Nearest Neighbour Algorithm)
08:40:13 – Introduction to Unsupervised Learning - Clustering
08:48:35 – Introduction to Principal Component Analysis
09:09:39 – PCA for Dimensionality Reduction
09:15:27 – Introduction to Hierarchical Clustering
09:28:38 – Types of Hierarchical Clustering
09:34:02 – How does Agglomerative hierarchical clustering work
09:42:32 – Euclidean Distance
09:45:10 – Manhattan Distance
09:48:01 – Minkowski Distance
09:50:02 – Jaccard Similarity Coefficient/Jaccard Index
09:54:02 – Cosine Similarity
09:58:18 – How to find an optimal number for clustering
10:03:02 – Applications Machine Learning

#datascience #machinelearning #deeplearning #ai #artificialintelligence #programming #developer #softwaredeveloper #computerscience 

Machine Learning for Beginners - Full Course
Romolo  Morelli

Romolo Morelli

1669187651

100+ JavaScript Concepts you Need to Know

This tutorial that quickly breaks down over 100 key concepts every web developer should know. Learn the basics of JS and start building apps on the web, mobile, desktop, and more.

1. all

This snippet returns true if the predicate function returns true for all elements in a collection and false otherwise. You can omit the second argument fnif you want to use Booleanas a default value.

const all = (arr, fn = Boolean) => arr.every(fn);

all([4, 2, 3], x => x > 1); // true
all([1, 2, 3]); // true

Read Also: Top 155 JavaScript Interview Questions and Answers for Developers

2. allEqual

This snippet checks whether all elements of the array are equal.

const allEqual = arr => arr.every(val => val === arr[0]);

allEqual([1, 2, 3, 4, 5, 6]); // false
allEqual([1, 1, 1, 1]); // true

3. approximatelyEqual

This snippet checks whether two numbers are approximately equal to each other, with a small difference.

const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;

approximatelyEqual(Math.PI / 2.0, 1.5708); // true

4. arrayToCSV

This snippet converts the elements to strings with comma-separated values.

const arrayToCSV = (arr, delimiter = ',') =>
  arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');
  
arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"'
arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"'```

5. arrayToHtmlList

This snippet converts the elements of an array into <li> tags and appends them to the list of the given ID.

const arrayToHtmlList = (arr, listID) =>
  (el => (
    (el = document.querySelector('#' + listID)),
    (el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
  ))();
  
arrayToHtmlList(['item 1', 'item 2'], 'myListID');

6. attempt

This snippet executes a function, returning either the result or the caught error object.

const attempt = (fn, ...args) => {
  try {
    return fn(...args);
  } catch (e) {
    return e instanceof Error ? e : new Error(e);
  }
};
var elements = attempt(function(selector) {
  return document.querySelectorAll(selector);
}, '>_>');
if (elements instanceof Error) elements = []; // elements = []

7. average

This snippet returns the average of two or more numerical values.

const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
average(...[1, 2, 3]); // 2
average(1, 2, 3); // 2

8. averageBy

This snippet returns the average of an array after initially doing the mapping of each element to a value using a given function.

const averageBy = (arr, fn) =>
  arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
  arr.length;
  
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5

9. bifurcate

This snippet splits values into two groups and then puts a truthy element of filterin the first group, and in the second group otherwise.

You can use Array.prototype.reduce()and Array.prototype.push()to add elements to groups based on filter.

const bifurcate = (arr, filter) =>
  arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); 
// [ ['beep', 'boop', 'bar'], ['foo'] ]

10. bifurcateBy

This snippet splits values into two groups, based on a predicate function. If the predicate function returns a truthy value, the element will be placed in the first group. Otherwise, it will be placed in the second group.

You can use Array.prototype.reduce()and Array.prototype.push()to add elements to groups, based on the value returned by fnfor each element.

const bifurcateBy = (arr, fn) =>
  arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
  
bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); 
// [ ['beep', 'boop', 'bar'], ['foo'] ]

11. bottomVisible

This snippet checks whether the bottom of a page is visible.

const bottomVisible = () =>
  document.documentElement.clientHeight + window.scrollY >=
  (document.documentElement.scrollHeight || document.documentElement.clientHeight);

bottomVisible(); // true

12. byteSize

This snippet returns the length of a string in bytes.

const byteSize = str => new Blob([str]).size;

byteSize('😀'); // 4
byteSize('Hello World'); // 11

13. capitalize

This snippet capitalizes the first letter of a string.

const capitalize = ([first, ...rest]) =>
  first.toUpperCase() + rest.join('');
  
capitalize('fooBar'); // 'FooBar'
capitalize('fooBar', true); // 'Foobar'

14. capitalizeEveryWord

This snippet capitalizes the first letter of every word in a given string.

const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());

capitalizeEveryWord('hello world!'); // 'Hello World!'

15. castArray

This snippet converts a non-array value into array.

const castArray = val => (Array.isArray(val) ? val : [val]);

castArray('foo'); // ['foo']
castArray([1]); // [1]

16. compact

This snippet removes false values from an array.

const compact = arr => arr.filter(Boolean);

compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); 
// [ 1, 2, 3, 'a', 's', 34 ]

17. countOccurrences

This snippet counts the occurrences of a value in an array.

const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3

18. Create Directory

This snippet uses existsSync() to check whether a directory exists and then mkdirSync() to create it if it doesn’t.

const fs = require('fs');
const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);
createDirIfNotExists('test'); 
// creates the directory 'test', if it doesn't exist

19. currentURL

This snippet returns the current URL.

const currentURL = () => window.location.href;

currentURL(); // 'https://medium.com/@fatosmorina'

20. dayOfYear

This snippet gets the day of the year from a Dateobject.

const dayOfYear = date =>
  Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);

dayOfYear(new Date()); // 272

21. decapitalize

This snippet turns the first letter of a string into lowercase.

const decapitalize = ([first, ...rest]) =>
  first.toLowerCase() + rest.join('')

decapitalize('FooBar'); // 'fooBar'
decapitalize('FooBar'); // 'fooBar'

22. deepFlatten

This snippet flattens an array recursively.

const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));

deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]

23. default

This snippet assigns default values for all properties in an object that are undefined.

const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);

defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 }

24. defer

This snippet delays the execution of a function until the current call stack is cleared.

const defer = (fn, ...args) => setTimeout(fn, 1, ...args);

defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'

25. degreesToRads

This code snippet can be used to convert a value from degrees to radians.

const degreesToRads = deg => (deg * Math.PI) / 180.0;

degreesToRads(90.0); // ~1.5708

26. difference

This snippet finds the difference between two arrays.

const difference = (a, b) => {
  const s = new Set(b);
  return a.filter(x => !s.has(x));
};

difference([1, 2, 3], [1, 2, 4]); // [3]

27. differenceBy

This method returns the difference between two arrays, after applying a given function to each element of both lists.

const differenceBy = (a, b, fn) => {
  const s = new Set(b.map(fn));
  return a.filter(x => !s.has(fn(x)));
};

differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2]
differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ]

28. differenceWith

This snippet removes the values for which the comparator function returns false.

const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);

differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); 
// [1, 1.2]

29. digitize

This snippet gets a number as input and returns an array of its digits.

const digitize = n => [...`${n}`].map(i => parseInt(i));

digitize(431); // [4, 3, 1]

30. distance

This snippet returns the distance between two points by calculating the Euclidean distance.

const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);

distance(1, 1, 2, 3); // 2.23606797749979

31. Drop Elements

This snippet returns a new array with n elements removed from the left.

const drop = (arr, n = 1) => arr.slice(n);

drop([1, 2, 3]); // [2,3]
drop([1, 2, 3], 2); // [3]
drop([1, 2, 3], 42); // []

32. dropRight

This snippet returns a new array with n elements removed from the right.

const dropRight = (arr, n = 1) => arr.slice(0, -n);

dropRight([1, 2, 3]); // [1,2]
dropRight([1, 2, 3], 2); // [1]
dropRight([1, 2, 3], 42); // []

33. dropRightWhile

This snippet removes elements from the right side of an array until the passed function returns true.

const dropRightWhile = (arr, func) => {
  while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
  return arr;
};

dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2]

34. dropWhile

This snippet removes elements from an array until the passed function returns true.

const dropWhile = (arr, func) => {
  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
  return arr;
};

dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4]

35. elementContains

This snippet checks whether the parent element contains the child.

const elementContains = (parent, child) => parent !== child && parent.contains(child);

elementContains(document.querySelector('head'), document.querySelector('title')); // true
elementContains(document.querySelector('body'), document.querySelector('body')); // false

36. Filter Duplicate Elements

This snippet removes duplicate values in an array.

const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));

filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5]

37. findKey

This snippet returns the first key that satisfies a given function.

const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));

findKey(
  {
    barney: { age: 36, active: true },
    fred: { age: 40, active: false },
    pebbles: { age: 1, active: true }
  },
  o => o['active']
); // 'barney'

38. findLast

This snippet returns the last element for which a given function returns a truthy value.

const findLast = (arr, fn) => arr.filter(fn).pop();

findLast([1, 2, 3, 4], n => n % 2 === 1); // 3

39. flatten

This snippet flattens an array up to a specified depth using recursion.

const flatten = (arr, depth = 1) =>
  arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);

flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]

40. forEachRight

This snippet executes a function for each element of an array starting from the array’s last element.

const forEachRight = (arr, callback) =>
  arr
    .slice(0)
    .reverse()
    .forEach(callback);
    
forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'

41. forOwn

This snippet iterates on each property of an object and iterates a callback for each one respectively.

const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1

42. functionName

This snippet prints the name of a function into the console.

const functionName = fn => (console.debug(fn.name), fn);

functionName(Math.max); // max (logged in debug channel of console)

43. Get Time From Date

This snippet can be used to get the time from a Dateobject as a string.

const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);

getColonTimeFromDate(new Date()); // "08:38:00"

44. Get Days Between Dates

This snippet can be used to find the difference in days between two dates.

const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
  (dateFinal - dateInitial) / (1000 * 3600 * 24);
  
getDaysDiffBetweenDates(new Date('2019-01-13'), new Date('2019-01-15')); // 2

45. getStyle

This snippet can be used to get the value of a CSS rule for a particular element.

const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];

getStyle(document.querySelector('p'), 'font-size'); // '16px'

46. getType

This snippet can be used to get the type of a value.

const getType = v =>
  v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
  
getType(new Set([1, 2, 3])); // 'set'

47. hasClass

This snippet checks whether an element has a particular class.

const hasClass = (el, className) => el.classList.contains(className);
hasClass(document.querySelector('p.special'), 'special'); // true

48. head

This snippet returns the head of a list.

const head = arr => arr[0];

head([1, 2, 3]); // 1

49. hide

This snippet can be used to hide all elements specified.

const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));

hide(document.querySelectorAll('img')); // Hides all <img> elements on the page

50. httpsRedirect

This snippet can be used to redirect from HTTP to HTTPS in a particular domain.

const httpsRedirect = () => {
  if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
};

httpsRedirect(); // If you are on http://mydomain.com, you are redirected to https://mydomain.com

51. indexOfAll

This snippet can be used to get all indexes of a value in an array, which returns an empty array, in case this value is not included in it.

const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);

indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []

52. initial

This snippet returns all elements of an array except the last one.

const initial = arr => arr.slice(0, -1);

initial([1, 2, 3]); // [1,2]const initial = arr => arr.slice(0, -1);
initial([1, 2, 3]); // [1,2]

53. insertAfter

This snippet can be used to insert an HTML string after the end of a particular element.

const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);

insertAfter(document.getElementById('myId'), '<p>after</p>'); // <div id="myId">...</div> <p>after</p>

54. insertBefore

This snippet can be used to insert an HTML string before a particular element.

const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);

insertBefore(document.getElementById('myId'), '<p>before</p>'); // <p>before</p> <div id="myId">...</div>

55. intersection

This snippet can be used to get an array with elements that are included in two other arrays.

const intersection = (a, b) => {
  const s = new Set(b);
  return a.filter(x => s.has(x));
};

intersection([1, 2, 3], [4, 3, 2]); // [2, 3]

56. intersectionBy

This snippet can be used to return a list of elements that exist in both arrays, after a particular function has been executed to each element of both arrays.

const intersectionBy = (a, b, fn) => {
  const s = new Set(b.map(fn));
  return a.filter(x => s.has(fn(x)));
};

intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1]

57. intersectionWith

This snippet can be used to return a list of elements that exist in both arrays by using a comparator function.

const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);

intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]

58. is

This snippet can be used to check if a value is of a particular type.

const is = (type, val) => ![, null].includes(val) && val.constructor === type;

is(Array, [1]); // true
is(ArrayBuffer, new ArrayBuffer()); // true
is(Map, new Map()); // true
is(RegExp, /./g); // true
is(Set, new Set()); // true
is(WeakMap, new WeakMap()); // true
is(WeakSet, new WeakSet()); // true
is(String, ''); // true
is(String, new String('')); // true
is(Number, 1); // true
is(Number, new Number(1)); // true
is(Boolean, true); // true
is(Boolean, new Boolean(true)); // true

59. isAfterDate

This snippet can be used to check whether a date is after another date.

const isAfterDate = (dateA, dateB) => dateA > dateB;

isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true

60. isAnagram

This snippet can be used to check whether a particular string is an anagram with another string.

const isAnagram = (str1, str2) => {
  const normalize = str =>
    str
      .toLowerCase()
      .replace(/[^a-z0-9]/gi, '')
      .split('')
      .sort()
      .join('');
  return normalize(str1) === normalize(str2);
};

isAnagram('iceman', 'cinema'); // true

61. isArrayLike

This snippet can be used to check if a provided argument is iterable like an array.

const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';

isArrayLike(document.querySelectorAll('.className')); // true
isArrayLike('abc'); // true
isArrayLike(null); // false

62. isBeforeDate

This snippet can be used to check whether a date is before another date.

const isBeforeDate = (dateA, dateB) => dateA < dateB;

isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true

63. isBoolean

This snippet can be used to check whether an argument is a boolean.

const isBoolean = val => typeof val === 'boolean';

isBoolean(null); // false
isBoolean(false); // true

64. isBrowser

This snippet can be used to determine whether the current runtime environment is a browser. This is helpful for avoiding errors when running front-end modules on the server (Node).

const isBrowser = () => ![typeof window, typeof document].includes('undefined');

isBrowser(); // true (browser)
isBrowser(); // false (Node)

65. isBrowserTabFocused

This snippet can be used to determine whether the browser tab is focused.

const isBrowserTabFocused = () => !document.hidden;

isBrowserTabFocused(); // true

66. isLowerCase

This snippet can be used to determine whether a string is lower case.

const isLowerCase = str => str === str.toLowerCase();

isLowerCase('abc'); // true
isLowerCase('a3@$'); // true
isLowerCase('Ab4'); // false

67. isNil

This snippet can be used to check whether a value is null or undefined.

const isNil = val => val === undefined || val === null;

isNil(null); // true
isNil(undefined); // true

68. isNull

This snippet can be used to check whether a value is null.

const isNull = val => val === null;

isNull(null); // true

69. isNumber

This snippet can be used to check whether a provided value is a number.

const isNumber = val => typeof val === 'number';

isNumber('1'); // false
isNumber(1); // true

70. isObject

This snippet can be used to check whether a provided value is an object. It uses the Object constructor to create an object wrapper for the given value.

If it is already an object, then an object type that corresponds to the given value will be returned. Otherwise, a new object will be returned.

const isObject = obj => obj === Object(obj);

isObject([1, 2, 3, 4]); // true
isObject([]); // true
isObject(['Hello!']); // true
isObject({ a: 1 }); // true
isObject({}); // true
isObject(true); // false

71. isObjectLike

This snippet can be used to check if a value is not nulland that its typeof is “object”.

const isObjectLike = val => val !== null && typeof val === 'object';

isObjectLike({}); // true
isObjectLike([1, 2, 3]); // true
isObjectLike(x => x); // false
isObjectLike(null); // false

72. isPlainObject

This snippet checks whether a value is an object created by the Object constructor.

const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;

isPlainObject({ a: 1 }); // true
isPlainObject(new Map()); // false

73. isPromiseLike

This snippet checks whether an object looks like a Promise.

const isPromiseLike = obj =>
  obj !== null &&
  (typeof obj === 'object' || typeof obj === 'function') &&
  typeof obj.then === 'function';
  
isPromiseLike({
  then: function() {
    return '';
  }
}); // true
isPromiseLike(null); // false
isPromiseLike({}); // false

74. isSameDate

This snippet can be used to check whether two dates are equal.

const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();

isSameDate(new Date(2010, 10, 20), new Date(2010, 10, 20)); // true

75. isString

This snippet can be used to check whether an argument is a string.

const isString = val => typeof val === 'string';

isString('10'); // true

76. isSymbol

This snippet can be used to check whether an argument is a symbol.

const isSymbol = val => typeof val === 'symbol';

isSymbol(Symbol('x')); // true

77. isUndefined

This snippet can be used to check whether a value is undefined.

const isUndefined = val => val === undefined;

isUndefined(undefined); // true

78. isUpperCase

This snippet can be used to check whether a string is upper case.

const isUpperCase = str => str === str.toUpperCase();

isUpperCase('ABC'); // true
isLowerCase('A3@$'); // true
isLowerCase('aB4'); // false

79. isValidJSON

This snippet can be used to check whether a string is a valid JSON.

const isValidJSON = str => {
  try {
    JSON.parse(str);
    return true;
  } catch (e) {
    return false;
  }
};

isValidJSON('{"name":"Adam","age":20}'); // true
isValidJSON('{"name":"Adam",age:"20"}'); // false
isValidJSON(null); // true

80. last

This snippet returns the last element of an array.

const last = arr => arr[arr.length - 1];

last([1, 2, 3]); // 3

81. matches

This snippet compares two objects to determine if the first one contains the same property values as the second one.

const matches = (obj, source) =>
  Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
  
matches({ age: 25, hair: 'long', beard: true }, { hair: 'long', beard: true }); // true
matches({ hair: 'long', beard: true }, { age: 25, hair: 'long', beard: true }); // false

82. maxDate

This snippet can be used to get the latest date.

const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates));

const array = [
  new Date(2017, 4, 13),
  new Date(2018, 2, 12),
  new Date(2016, 0, 10),
  new Date(2016, 0, 9)
];
maxDate(array); // 2018-03-11T22:00:00.000Z

83. maxN

This snippet returns the n largest elements from a list. If nis greater than or equal to the list’s length, then it will return the original list (sorted in descending order).

const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);

maxN([1, 2, 3]); // [3]
maxN([1, 2, 3], 2); // [3,2] 	

84. minDate

This snippet can be used to get the earliest date.

const minDate = (...dates) => new Date(Math.min.apply(null, ...dates));

const array = [
  new Date(2017, 4, 13),
  new Date(2018, 2, 12),
  new Date(2016, 0, 10),
  new Date(2016, 0, 9)
];
minDate(array); // 2016-01-08T22:00:00.000Z

85. minN

This snippet returns the n smallest elements from a list. If nis greater than or equal to the list’s length, then it will return the original list (sorted in ascending order).

const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);

minN([1, 2, 3]); // [1]
minN([1, 2, 3], 2); // [1,2]

86. negate

This snippet can be used to apply the not operator (!) to a predicate function with its arguments.

const negate = func => (...args) => !func(...args);

[1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ]

87. nodeListToArray

This snippet can be used to convert a nodeList to an array.

const nodeListToArray = nodeList => [...nodeList];

nodeListToArray(document.childNodes); // [ <!DOCTYPE html>, html ]

88. pad

This snippet can be used to pad a string on both sides with a specified character if it is shorter than the specified length.

const pad = (str, length, char = ' ') =>
  str.padStart((str.length + length) / 2, char).padEnd(length, char);
  
pad('cat', 8); // '  cat   '
pad(String(42), 6, '0'); // '004200'
pad('foobar', 3); // 'foobar'

89. radsToDegrees

This snippet can be used to convert an angle from radians to degrees.

const radsToDegrees = rad => (rad * 180.0) / Math.PI;

radsToDegrees(Math.PI / 2); // 90

90. Random Hexadecimal Color Code

This snippet can be used to generate a random hexadecimal color code.

const randomHexColorCode = () => {
  let n = (Math.random() * 0xfffff * 1000000).toString(16);
  return '#' + n.slice(0, 6);
};

randomHexColorCode(); // "#e34155"

91. randomIntArrayInRange

This snippet can be used to generate an array with n random integers in a specified range.

const randomIntArrayInRange = (min, max, n = 1) =>
  Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
  
randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]

92. randomIntegerInRange

This snippet can be used to generate a random integer in a specified range.

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

randomIntegerInRange(0, 5); // 3

93. randomNumberInRange

This snippet can be used to return a random number in a specified range.

const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;

randomNumberInRange(2, 10); // 6.0211363285087005

94. readFileLines

This snippet can be used to read a file by getting an array of lines from a file.

const fs = require('fs');
const readFileLines = filename =>
  fs
    .readFileSync(filename)
    .toString('UTF8')
    .split('\n');

let arr = readFileLines('test.txt');
console.log(arr); // ['line1', 'line2', 'line3']

 

95. Redirect to a URL

This snippet can be used to do a redirect to a specified URL.

const redirect = (url, asLink = true) =>
  asLink ? (window.location.href = url) : window.location.replace(url);
  
redirect('https://google.com');

96. reverse

This snippet can be used to reverse a string.

const reverseString = str => [...str].reverse().join('');

reverseString('foobar'); // 'raboof'

97. round

This snippet can be used to round a number to a specified number of digits.

const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);

round(1.005, 2); // 1.01

98. runPromisesInSeries

This snippet can be used to run an array of promises in series.

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
const delay = d => new Promise(r => setTimeout(r, d));

runPromisesInSeries([() => delay(1000), () => delay(2000)]); 
// Executes each promise sequentially, taking a total of 3 seconds to complete

99. sample

This snippet can be used to get a random number from an array.

const sample = arr => arr[Math.floor(Math.random() * arr.length)];

sample([3, 7, 9, 11]); // 9

100. sampleSize

This snippet can be used to get nrandom elements from unique positions from an array up to the size of the array. Elements in the array are shuffled using the Fisher-Yates algorithm.

const sampleSize = ([...arr], n = 1) => {
  let m = arr.length;
  while (m) {
    const i = Math.floor(Math.random() * m--);
    [arr[m], arr[i]] = [arr[i], arr[m]];
  }
  return arr.slice(0, n);
};

sampleSize([1, 2, 3], 2); // [3,1]
sampleSize([1, 2, 3], 4); // [2,3,1]

101. scrollToTop

This snippet can be used to do a smooth scroll to the top of the current page.

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};

scrollToTop();

102. serializeCookie

This snippet can be used to serialize a cookie name-value pair into a Set-Cookie header string.

const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;

serializeCookie('foo', 'bar'); // 'foo=bar'

103. setStyle

This snippet can be used to set the value of a CSS rule for a particular element.

const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);

setStyle(document.querySelector('p'), 'font-size', '20px');
// The first <p> element on the page will have a font-size of 20px

104. shallowClone

This snippet can be used to create a shallow clone of an object.

const shallowClone = obj => Object.assign({}, obj);

const a = { x: true, y: 1 };
const b = shallowClone(a); // a !== b

105. show

This snippet can be used to show all the elements specified.

const show = (...el) => [...el].forEach(e => (e.style.display = ''));

show(...document.querySelectorAll('img')); // Shows all <img> elements on the page

106. shuffle

This snippet can be used to order the elements of an array randomly using the Fisher-Yates algorithm.

const shuffle = ([...arr]) => {
  let m = arr.length;
  while (m) {
    const i = Math.floor(Math.random() * m--);
    [arr[m], arr[i]] = [arr[i], arr[m]];
  }
  return arr;
};

const foo = [1, 2, 3];
shuffle(foo); // [2, 3, 1], foo = [1, 2, 3]

107. similarity

This snippet can be used to return an array of elements that appear in two arrays.

https://medium.com/better-programming/127-helpful-javascript-snippets-you-can-learn-in-30-seconds-or-less-part-6-of-6-862a6403d334

108. sleep

This snippet can be used to delay the execution of an asynchronous function by putting it into sleep.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

async function sleepyWork() {
  console.log("I'm going to sleep for 1 second.");
  await sleep(1000);
  console.log('I woke up after 1 second.');
}

109. smoothScroll

This snippet can be used to smoothly scroll the element on which it is called into the visible area of the browser window.

const smoothScroll = element =>
  document.querySelector(element).scrollIntoView({
    behavior: 'smooth'
  });
  
smoothScroll('#fooBar'); // scrolls smoothly to the element with the id fooBar
smoothScroll('.fooBar'); // scrolls smoothly to the first element with a class of fooBar

110. sortCharactersInString

This snippet can be used to alphabetically sort the characters in a string.

const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');

sortCharactersInString('cabbage'); // 'aabbceg'

111. splitLines

This snippet can be used to split a multi-line string into an array of lines.

const splitLines = str => str.split(/\r?\n/);

splitLines('This\nis a\nmultiline\nstring.\n'); // ['This', 'is a', 'multiline', 'string.' , '']

112. stripHTMLTags

This snippet can be used to remove HTML/XML tags from a string.

const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');

stripHTMLTags('<p><em>lorem</em> <strong>ipsum</strong></p>'); // 'lorem ipsum'

113. sum

This snippet can be used to find the sum of two or more numbers or arrays.

const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);

sum(1, 2, 3, 4); // 10
sum(...[1, 2, 3, 4]); // 10

114. tail

This snippet can be used to get an array with all the elements of an array except for the first one. If the array has only one element, then that an array with that element will be returned instead.

const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);

tail([1, 2, 3]); // [2,3]
tail([1]); // [1]

115. take

This snippet can be used to get an array with nelements removed from the beginning.

const take = (arr, n = 1) => arr.slice(0, n);

take([1, 2, 3], 5); // [1, 2, 3]
take([1, 2, 3], 0); // []

116. takeRight

This snippet can be used to get an array with nelements removed from the end.

const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);

takeRight([1, 2, 3], 2); // [ 2, 3 ]
takeRight([1, 2, 3]); // [3]

117. timeTaken

This snippet can be used to find out the time it takes to execute a function.

const timeTaken = callback => {
  console.time('timeTaken');
  const r = callback();
  console.timeEnd('timeTaken');
  return r;
};

timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms

118. times

This snippet can be used to iterate over a callback ntimes.

const times = (n, fn, context = undefined) => {
  let i = 0;
  while (fn.call(context, i) !== false && ++i < n) {}
};

var output = '';
times(5, i => (output += i));
console.log(output); // 01234

119. toCurrency

This snippet can be used to format a number like a currency.

const toCurrency = (n, curr, LanguageFormat = undefined) =>
  Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
  
toCurrency(123456.789, 'EUR'); // €123,456.79  | currency: Euro | currencyLangFormat: Local
toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79  | currency: US Dollar | currencyLangFormat: English (United States)
toCurrency(123456.789, 'USD', 'fa'); // ۱۲۳٬۴۵۶٫۷۹ ؜$ | currency: US Dollar | currencyLangFormat: Farsi
toCurrency(322342436423.2435, 'JPY'); // ¥322,342,436,423 | currency: Japanese Yen | currencyLangFormat: Local
toCurrency(322342436423.2435, 'JPY', 'fi'); // 322 342 436 423 ¥ | currency: Japanese Yen | currencyLangFormat: Finnish

120. toDecimalMark

This snippet uses the toLocaleString()function to convert float-point arithmetic to the decimal mark form by using a number to make a comma-separated string.

const toDecimalMark = num => num.toLocaleString('en-US');

toDecimalMark(12305030388.9087); // "12,305,030,388.909"

121. toggleClass

This snippet can be used to toggle a class for an element.

const toggleClass = (el, className) => el.classList.toggle(className);

toggleClass(document.querySelector('p.special'), 'special'); // The paragraph will not have the 'special' class anymore

122. tomorrow

This snippet can be used to get a string representation of tomorrow’s date.

const tomorrow = () => {
  let t = new Date();
  t.setDate(t.getDate() + 1);
  return t.toISOString().split('T')[0];
};

tomorrow(); // 2019-09-08 (if current date is 2018-09-08)

123. unfold

This snippet can be used to build an array using an iterator function and an initial seed value.

const unfold = (fn, seed) => {
  let result = [],
    val = [null, seed];
  while ((val = fn(val[1]))) result.push(val[0]);
  return result;
};

var f = n => (n > 50 ? false : [-n, n + 10]);
unfold(f, 10); // [-10, -20, -30, -40, -50]

124. union

This snippet can be used to find the union of two arrays, resulting in an array that has elements that come from both arrays but that do not repeat.

const union = (a, b) => Array.from(new Set([...a, ...b]));

union([1, 2, 3], [4, 3, 2]); // [1,2,3,4]

125. uniqueElements

This snippet uses ES6 Setandthe…restoperator to get every element only once.

const uniqueElements = arr => [...new Set(arr)];

uniqueElements([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5]

126. validateNumber

This snippet can be used to check whether a value is a number.

const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;

validateNumber('10'); // true

127. words

This snippet converts a string into an array of words.

const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);

words('I love javaScript!!'); // ["I", "love", "javaScript"]
words('python, javaScript & coffee'); // ["python", "javaScript", "coffee"]

#javascript #js #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

100+ JavaScript Concepts you Need to Know
Adam Daniels

Adam Daniels

1669176068

How to Create a New Java Web Project

In this tutorial, you'll learn how to create a new Java Web project in IntelliJ IDEA with Spring Boot, Spring Security, Spring Data, Lombok, and Vaadin.

  • Creating a new project with database connection in IntelliJ IDEA: Learn how to create a new Java Web project in IntelliJ IDEA with Spring Boot, Spring Security, Spring Data, Lombok, and Vaadin.
  • Implementing the backend with JPA: Learn how to implement a backend with database connectivity using JPA and Spring Data.
  • Authentication and authorization with Spring Security: Learn how to configure Spring Security in a Java Web application developed with Vaadin, how to implement a login screen, and how to manage authentication and authorization.
  • Implementing a CRUD view with database connection: Learn how to implement CRUD (create, read, update, delete) web pages with a database connection in Java using Vaadin.
  • Implementing a collaborative web form with chat: Learn how to implement a web form with collaborative features that include a real-time chat in a few lines of code using Vaadin Collaboration Engine.
  • Adding exportable reports (PDF, CSV, XML, DOC, XLS): Learn how to use JasperReports (through DynamicJasper) to render reports in the browser and how to export them to different formats (PDF, CSV, XML, DOC, XLS, and others).

#java #intellijidea #springboot #springsecurity #springdata #lombok #vaadin #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

How to Create a New Java Web Project
Garry Taylor

Garry Taylor

1669169798

5 Ways for Optimizing Vue Applications

Learn how to speed up your Vue.js web applications with 5 techniques: Lazy loading route components, Minimize the use of external libraries, Compress and optimize images, Lazy load images, Reuse functionalities across your app

Performance is a touchy subject in software engineering. It’s one thing to write code and ship it; it’s another thing entirely to make it faster and more enjoyable for your users — and the next developers after you.

In this article, we will look at how to speed up your Vue.js web applications, thereby improving both user experience and developer experience. Let’s begin, shall we?

  1. Lazy loading route components
  2. Minimize the use of external libraries
  3. Compress and optimize images
  4. Lazy load images
  5. Reuse functionalities across your app

1. Lazy loading route components

The term lazy loading in software engineering refers to the pattern of deferring the initialization of an object or a part of an application until it is needed.

Typically, our Vue.js app is bundled into one relatively large JavaScript file, but with this technique, each component is compiled into into smaller file chunks, each chunk for a route component. Because of this, our application loads faster in a browser, and a new chunk is requested only when a user visits a new route.

If you’re already familiar with lazy loading components in Vue, bear in mind that this method is not for lazy loading every single component in our codebase, just the ones we register with Vue Router. All other components registered inside the router component would be part of the bundle.

You can go through this article to learn more about lazy loading those components.

So how is this done? Let’s have a look:

// in router.js file
import Vue from 'vue'
import Router from 'vue-router'

const Home = () => import('./routes/Home.vue');
const Profile = () => import('./routes/Profile.vue');

Vue.use(Router)

export default new Router({
  routes: [
    { path: '/', component: Home },
    { path: '/profile', component: Profile }
  ]
})

When we register our components this way, webpack automatically splits our code into chunks. It is also possible to group these files into one chunk. A great scenario would be grouping components related by route into one chunk.

// specifying the same chunk for components
const Profile = () => import(/* webpackChunkName: "profile" */'./routes/Profile.vue');
const ProfileSettings = () => import(/* webpackChunkName: "profile" */'./routes/ProfileSettings.vue');

By using the comment to explicitly specify the chunk name, webpack automatically bundles the compiled components into the same chunk.

2. Minimize the use of external libraries

With the massive support behind JavaScript and the large number of packages published and updated on npm daily, chances are good there’s a package for anything you need in your web app. And that’s great — but we have to be careful not to bloat our app’s size with code that may not be necessary. There is almost always a lighter alternative to a package.

A good practice is to check whether the feature you want to implement is available natively in browsers before looking for a package. If the native feature is unreliable across browsers or is tough to implement, then a package is likely the best way to go.

When searching for a package, be sure to weigh your options across the various packages you find. A package that’s built in a modular pattern and supports tree-shaking is the most suitable for your project.

3. Compress and optimize images

Images are easily the greatest factors that contribute to an app’s bundle size. During rendering, heavy images can actually block some parts of the application from being rendered quickly.

It all depends on how you are serving your images; the two techniques are locally or with the help of CDNs. The use of a CDN to deliver images would depend on the number of images to be displayed in the application.

Optimizing local images

If your application just has three to five images to display, serving them locally is okay. The sizes of these files have to be considered, however, and the images may have to be compressed and scaled down in order to reduce the file sizes. A tool like Adobe Photoshop can work magic, but there are also freely available online tools for compressing images:

  1. Image compressor
  2. TinyPNG
  3. iLoveIMG

Optimizing CDN images

Optimizing images on a CDN is a great way to optimize a media-heavy application. With the transformation features a CDN provides, the file sizes of images can be reduced by up to 70 percent, and they would still look good on the site.

If the total number of images to be used in the application is around 10 or more, using a CDN is probably the best way to go about handling these files. Here’s a list of some popular media management platforms:

  1. Cloudinary
  2. Imagekit

4. Lazy load images

In some cases, just compressing media files on the web isn’t enough, especially when dealing with media-heavy sites. This is where lazy loading comes in handy again. On the initial page load, only media files that are visible in the viewport are requested; the rest are requested as the user navigates through the application.

For lazy loading images, we can use the vue-lazyload package. It is a lightweight, easy-to-use library with a lot of flexibility.

Installation:

npm i vue-lazyload

Setup:

// in main.js

import Vue from 'vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)

Working with v-for:

<ul>
  <li v-for="image in images">
    <img v-lazy="image.src" >
  </li>
</ul>

Working with raw HTML:

<section v-lazy-container="{ selector: 'img' }">
  <img data-src="//images.com/cat1.jpg">
  <img data-src="//images.com/cat2.jpg">
  <img data-src="//images.com/cat3.png">  
</section>

Now the images will only be requested when they enter the viewport. If you’re working on a Nuxt project, create the file vue-lazyload.js with the content of the main.js (above) in the /plugins directory.

Register the plugin in the nuxt.config.js file like this:

export default {
  plugins: [
    { src: '~/plugins/vue-lazyload.js', mode: 'client' }
  ]
}

There are other flexible options in the official documentation.

5. Reuse functionalities across your app

When working with external libraries, it’s quite easy to forget about reusability. In this section, we’ll be looking at the Vue Notifications library as an example.

Vue Notifications is a bridge between your Vue app and various notification libraries. It makes switching between notification libraries easy as well. Let’s have a look at how to use the library according to the documentation.

// in main.js
import Vue from 'vue'
import VueNotifications from 'vue-notifications'
import VueToasted from 'vue-toasted' // https://github.com/shakee93/vue-toasted


function toast({ title, message, type, timeout, cb }) {
  if (type === VueNotifications.types.warn) type = 'show'
  return Vue.toasted\[type\](message, { duration: timeout })
}

Vue.use(VueToasted)

const options = {
  success: toast,
  error: toast,
  info: toast,
  warn: toast
}
Vue.use(VueNotifications, options)

In the script section of our components:

import VueNotifications from 'vue-notifications'

export default {
  name: 'Register',
  data () {
    return {
      email: '',
      password: ''
    }
  },
  notifications: {
    showSuccess: {
      type: VueNotifications.types.success,
      title: 'Success!',
      message: 'Account created successfully'
    },
    showError: {
      type: VueNotifications.types.error,
      title: 'Oops!',
      message: "Something's wrong"
    }
  }
  methods: {
    async login(){
      try {
        await sendUserData() // or any other way to send credentials
        this.showSuccess()
      } catch (error){
        // after checking error type
        this.showError({message: error.data.message})
      }
    }
  }
}

Notice how we had to import the VueNotifications package into the component and add a notifications option as well? That would be fine if we were only to use the package in just one component, but I doubt that would be the case for any large application.

Instead of manually importing VueNotifications into components and setting custom options in over 10 different components, how about we create a generic mixin that can serve the purpose of displaying any notification message to our users?

First, we create the file /mixins/notifications.js:

import VueNotifications from 'vue-notifications'
export default {
  notifications: {
    showError: {
      title: 'Oops!',
      message:
        "Something's wrong with, please check your internet and try again.",
      type: VueNotifications.types.error
    },
    showSuccess: {
      type: VueNotifications.types.success,
      title: 'Success!',
      message: 'Action successful'
    }
  }
}

And now we can just import only the mixin in our components:

import notifications from '@/mixins/notifications'

export default {
  name: 'Register',
  mixins: [notifications],
  data () {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    async login(){
      try {
        await sendUserData() // or any other way to send credentials
        this.showSuccess({ message: 'Account created successfully' })
      } catch (error){
        // after checking error type
        this.showError({ message: error.data.message })
      }
    }
  }
}

Now our component is less cluttered and easier to read. By using mixins, we are only importing references to the specific parts of the package we need.

Conclusion

While there are even more ways to optimize our Vue apps not listed here, the five techniques listed above are among the most used.

For those who skimmed through the article, here are the points highlighted above:

  • Lazy load your route components
  • Minimize the use of external libraries, and be sure to weigh your options if you must use one
  • Compress and optimize images before delivering on the web
  • Lazy load your images to provide a smooth user experience through out your app
  • Reuse functionalities across your app to minimize duplicate code

Original article source at https://blog.logrocket.com

#vue #vuejs #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

5 Ways for Optimizing Vue Applications

How to Optimize the Performance of Vue.js Application?

Learn how to optimize the performance of Vue.js application. This tutorial shows some of the front-end optimization tips to keep our Vue apps as efficient as possible.

Single Page Applications (SPAs) can provide a rich, interactive user experience when dealing with real-time, dynamic data. But they can also be heavy, bloated, and perform poorly. In this article, we’ll walk through some of the front-end optimization tips to keep our Vue apps relatively lean and only ship the JS we need when it’s needed.

Note: Some familiarity with Vue and the Composition API is assumed, but there will hopefully be some useful takeaways regardless of your framework choice.

As a front-end developer at Ada Mode, my job involves building Windscope, a web app for wind farm operators to manage and maintain their fleet of turbines. Due to the need to receive data in real time and the high level of interactivity required, an SPA architecture was chosen for the project. Our web app is dependent on some heavy JS libraries, but we want to provide the best experience for the end user by fetching data and rendering as quickly and efficiently as possible.

Choosing A Framework 

Our JS framework of choice is Vue, partly chosen as it’s the framework I’m most familiar with. Previously Vue had a smaller overall bundle size compared to React. However, since recent React updates, the balance appears to have shifted in React’s favor. That doesn’t necessarily matter, as we’ll look at how to only import what we need in the course of this article. Both frameworks have excellent documentation and a large developer ecosystem, which was another consideration. Svelte is another possible choice, but it would have required a steeper learning curve due to unfamiliarity, and being newer, it has a less developed ecosystem.

As an example to demonstrate the various optimizations, I’ve built a simple Vue app that fetches data from an API and renders some charts using D3.js.

Visualization of the Vue app with some charts

(Large preview)

Note: Please refer to the example GitHub repository for the full code.

We’re using Parcel, a minimal-config build tool, to bundle our app, but all of the optimizations we’ll cover here are applicable to whichever bundler you choose.

Tree Shaking, Compression, And Minification With Build Tools 

It’s good practice to only ship the code you need, and right out of the box, Parcel removes unused Javascript code during the build process (tree shaking). It also minifies the result and can be configured to compress the output with Gzip or Brotli.

As well as minification, Parcel also employs scope hoisting as part of its production process, which can help make minification even more efficient. An in-depth guide to scope hoisting is outside of the scope (see what I did there?) of this article. Still, if we run Parcel’s build process on our example app with the --no-optimize and --no-scope-hoist flags, we can see the resulting bundle is 510kB — around 5 times higher than the optimized and minified version. So, whichever bundler you’re using, it’s fair to say you’ll probably want to make sure it’s carrying out as many optimizations as possible.

But the work doesn’t end here. Even if we’re shipping a smaller bundle overall, it still takes time for the browser to parse and compile our JS, which can contribute to a slower user experience. This article on Bundle Size Optimization by Calibre explains how large JS bundles affect performance metrics.

Let’s look at what else we can do to reduce the amount of work the browser has to do.

Vue Composition API 

Vue 3 introduced the Composition API, a new set of APIs for authoring components as an alternative to the Options API. By exclusively using the Composition API, we can import only the Vue functions that we need instead of the whole package. It also enables us to write more reusable code using composables. Code written using the Composition API lends itself better to minification, and the whole app is more susceptible to tree-shaking.

Note: You can still use the Composition API if you’re using an older version of Vue: it was backported to Vue 2.7, and there is an official plugin for older versions.

Importing Dependencies 

A key goal was to reduce the size of the initial JS bundle downloaded by the client. Windscope makes extensive use of D3 for data visualization, a large library and wide-ranging in scope. However, Windscope only needs part of it (there are entire modules in the D3 library that we don’t need at all). If we examine the entire D3 package on Bundlephobia, we can see that our app uses less than half of the available modules and perhaps not even all of the functions within those modules.

One of the easiest ways to keep our bundle size as small as possible is only to import the modules we need.

Let’s take D3’s selectAll function. Instead of using a default import, we can just import the function we need from the d3-selection module:

// Previous:
import * as d3 from 'd3'

// Instead:
import { selectAll } from 'd3-selection'

 

Code Splitting With Dynamic Imports 

There are certain packages that are used in a bunch of places throughout Windscope, such as the AWS Amplify authentication library, specifically the Auth method. This is a large dependency that contributes heavily to our JS bundle size. Rather than import the module statically at the top of the file, dynamic imports allow us to import the module exactly where we need it in our code.

Instead of:

import { Auth } from '@aws-amplify/auth'

const user = Auth.currentAuthenticatedUser()

 

We can import the module when we want to use it:

import('@aws-amplify/auth').then(({ Auth }) => {
    const user = Auth.currentAuthenticatedUser()
})

 

This means that the module will be split out into a separate JS bundle (or “chunk”), which will only be downloaded by the browser if and when it is needed. Additionally, the browser can cache these dependencies, which may change less frequently than the code for the rest of our app.

Lazy Loading Routes With Vue Router 

Our app uses Vue Router for navigation. Similarly to dynamic imports, we can lazyload our route components, so they will only be imported (along with their associated dependencies) when a user navigates to that route.

In our index/router.js file:

// Previously:
import Home from "../routes/Home.vue";
import About = "../routes/About.vue";

// Lazyload the route components instead:
const Home = () => import("../routes/Home.vue");
const About = () => import("../routes/About.vue");

const routes = [
  {
    name: "home",
    path: "/",
    component: Home,
  },
  {
    name: "about",
    path: "/about",
    component: About,
  },
];

 

The code for the ‘About’ route will only be loaded when the user clicks the ‘About’ link and navigates to the route.

Async Components 

In addition to lazyloading each route, we can also lazyload individual components using Vue’s defineAsyncComponent method.

const KPIComponent = defineAsyncComponent(() => import('../components/KPI.vue))

 

This means the code for the KPI component will be dynamically imported, as we saw in the router example. We can also provide some components to display while it’s in a loading or error state (useful if we’re loading a particularly large file).

const KPIComponent = defineAsyncComponent({
  loader: () => import('../components/KPI.vue),
  loadingComponent: Loader,
  errorComponent: Error,
  delay: 200,
  timeout: 5000,
});

Splitting API Requests 

Our application is primarily concerned with data visualization and relies heavily on fetching large amounts of data from the server. Some of these requests can be quite slow, as the server has to perform a number of computations on the data. In our initial prototype, we made a single request to the REST API per route. Unfortunately, we found this resulted in users having to wait a long time — sometimes up to 10 seconds, watching a loading spinner before the app successfully received the data and could begin rendering the visualizations.

We made the decision to split the API into several endpoints and make a request for each widget. While this could increase the response time overall, it means the app should become usable much quicker, as users will see parts of the page rendered while they’re still waiting for others. Additionally, any error that might occur will be localized while the rest of the page remains usable.

You can see the difference illustrated here:

Play: In the example on the right, the user can interact with some components while others are still requesting data. The page on the left has to wait for a large data response before it can be rendered and become interactive.

In the example on the right, the user can interact with some components while others are still requesting data. The page on the left has to wait for a large data response before it can be rendered and become interactive.

CONDITIONALLY LOAD COMPONENTS 

Now we can combine this with async components to only load a component when we’ve received a successful response from the server. Here we’re fetching the data, then importing the component when our fetch function returns successfully:

<template>
  <div>
    <component :is="KPIComponent" :data="data"></component>
  </div>
</template>

<script>
import {
  defineComponent,
  ref,
  defineAsyncComponent,
} from "vue";
import Loader from "./Loader";
import Error from "./Error";

export default defineComponent({
    components: { Loader, Error },

    setup() {
        const data = ref(null);

        const loadComponent = () => {
          return fetch('https://api.npoint.io/ec46e59905dc0011b7f4')
            .then((response) => response.json())
            .then((response) => (data.value = response))
            .then(() => import("../components/KPI.vue") // Import the component
            .catch((e) => console.error(e));
        };

        const KPIComponent = defineAsyncComponent({
          loader: loadComponent,
          loadingComponent: Loader,
          errorComponent: Error,
          delay: 200,
          timeout: 5000,
        });

        return { data, KPIComponent };
    }
}

 

To handle this process for every component, we created a higher order component called WidgetLoader, which you can see in the repository.

This pattern can be extended to any place in the app where a component is rendered upon user interaction. For example, in Windscope, we load a map component (and its dependencies) only when the user clicks on the ‘Map’ tab. This is known as Import on interaction.

CSS 

If you run the example code, you will see that clicking the ‘Locations’ navigation link loads the map component. As well as dynamically importing the JS module, importing the dependency within the component’s <style> block will lazyload the CSS too:

// In MapView.vue
<style>
@import "../../node_modules/leaflet/dist/leaflet.css";

.map-wrapper {
  aspect-ratio: 16 / 9;
}
</style>

 

REFINING THE LOADING STATE 

At this point, we have our API requests running in parallel, with components being rendered at different times. One thing we might notice is the page appears janky, as the layout will be shifting around quite a bit.

Play: Video

A quick way to make things feel a bit smoother for users is to set an aspect ratio on the widget that roughly corresponds to the rendered component so the user doesn’t see quite as big a layout shift. We could pass in a prop for this to account for different components, with a default value to fall back to.

// WidgetLoader.vue
<template>
  <div class="widget" :style="{ 'aspect-ratio': loading ? aspectRatio : '' }">
    <component :is="AsyncComponent" :data="data"></component>
  </div>
</template>

<script>
import { defineComponent, ref, onBeforeMount, onBeforeUnmount } from "vue";
import Loader from "./Loader";
import Error from "./Error";

export default defineComponent({
  components: { Loader, Error },

  props: {
    aspectRatio: {
      type: String,
      default: "5 / 3", // define a default value
    },
    url: String,
    importFunction: Function,
  },

  setup(props) {
      const data = ref(null);
      const loading = ref(true);

        const loadComponent = () => {
          return fetch(url)
            .then((response) => response.json())
            .then((response) => (data.value = response))
            .then(importFunction
            .catch((e) => console.error(e))
            .finally(() => (loading.value = false)); // Set the loading state to false
        };

    /* ...Rest of the component code */

    return { data, aspectRatio, loading };
  },
});
</script>

 

Aborting API Requests 

On a page with a large number of API requests, what should happen if the user navigates away before all the requests have been completed? We probably don’t want those requests to continue running in the background, slowing down the user experience.

We can use the AbortController interface, which enables us to abort API requests as desired.

In our setup function, we create a new controller and pass its signal into our fetch request parameters:

setup(props) {
    const controller = new AbortController();

    const loadComponent = () => {
      return fetch(url, { signal: controller.signal })
        .then((response) => response.json())
        .then((response) => (data.value = response))
        .then(importFunction)
        .catch((e) => console.error(e))
        .finally(() => (loading.value = false));
        };
}

 

Then we abort the request before the component is unmounted, using Vue’s onBeforeUnmount function:

onBeforeUnmount(() => controller.abort());

 

If you run the project and navigate to another page before the requests have been completed, you should see errors logged in the console stating that the requests have been aborted.

Stale While Revalidate 

So far, we’ve done a pretty good of optimizing our app. But when a user navigates to the second view and then back to the previous one, all the components remount and are returned to their loading state, and we have to wait for the request responses all over again.

Stale-while-revalidate is an HTTP cache invalidation strategy where the browser determines whether to serve a response from the cache if that content is still fresh or “revalidate” and serve from the network if the response is stale.

In addition to applying cache-control headers to our HTTP response (out of the scope of this article, but read this article from Web.dev for more detail), we can apply a similar strategy to our Vue component state, using the SWRV library.

First, we must import the composable from the SWRV library:

import useSWRV from "swrv";

 

Then we can use it in our setup function. We’ll rename our loadComponent function to fetchData, as it will only deal with data fetching. We’ll no longer import our component in this function, as we’ll take care of that separately.

We’ll pass this into the useSWRV function call as the second argument. We only need to do this if we need a custom function for fetching data (maybe we need to update some other pieces of state). As we’re using an Abort Controller, we’ll do this; otherwise, the second argument can be omitted, and SWRV will use the Fetch API:

// In setup()
const { url, importFunction } = props;

const controller = new AbortController();

const fetchData = () => {
  return fetch(url, { signal: controller.signal })
    .then((response) => response.json())
    .then((response) => (data.value = response))
    .catch((e) => (error.value = e));
};

const { data, isValidating, error } = useSWRV(url, fetchData);

 

Then we’ll remove the loadingComponent and errorComponent options from our async component definition, as we’ll use SWRV to handle the error and loading states.

// In setup()
const AsyncComponent = defineAsyncComponent({
  loader: importFunction,
  delay: 200,
  timeout: 5000,
});

 

This means we’ll need to include the Loader and Error components in our template and show and hide them depending on the state. The isValidating return value tells us whether there is a request or revalidation happening.

<template>
  <div>
    <Loader v-if="isValidating && !data"></Loader>
    <Error v-else-if="error" :errorMessage="error.message"></Error>
    <component :is="AsyncComponent" :data="data" v-else></component>
  </div>
</template>

<script>
import {
  defineComponent,
  defineAsyncComponent,
} from "vue";
import useSWRV from "swrv";

export default defineComponent({
  components: {
    Error,
    Loader,
  },

  props: {
    url: String,
    importFunction: Function,
  },

  setup(props) {
    const { url, importFunction } = props;

    const controller = new AbortController();

    const fetchData = () => {
      return fetch(url, { signal: controller.signal })
        .then((response) => response.json())
        .then((response) => (data.value = response))
        .catch((e) => (error.value = e));
    };

    const { data, isValidating, error } = useSWRV(url, fetchData);

    const AsyncComponent = defineAsyncComponent({
      loader: importFunction,
      delay: 200,
      timeout: 5000,
    });

    onBeforeUnmount(() => controller.abort());

    return {
      AsyncComponent,
      isValidating,
      data,
      error,
    };
  },
});
</script>

 

We could refactor this into its own composable, making our code a bit cleaner and enabling us to use it anywhere.

// composables/lazyFetch.js
import { onBeforeUnmount } from "vue";
import useSWRV from "swrv";

export function useLazyFetch(url) {
  const controller = new AbortController();

  const fetchData = () => {
    return fetch(url, { signal: controller.signal })
      .then((response) => response.json())
      .then((response) => (data.value = response))
      .catch((e) => (error.value = e));
  };

  const { data, isValidating, error } = useSWRV(url, fetchData);

  onBeforeUnmount(() => controller.abort());

  return {
    isValidating,
    data,
    error,
  };
}

 

// WidgetLoader.vue
<script>
import { defineComponent, defineAsyncComponent, computed } from "vue";
import Loader from "./Loader";
import Error from "./Error";
import { useLazyFetch } from "../composables/lazyFetch";

export default defineComponent({
  components: {
    Error,
    Loader,
  },

  props: {
    aspectRatio: {
      type: String,
      default: "5 / 3",
    },
    url: String,
    importFunction: Function,
  },

  setup(props) {
    const { aspectRatio, url, importFunction } = props;
    const { data, isValidating, error } = useLazyFetch(url);

    const AsyncComponent = defineAsyncComponent({
      loader: importFunction,
      delay: 200,
      timeout: 5000,
    });

    return {
      aspectRatio,
      AsyncComponent,
      isValidating,
      data,
      error,
    };
  },
});
</script>

 

UPDATING INDICATOR 

It might be useful if we could show an indicator to the user while our request is revalidating so that they know the app is checking for new data. In the example, I’ve added a small loading indicator in the corner of the component, which will only be shown if there is already data, but the component is checking for updates. I’ve also added a simple fade-in transition on the component (using Vue’s built-in Transition component), so there is not such an abrupt jump when the component is rendered.

<template>
  <div
    class="widget"
    :style="{ 'aspect-ratio': isValidating && !data ? aspectRatio : '' }"
  >
    <Loader v-if="isValidating && !data"></Loader>
    <Error v-else-if="error" :errorMessage="error.message"></Error>
    <Transition>
        <component :is="AsyncComponent" :data="data" v-else></component>
    </Transition>

    <!--Indicator if data is updating-->
    <Loader
      v-if="isValidating && data"
      text=""
    ></Loader>
  </div>
</template>

Conclusion 

Prioritizing performance when building our web apps improves the user experience and helps ensure they can be used by as many people as possible. We’ve successfully used the above techniques at Ada Mode to make our applications faster. I hope this article has provided some pointers on how to make your app as efficient as possible — whether you choose to implement them in full or in part.

SPAs can work well, but they can also be a performance bottleneck. So, let’s try to build them better.

Original article source at https://www.smashingmagazine.com

#vue #vuejs #javascript #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

How to Optimize the Performance of Vue.js Application?
Go Programming

Go Programming

1669013360

Everything You Need to Know about Go Programming (Handbook)

This handbook will introduce you to the Go programming language so you can get started coding in Go. You'll learn: How to get started with Go, How to install Go, How to setup your editor, How to write Hello, World! in Go, How to compile and run a Go program, The Go workspace, Diving into the Go language, Variables in Go, Basic types in Go, Strings in Go, Arrays in Go, Slices in Go, Maps in Go, Loops in Go, Conditionals in Go, Operators in Go, Structs in Go, Functions in Go, Pointers in Go, Methods in Go, Interfaces in Go, and more

Golang is an awesome, simple, modern, and fast programming language.

It’s compiled, open source, and strongly typed.

Golang – also called Go – was created by Google engineers with these main goals:

  • make their projects compile (and run) faster
  • be simple so people can pick it up in little time
  • be low level enough but also avoid some pitfalls of being too low level
  • be portable (compiled Go programs are binaries that do not require other files to run and are cross-platform, so they can be distributed easily)
  • be boring, stable, predictable, offer less opportunities to make mistakes
  • make it easy to take advantage of multiprocessor systems

Go was meant to be a replacement for C and C++ codebases. It aims to make some things simpler like concurrency and memory management, with garbage collection.

Also, it was built to work along with C and C++ codebases, thanks to its C interoperability features.

You can use Go for many different tasks, and it can solve both simple problems and very complex ones.

You can use Go to create command line utilities and networking servers, and it's widely used in many different scenarios.

For example, Docker and Kubernetes are written in Go.

My favorite Static Site Generator (Hugo) is written in Go.

Caddy, a quite popular web server, is written in Go.

There’s lots of different, widely used tools that use this programming language under the hood.

This handbook will introduce you to the Go programming language so you can get started coding in Go.

You can get a PDF and ePub version of this Go Beginner's Handbook here.

Table of Contents

  1. How to get started with Go
  2. How to install Go
  3. How to setup your editor
  4. How to write Hello, World! in Go
  5. How to compile and run a Go program
  6. The Go workspace
  7. Diving into the Go language
  8. Variables in Go
  9. Basic types in Go
  10. Strings in Go
  11. Arrays in Go
  12. Slices in Go
  13. Maps in Go
  14. Loops in Go
  15. Conditionals in Go
  16. Operators in Go
  17. Structs in Go
  18. Functions in Go
  19. Pointers in Go
  20. Methods in Go
  21. Interfaces in Go
  22. Where to go from here

How to Get Started with Go

Here are a few things you should know before we dive into the specifics of the language.

First, https://go.dev is the homepage of the language. This will be your go-to resource to:

…and more.

How to Install Go

Go to https://go.dev/doc/install and download the package for your Operating System.

Run the installer, and at the end of the process you will have the go command available in your terminal:

Screen Shot 2022-07-28 at 10.19.21.png

Welcome to the Go installerScreen Shot 2022-07-28 at 10.20.54.pngSuccessful installation modal

Open the terminal and run go version and you should see something like this:

Screen Shot 2022-07-28 at 10.21.32.png

Displaying the Go version you have

NOTE: you might have to open a new terminal before you can run the program, as the installer added the Go binaries folder to the path.

The exact location of the Go installation files will depend on your Operating System.

On macOS, it’s under /usr/local/go, with binaries in /usr/local/go/bin.

On Windows, it will be under C:\Program Files\go.

The Windows and Mac installers will set the Go binaries path automatically.

On a Mac you might also want to install Go via Homebrew using brew install golang. This will make it easier to update later.

On Linux you will have to add the Go binaries folder to your terminal path before you can run the go command after unpackaging the Linux package to /usr/local/go with this command:

echo 'export PATH=$PATH:/usr/local/go/bin' >> $HOME/.profile
source $HOME/.profile

How to Setup Your Editor

I recommend using Visual Studio Code (aka VS Code) as your editor.

Read Go in Visual Studio Code for a quick “up and running” setup. At the bare minimum, install the Go extension.

Screen Shot 2022-07-28 at 10.54.06.png

Go extension for VSCode

This extension will make your life easier, as it provides IntelliSense (syntax highlighting, autocompletion, on hover information, error highlighting…) and other things like auto formatting, menu options to install packages, testing, and more.

How to Write Hello, World! in Go

Now we’re ready to create our first Go program!

It’s a programmer's tradition to make the first program print the “Hello, World!” string to the terminal when it’s run. So we’ll do that first, and then we’ll explain how we did it.

Maybe you have a folder in your home directory where you keep all your coding projects and tests.

In there, create a new folder, for example call it hello.

In there, create a hello.go file (you can name it as you want).

Add this content:

package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}

Screen Shot 2022-07-28 at 12.17.14.png

Go "Hello, World!" code

This is your first Go program!

Let’s analyze this line by line.

package main

We organize Go programs in packages.

Each .go file first declares which package it is part of.

A package can be composed by multiple files, or just one file.

A program can contain multiple packages.

The main package is the entry point of the program and identifies an executable program.

import "fmt"

We use the import keyword to import a package.

fmt is a built-in package provided by Go that provides input/output utility functions.

We have a large standard library ready to use that we can use for anything from network connectivity to math, crypto, image processing, filesystem access, and more.

You can read about all the features that this fmt package provides on the official documentation.

func main() {
	
}

Here we declare the main() function.

What’s a function? We’ll see more about them later, but in the meantime let’s say a function is a block of code that’s assigned a name, and contains some instructions.

The main function is special because what’s where the program starts.

In this simple case we just have one function – the program starts with that and then ends.

fmt.Println("Hello, World!")

This is the content of the function we defined.

We call the Println() function defined in the fmt package we previously imported, passing a string as a parameter.

This function, according to the docs "formats according to a format specifier and writes to standard output”.

Take a look at the docs because they are great. They even have examples you can run:

Screen Shot 2022-07-28 at 14.18.46.png

Go basic function example

We use the “dot” syntax fmt.Println() to specify that the function is provided by that package.

After the code executes the main function, it has nothing else to do and the execution ends.

How to Compile and Run a Go program

Now open the terminal in the hello folder and run the program using:

go run hello.go

Screen Shot 2022-07-28 at 12.18.23.png

Hello world output in Go

Our program ran successfully, and it printed “Hello, World!” to the terminal.

The go run tool first compiles and then runs the program specified.

You can create a binary using go build:

go build hello.go

This will create a hello file that’s a binary you can execute:

Screen Shot 2022-07-28 at 12.19.50.png

Executable binary in Go

In the introduction I mentioned that Go is portable.

Now you can distribute this binary and everyone can run the program as-is, because the binary is already packaged for execution.

The program will run on the same architecture we built it on.

We can create a different binary for a different architecture using the GOOS and GOARCH environment variables, like this:

GOOS=windows GOARCH=amd64 go build hello.go

This will create a hello.exe executable for 64-bit Windows machines:

Screen Shot 2022-07-28 at 15.36.55.png

Hello.exe executable

Setup for 64-bit macOS (Intel or Apple Silicon) is GOOS=darwin GOARCH=amd64 and Linux is GOOS=linux GOARCH=amd64.

This is one of the best features of Go.

The Go Workspace

One special thing about Go is what we call the workspace.

The workspace is the “home base” for Go.

By default Go picks the $HOME/go path, so you will see a go folder in your home.

It’s first created when you install a package (as we’ll see later) but also to store some tooling.

For example the moment I loaded the hello.go file in VS Code, it prompted me to install the [gopls](https://pkg.go.dev/golang.org/x/tools/gopls) command, the Delve debugger (dlv), and the staticcheck linter.

They were automatically installed under $HOME/go:

Screen Shot 2022-07-28 at 12.27.27.png

$HOME/go

When you install packages using go install, they will be stored here.

This is what we call GOPATH.

You can change the GOPATH environment variable to change where Go should install packages.

This is useful when working on different projects at the same time and you want to isolate the libraries you use.

Diving into the Go Language

Now that we've got the first notions in place, and we ran our first Hello, World! program, we can dive into the language.

The language has no semantically significant whitespace. This is like C, C++, Rust, Java, JavaScript, but unlike Python, where whitespace is meaningful and is used to create blocks instead of curly brackets.

Semicolons are optional, like in JavaScript (unlike in C, C++, Rust or Java).

Go takes indentation and visual order very seriously.

When we install Go we also get access to the gofmt command line tool which we can use to format Go programs. VS Code uses that under the hood to format Go source files.

This is very interesting and innovative because formatting and issues like tabs vs spaces or “should I put the curly brackets on the same line of the loop definition or in the next line” are a huge waste of time.

The language creators defined the rules, and everyone uses those rules.

This is great for projects with large teams.

I recommend you enable in the VS Code Settings “Format on Save” and “Format on Paste”:

Screen Shot 2022-07-28 at 14.39.42.png

VS Code settings for Go - Format on Paste and Format on Save

You can write comments in Go using the usual C / C++ / JavaScript / Java syntax:

// this is a line comment

/*
multi
line
comment
*/

Variables in Go

One of the first things you do in a programming language is defining a variable.

In Go we define variables using var:

var age = 20

You can define variables at the package level:

package main

import "fmt"

var age = 20

func main() {
	fmt.Println("Hello, World!")
}

or inside a function:

package main

import "fmt"

func main() {
	var age = 20

	fmt.Println("Hello, World!")
}

Defined at the package level, a variable is visible across all the files that compose the package. A package can be composed of multiple files, you just need to create another file and use the same package name at the top.

Defined at the function level, a variable is visible only within that function. It’s initialized when the function is called, and destroyed when the function ends the execution.

In the example we used:

var age = 20

we assign the value 20 to age.

This makes Go determine that the type of the variable age is int.

We’ll see more about types later, but you should know there are many different ones, starting with int, string, and bool.

We can also declare a variable without an existing value, but in this case we must set the type like this:

var age int
var name string
var done bool

When you know the value, you typically use the short variable declaration with the := operator:

age := 10
name := "Roger"

For the name of the variable you can use letters, digits, and the underscore _ as long as the name starts with a character or _.

Names are case sensitive.

If the name is long, it’s common to use camelCase. So to indicate the name of the car we use carName.

You can assign a new value to a variable with the assignment operator =

var age int
age = 10
age = 11

If you have a variable that never changes during the program you can declare it as a constant using const:

const age = 10

You can declare multiple variables on a single line:

var age, name

and initialize them too:

var age, name = 10, "Roger"

//or

age, name := 10, "Roger"

Declared variables that are not used in the program raise an error and the program does not compile.

You will see a warning in VS Code:

Screen Shot 2022-07-28 at 15.45.31.png

Warning for unused declared variables

and the error from the compiler:

Screen Shot 2022-07-28 at 15.45.44.png

Error in compiler for unused declared variables

If you declare a variable without initializing it to a value, it is assigned a value automatically that depends on the type – for example an integer is 0 and a string is an empty string.

Basic Types in Go

Go is a typed language.

We saw how you can declare a variable, specifying its type:

var age int

Or you can let Go infer the type from the initial value assigned:

var age = 10

The basic types in Go are:

  • Integers (int, int8, int16, int32, rune, int64, uint, uintptr, uint8, uint16, uint64)
  • Floats (float32, float64), useful to represent decimals
  • Complex types (complex64, complex128), useful in math
  • Byte (byte), represents a single ASCII character
  • Strings (string), a set of bytes
  • Booleans (bool), either true or false

We have a lot of different types to represent integers. You will use int most of the time, and you might choose a more specialized one for optimization (not something you need to think about when you are just learning).

An int type will default to be 64 bits when used on a 64 bit system, 32 bits on a 32 bit system, and so on.

uint is an int that’s unsigned, and you can use this to double the amount of values you can store if you know the number is not going to be negative.

All the above basic types are value types, which means they are passed by value to functions when passed as parameters, or when returned from functions.

Strings in Go

A string in Go is a sequence of byte values.

As we saw above, you can define a string using this syntax:

var name = "test"

It’s important to note that unlike other languages, strings are defined only using double quotes, not single quotes.

To get the length of a string, use the built-in len() function:

len(name) //4

You can access individual characters using square brackets, passing the index of the character you want to get:

name[0] //"t" (indexes start at 0)
name[1] //"e"

You can get a portion of the string using this syntax:

name[0:2] //"te"
name[:2]  //"te"
name[2:]  //"st"

Using this you can create a copy of the string using:

var newstring = name[:]

You can assign a string to a new variable like this:

var first = "test"
var second = first

Strings are immutable, so you cannot update the value of a string.

Even if you assign a new value to first using an assignment operator, the value second is still going to be "test":

var first = "test"
var second = first

first = "another test"

first  //"another test"
second //"test"

Strings are reference types, which means if you pass a string to a function, the reference to the string will be copied, not its value. But since strings are immutable, in this case it’s not a big difference in practice with passing an int, for example.

You can concatenate two strings using the + operator:

var first = "first"
var second = "second"

var word = first + " " + second  //"first second"

Go provides several string utilities in the the strings package.

We already saw how to import a package in the “Hello, World!” example.

Here’s how you can import strings:

package main

import (
    "strings"
)

And then you can use it.

For example we can use the HasPrefix() function to see if a string starts with a specific substring:

package main

import (
    "strings"
)

func main() {
    strings.HasPrefix("test", "te") // true
}

You can find the full list of methods here: https://pkg.go.dev/strings.

Here’s a list of methods you might use frequently:

  • strings.ToUpper() returns a new string, uppercase
  • strings.ToLower() returns a new string, lowercase
  • strings.HasSuffix() checks if a string ends with a substring
  • strings.HasPrefix() checks if a string starts with a substring
  • strings.Contains() checks if a string contains a substring
  • strings.Count() counts how many times a substring appears in a string
  • strings.Join() used to join multiple strings and create a new one
  • strings.Split() used to create an array of strings from a string, dividing the original one on a specific character, like a comma or a space
  • strings.ReplaceAll() used to replace a portion in a string and replace it with a new one

Arrays in Go

Arrays are a sequence of items of a single type.

We define an array in this way:

var myArray [3]string //an array of 3 strings

and you can initialize the array with values using:

var myArray = [3]string{"First", "Second", "Third"}

In this case you can also let Go do some work and count the items for you:

var myArray = [...]string{"First", "Second", "Third"}

An array can only contain values of the same type.

The array cannot be resized – you have to explicitly define the length of an array in Go. That’s part of the type of an array. Also, you cannot use a variable to set the length of the array.

Due to this limitation, arrays are rarely used directly in Go. Instead we use slices (more on them later). Slices use arrays under the hood, so it’s still necessary to know how they work.

You can access an item in the array with the square brackets notation we already used in strings to access a single character:

myArray[0] //indexes start at 0
myArray[1]

You can set a new value for a specific position in the array:

myArray[2] = "Another"

And you can get the length of an array using the len() function:

len(myArray)

Arrays are value types. This means copying an array:

anotherArray := myArray

or passing an array to a function, or returning it from a function, creates a copy of the original array.

This is different from other programming languages out there.

Let’s make a simple example where we assign a new value to an array item after copying it. See, the copy doesn't change:

var myArray = [3]string{"First", "Second", "Third"}
myArrayCopy := myArray
myArray[2] = "Another"

myArray[2]     //"Another"
myArrayCopy[2] //"Third"

Remember you can only add a single type of items in an array, so setting the myArray[2] = 2 for example will raise an error.

Low-level elements are stored continuously in memory.

Slices in Go

A slice is a data structure similar to an array, but it can change in size.

Under the hood, slices use an array and they are an abstraction built on top of them that makes them more flexible and useful (think about arrays as lower level).

You will use slices in a way that’s very similar to how you use arrays in higher level languages.

You define a slice similarly to an array, omitting the length:

var mySlice []string //a slice of strings

You can initialize the slice with values:

var mySlice = []string{"First", "Second", "Third"}

//or

mySlice := []string{"First", "Second", "Third"}

You can create an empty slice of a specific length using the make() function:

mySlice := make([]string, 3) //a slice of 3 empty strings

You can create a new slice from an existing slice, appending one or more items to it:

mySlice := []string{"First", "Second", "Third"}

newSlice := append(mySlice, "Fourth", "Fifth")

Note that we need to assign the result of append() to a new slice, otherwise we’ll get a compiler error. The original slice is not modified – we’ll get a brand new one.

You can also use the copy() function to duplicate a slice so it does not share the same memory of the other one and is independent:

mySlice := []string{"First", "Second", "Third"}

newSlice := make([]string, 3)

copy(newSlice, mySlice)

If the slice you’re copying to does not have enough space (is shorter than the original) only the first items (until there’s space) will be copied.

You can initialize a slice from an array:

myArray := [3]string{"First", "Second", "Third"}

mySlice = myArray[:]

Multiple slices can use the same array as the underlying array:

myArray := [3]string{"First", "Second", "Third"}

mySlice := myArray[:]
mySlice2 := myArray[:]

mySlice[0] = "test"

fmt.Println(mySlice2[0]) //"test"

Those 2 slices now share the same memory. Modifying one slice modifies the underlying array and causes the other slice generated from the array to be modified, too.

As with arrays, each item in a slice is stored in memory in consecutive memory locations.

If you know you need to perform operations on the slice, you can request it to have more capacity than initially needed. This way, when you need more space, the space will be readily available (instead of finding and moving the slice to a new memory location with more space to grow and dispose via garbage collection of the old location).

We can specify the capacity by adding a third parameter to make():

newSlice := make([]string, 0, 10)
//an empty slice with capacity 10

As with strings, you can get a portion of a slice using this syntax:

mySlice := []string{"First", "Second", "Third"}

newSlice := mySlice[:2] //get the first 2 items
newSlice2 := mySlice[2:] //ignore the first 2 items
newSlice3 := mySlice[1:3] //new slice with items in position 1-2

Maps in Go

A map is a very useful data type in Go.

In other language it’s also called a dictionary or hash map or associative array.

Here’s how you create a map:

agesMap := make(map[string]int)

You don’t need to set how many items the map will hold.

You can add a new item to the map in this way:

agesMap["flavio"] = 39

You can also initialize the map with values directly using this syntax:

agesMap := map[string]int{"flavio": 39}

You can get the value associated with a key using:

age := agesMap["flavio"]

You can delete an item from the map using the delete() function in this way:

delete(agesMap, "flavio")

Loops in Go

One of Go’s best features is to give you fewer choices.

We have one loop statement: for.

You can use it like this:

for i := 0; i < 10; i++ {
	fmt.Println(i)
}

We first initialize a loop variable, then we set the condition we check for with each iteration to decide if the loop should end. Finally we have the post statement, executed at the end of each iteration, which in this case increments i.

i++ increments the i variable.

The < operator is used to compare i to the number 10 and returns true or false, determining if the loop body should be executed or not.

We don’t need parentheses around this block, unlike other languages like C or JavaScript.

Other languages offer different kind of loop structures, but Go only has this one. We can simulate a while loop, if you’re familiar with a language that has it, like this:

i := 0

for i < 10 {
	fmt.Println(i)
  i++
}

We can also completely omit the condition and use break to end the loop when we want:

i := 0

for {
	fmt.Println(i)

	if i < 10 {
		break
	}

  i++
}

I used a if statement inside the loop body, but we haven’t seen conditionals yet! We’ll do that next.

One thing I want to introduce now is range.

We can use for to iterate through an array using this syntax:

numbers := []int{1, 2, 3}

for i, num := range numbers {
	fmt.Printf("%d: %d\n", i, num)
}

//0: 1
//1: 2
//2: 3

Note: I used fmt.Printf() which allows us to print any value to the terminal using the verbs %d which mean decimal integer and \n means add a line terminator.

It’s common to use this syntax when you don’t need to use the index:

for _, num := range numbers {
  //...
}

We're using the special _ character that means “ignore this” to avoid the Go compiler raising an error saying “you’re not using the i variable!”.

Conditionals in Go

We use the if statement to execute different instructions depending on a condition:

if age < 18 {
	//underage
}

The else part is optional:

if age < 18 {
	//underage
} else {
  //adult
}

and can be combined with other ifs:

if age < 12 {
	//child
} else if age < 18  {
  //teen
} else {
	//adult
}

If you define any variable inside the if, that’s only visible inside the if (same applies to else and anywhere you open a new block with {}).

If you’re going to have many different if statements to check a single condition, it’s probably better to use switch:

switch age {
case 0: fmt.Println("Zero years old")
case 1: fmt.Println("One year old")
case 2: fmt.Println("Two years old")
case 3: fmt.Println("Three years old")
case 4: fmt.Println("Four years old")
default: fmt.Println(i + " years old")
}

Compared to C, JavaScript, and other languages, you don’t need to have a break after each case.

Operators in Go

We've used some operators so far in our code examples, like =, := and <.

Let’s talk a bit more about them.

We have assignment operators = and := we use to declare and initialize variables:

var a = 1

b := 1

We have comparison operators == and != that take 2 arguments and return a boolean:

var num = 1
num == 1 //true
num != 1 //false

and <, <=, >, >=:

var num = 1
num > 1 //false
num >= 1 //true
num < 1 //false
num <= 1 //true

We have binary (require two arguments) arithmetic operators, like +, -, *, /, %.

1 + 1 //2
1 - 1 //0
1 * 2 //2
2 / 2 //1
2 % 2 //0

+ can also join strings:

"a" + "b" //"ab"

We have unary operators ++ and -- to increment or decrement a number:

var num = 1
num++ // num == 2
num-- // num == 1

Note that unlike C or JavaScript we can’t prepend them to a number like ++num. Also, the operation does not return any value.

We have boolean operators that help us with making decisions based on true and false values: &&, || and !:

true && true  //true
true && false //false
true || false //true
false || false //false
!true  //false
!false //true

Those are the main ones.

Structs in Go

A struct is a type that contains one or more variables. It’s like a collection of variables. We call them fields. And they can have different types.

Here’s an example of a struct definition:

type Person struct {
	Name string
	Age int
}

Note that I used uppercase names for the fields, otherwise those will be private to the package. And when you pass the struct to a function provided by another package, like the ones we use to work with JSON or database, those fields cannot be accessed.

Once we define a struct we can initialize a variable with that type:

flavio := Person{"Flavio", 39}

and we can access the individual fields using the dot syntax:

flavio.Age //39
flavio.Name //"Flavio"

You can also initialize a new variable from a struct in this way:

flavio := Person{Age: 39, Name: "Flavio"}

This lets you initialize only one field, too:

flavio := Person{Age: 39}

or even initialize it without any value:

flavio := Person{}

//or

var flavio Person

and set the values later:

flavio.Name = "Flavio"
flavio.Age = 39

Structs are useful because you can group unrelated data and pass it around to/from functions, store in a slice, and more.

Once defined, a struct is a type like int or string and this means you can use it inside other structs, too:

type FullName struct {
	FirstName string
	LastName string
}

type Person struct {
	Name FullName
	Age int
}

Functions in Go

A function is a block of code that’s assigned a name, and contains some instructions.

In the “Hello, World!” example we created a main function, which is the entry point of the program.

package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}

That’s a special function.

Usually we define functions with a custom name:

func doSomething() {

}

and then you can call them, like this:

doSomething()

A function can accept parameters, and we have to set the type of the parameters like this:

func doSomething(a int, b int) {

}

doSomething(1, 2)

a and b are the names we associate to the parameters internally to the function.

A function can return a value, like this:

func sumTwoNumbers(a int, b int) int {
	return a + b
}

result := sumTwoNumbers(1, 2)

Note that we specified the return value type.

A function in Go can return more than one value:

func performOperations(a int, b int) (int, int) {
	return a + b, a - b
}

sum, diff := performOperations(1, 2)

It’s interesting because many languages only allow one return value.

Any variable defined inside the function is local to the function.

A function can also accept an unlimited number of parameters, and in this case we call it a variadic function:

func sumNumbers(numbers ...int) int {
	sum := 0
	for _, number := range numbers {
		sum += number
	}
	return sum
}

total := sumNumbers(1, 2, 3, 4)

Pointers in Go

Go supports pointers.

Suppose you have a variable:

age := 20

Using &age you get the pointer to the variable, its memory address.

When you have the pointer to the variable, you can get the value it points to by using the * operator:

age := 20
ageptr = &age
agevalue = *ageptr

This is useful when you want to call a function and pass the variable as a parameter. Go by default copies the value of the variable inside the function, so this will not change the value of age:

func increment(a int) {
	a = a + 1
}

func main() {
	age := 20
	increment(age)

	//age is still 20
}

You can use pointers for this:

func increment(a *int) {
	*a = *a + 1
}

func main() {
	age := 20
	increment(&age)

	//age is now 21
}

Methods in Go

You can assign a function to a struct, and in this case we call it a method.

Example:

type Person struct {
	Name string
	Age int
}

func (p Person) Speak() {
	fmt.Println("Hello from " + p.Name)
}

func main() {
	flavio := Person{Age: 39, Name: "Flavio"}
	flavio.Speak()
}

You can declare methods to be pointer receiver or value receiver.

The above example shows a value receiver. It receives a copy of the struct instance.

This would be a pointer receiver that receives the pointer to the struct instance:

func (p *Person) Speak() {
	fmt.Println("Hello from " + p.Name)
}

Interfaces in Go

An interface is a type that defines one or more method signatures.

Methods are not implemented, just their signature: the name, parameter types and return value type.

Something like this:

type Speaker interface {
	Speak()
}

Now you could have a function accept any type that implements all the methods defined by the interface:

func SaySomething(s Speaker) {
	s.Speak()
}

And we can pass it any struct that implements those methods:

type Speaker interface {
	Speak()
}

type Person struct {
	Name string
	Age int
}

func (p Person) Speak() {
	fmt.Println("Hello from " + p.Name)
}

func SaySomething(s Speaker) {
	s.Speak()
}

func main() {
	flavio := Person{Age: 39, Name: "Flavio"}
	SaySomething(flavio)
}

Where to Go from Here

This handbook is an introduction to the Go programming language.

Beside these basics, there are many things to learn now.

Garbage collection, error handling, concurrency and networking, the filesystem APIs, and much more.

The sky is the limit.

My suggestion is to pick a program you want to build and just start, learning the things you need along the way.

It will be fun and rewarding.

Note: you can get a PDF and ePub version of this Go Beginner's Handbook here.

Original article source at https://www.freecodecamp.org

#go #golang #programming #developer #softwaredeveloper #computerscience 

Everything You Need to Know about Go Programming (Handbook)
Riley Lambert

Riley Lambert

1669011955

Everything You Need to Know about Python Programming (Free Book)

Learn Python programming with Free Book, you'll learn: Python Basics, Operators in Python, Data types in Python, Tuples in Python, Dictionaries in Python, Sets in Python, Type Conversions in Python, Control Flow in Python, Functions in Python, Object Oriented Programming in Python, Importing in Python, How to Handle Exceptions in Python, User Input in Python, and more

Python is one of the most popular programming languages in the world today. It was created in 1991 by Guido van Rossum.

According to van Rossum, Python is a:

“high-level programming language, and its core design philosophy is all about code readability and a syntax which allows programmers to express concepts in a few lines of code.”

Benefits of Learning Python

Python is one of the easiest languages that you can learn and work with. You can use it for software development, server side of web development, machine learning, mathematics, and any type of scripting that you can think of.

The good thing about Python is that it is widely used and accepted by many companies and academic institutions. This makes it a really good choice, especially if you are just starting your coding journey.

Python also has a large community of developers that use it and are willing to help you if you get stuck or have questions. This community has already published many open source libraries that you can start using. They also actively keep improving them.

Python's syntax is quite similar to that of the English language, which makes it easier for you to understand and use quite intuitively.

Python runs on an interpreter system, meaning that you don't have to wait for a compiler to compile the code and then execute it. You can instead build prototypes quickly.

It also works on different platforms, such as Windows, Linux, Mac, Rapsberry Pi, and so on.

So you see – it's a great programming language, whether you're just starting out or you're looking to add another useful tool to your kit.

Here's what we'll cover in this book:

Table of Contents

  • Python Basics
  • Operators in Python
  • Data types in Python
  • Tuples in Python
  • Dictionaries in Python
  • Sets in Python
  • Type Conversions in Python
  • Control Flow in Python
  • Functions in Python
  • Object Oriented Programming in Python
  •  
  • Importing in Python
  • How to Handle Exceptions in Python
  • User Input in Python
  • Get the PDF version of the book

Python Basics

Indentation in Python

Compared to other languages, Python places special importance on indentation.

In other programming languages, white spaces and indentations are only used to make the code more readable and prettier. But in Python, they represent a sub-block of code.

The following code is not going to work, since the second line is not properly intended:

if 100 > 10:
  print("100 is greater than 10")

For it to work properly, the indentation should look like the following:

if 100 > 10:
    print("100 is greater than 10")

This may look hard to understand, but you can use a code editor that highlights such syntax errors quite vividly. Moreover, the more Python code you write, the easier it gets for you to consider such indentations as second nature.

Python uses four spaces for proper indentation by default.

Comments in Python

We use comments to specify parts of the program that should be simply ignored and not executed by the Python interpreter. This means that everything written inside a comment is not taken into consideration at all and you can write in any language that you want, including your own native language.

In Python, you start a comment with the symbol # in front of the line:

# This is a comment in Python

You can also include more extended comments in multiple lines using triple quotes:

"""
This is a comment in Python.
Here we are typing in another line and we are still inside the same comment block.

In the previous line we have a space, because it's allowed to have spaces inside comments.

Let's end this comment right here.
"""

print() method in Python

We are going to use the method print() since it helps us see results in the console.

You do not need to know how it works behind the scenes or even know what a method is right now. Just think of it as a way for us to display results from our code in the console.

Operators in Python

Arithmetic operators in Python

Even though you can just pull out your phone from your pocket and do some calculations, you should also get used to implementing some arithmetic operators in Python.

When we want to add two numbers, we use the plus sign, just like in math:

print(50 + 4)  # 54

Similarly, for subtraction, we use the minus sign:

print(50 - 4)  # 46

For multiplication, we use the star or asterisk:

print(50 * 4)  # 200

When doing divisions, we use the forward slash:

print(50 / 4)  # 12.5
print(8 / 4)  # 2.0

This often results in float numbers (numbers with a decimal point, that is, not a round number). If we want to only get integer numbers when doing division, that's called floor division. In that case, we should use the double forward slashes like this:

print(50 // 4)  # 12
print(8 / 4)  # 2

We can also find the remainder of a number divided by another number using the percent sign %:

print(50 % 4)  # 2

This operation can be helpful especially in cases when we want to check whether a number is odd or even. A number is odd if, when divided by 2, the remainder is 1. Otherwise, it is even.

Here is an illustration:

print(50 % 4)  # 2
# Since the remainder is 2, this number is even

print(51 % 4)  # 3
#Since the remainder is 3, this number is odd

When we want to raise a number to a specific power, we use the double asterisk:

print(2 ** 3)  # 8
# This is a short way of writing 2 * 2 * 2

print(5 ** 4)  # 625
# This is a short way of writing 5 * 5 * 5 * 5

Assignment operators in Python

You use these operators to assign values to variables.

When we declare a variable, we use the equal sign:

name = "Fatos"
age = 28

We can also declare multiple variables in the same line:

name, age, location = "Fatos", 28, "Europe"

We can use this as a way to also swap values between variables. For example, let's say that we have two variables a and b and we want to switch their values.

One logical way to do that would be to introduce a third variable that serves as a temporary variable:

a, b = 1, 2

print(a)  # 1
print(b)  # 2

c = a
a = b
b = c

print(a)  # 2
print(b)  # 1

We can do that in a single line in the following way:

a, b = 1, 2

print(a)  # 1
print(b)  # 2

b, a = a, b

print(a)  # 2
print(b)  # 1

We can also merge the assignment operators with arithmetic operators.

Let's see how we can do that for addition first.

Let's assume that we have the following variables:

total_sum = 20

current_sum = 10

Now we want to add the value of the current_sum to total_sum. To do that, we should write the following:

total_sum = total_sum + current_sum

print(total_sum)  # 30

This may not look accurate, since the right hand side is not equal to the left hand side. However, in this case we are simply doing an assignment and not a comparison of both sides of the equation.

To do this quickly, we can use the following form:

total_sum += current_sum

print(total_sum)  # 30

This is equivalent to the previous statement.

Similarly, we can do the same with other arithmetic operators:

Subtraction:

result = 3
number = 4

result -= number  # This is equal to result = result - number

print(result)  # -1

Multiplication:

product = 3
number = 4

product *= number  # This is equal to product = product * number

print(product)  # 12

Division:

result = 8
number = 4

result /= number  # This is equal to result = result / number

print(result)  # 2.0

Modulo operator:

result = 8
number = 4

result %= number  # This is equal to result = result % number

print(result)  # 0

Power operator:

result = 2
number = 4

result **= number  # This is equal to result = result ** number

print(result)  # 16

Comparison operators in Python

You likely learned how to do basic comparisons of numbers in school, such as checking whether a specific number is larger than another number, or whether they are equal.

We can use almost the same operators in Python to do such comparisons.

Let's see them in action.

Equality operators

You can check whether two numbers are equal using the == operator:

print(2 == 3)  # False 

The last expression evaluates to False since 2 is not equal to 3.

There is another operator that you can use to check whether 2 numbers are not equal. This is an operator that you may have not have seen in your math classes written exactly in this way. This is the operator !=.

Let's do a comparison of whether 2 is not equal to 3:

print(2 != 3)  # True

This expression evaluates to True since 2 is indeed not equal to 3.

Inequality operators

Now here we are going to see how to check whether a number is larger than another number:

print(2 > 3)  # False

This is something that you should already know from your math classes.

When trying to check whether a number is greater than or equal to another number, we need to use this operator >=:

print(2 >= 3)  # False

Similarly, to check whether a number is less than or equal to another, we have:

print(2 < 3)  # True
print(2 <= 3)  # True

Logical operators

In high school math, you may have learned about logical operators such as and and or.

Briefly speaking, for an expression to evaluate to True when using and, both statements should be true. In Python, we implement it using and:

print(5 > 0 and 3 < 5)  # True

This example is going to evaluate to True since 5 is greater than 0, which evaluates to True, and 3 is less than 5, which also evaluates to True. From this we get True and True, which evaluates to True.

Let's take an example when an and expression is going to evaluate to False:

print(2 > 5 and 0 > -1)  # False

2 is not greater than 5, so the statement in the left hand side is going to evaluate to False. No matter what's on the right hand side, we are going to get the whole expression equal to False, since False and any other value (like True) are going to result in False.

When you have statements where at least one of them should evaluate to True, then we should use the or operator:

print(2 > 5 or 0 > -1)  # True

This is going to evaluate to True since the statement in the right hand side evaluates to True – so at least one of them is true.

If both statements are False, then or results in False in the end:

print(2 < 0 or 0 > 1)  # False

This is False since 0 is not greater than 2 and also 0 is not greater than 1. So the whole expression is False.

Data Types in Python

Variables in Python

You can think about variables as the building blocks of any computer program that you might write.

You can use variables to store values and then reuse them as many times as you want. The moment you want to change a value, you can just change it in one place and that new value that you just changed is going to get reflected everywhere else where that variable is used.

Every variable in Python is an object.

A variable is created in the moment it is initialized with a value.

Here are the general rules for Python variables:

  • A variable name must start with a letter or the underscore character. It cannot start with a number.
  • A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ ).
  • Variable names are case-sensitive, meaning that height, Height, and HEIGHT are all different variables.

Let's define our first variable:

age = 28

In this example, we are initializing a variable with the name age and assigning the value 28 to it.

We can define other variables along with it, like:

age = 28
salary = 10000

We can use pretty much any name that we want, but it is a better practice to use names that both you and other any colleagues who work with you can understand.

We have other variable types in Python, such as float numbers, strings, and boolean values. We can even create our own custom types.

Let's see an example of a variable that holds a float number:

height = 3.5

As you can see, this initialization is quite similar to the ones when we had integer numbers. Here we are only changing the value on the right. The Python interpreter is smart enough to know that we are dealing with another type of variable, namely a float type of variable.

Let's see an example of a string:

reader = "Fatos"

We put string values either in double quotes or single quotes to specify the value that we want to store in string variables.

When we want to store boolean values, we need to use reserved words, namely, True and False.

text_visibile = False

We can also have a boolean value stored when we have expressions that result with a boolean value, for example, when we compare a number with another number, such as:

is_greater = 5 > 6

This variable is going to get initialized with the value False since 5 is lower than 6.

Numbers in Python

We have three numeric types in Python: integers, floats, and complex numbers.

Integers

Integers represent whole numbers that can be both positive and negative and do not contain any decimal part.

Here are a few examples of integers: 1, 3000, -31234, and so on.

When adding, subtracting, or multiplying two integers, we get an integer as a result in the end.

print(3 + 5)  # 8
print(3 - 5)  # -2
print(3 * 5)  # 15

These are all integers.

This also includes cases when we raise a number to a power:

result = 3 ** 4  # This is similar to multiplying 3 * 3 * 3 * 3 in which case, we are multiplying integers together
print(result)  # 81

When we want to divide two integers, we are going to get a float number.

Booleans

The boolean type represents truth values, True and False. You learned the explanation of this type in the Numbers section, since booleans are indeed subtypes of the integer type.

More specifically, almost always a False value can be considered as a 0, whereas a True value can be considered as a 1.

As such, we can also do arithmetic operations with them:

print(True * 5)  # 5
print(False * 500)  # 0, since False is equal to 0

The exception for such integer representations of Boolean values is when these values are strings such as "False" and "True".

Floats

Float numbers are numbers that contain the decimal part, such as -3.14, 12.031, 9.3124, and so on.

We can also convert to float numbers using the float() function:

ten = float(10)

print(ten)  # 10.0

When adding, subtracting, or dividing two float numbers, or a float number and an integer, we get a float number as a result in the end:

print(3.4 * 2)  # 6.8
print(3.4 + 2)  # 5.4
print(3.4 - 2)  # 1.4
print(2.1 * 3.4)  # 7.14

Complex numbers

Complex numbers have both the real and the imaginary part that we write in the following way:

complex_number = 1 + 5j

print(complex_number)  # (1+5j)

Strings in Python

Strings represent characters that are enclosed in either single quotes or double quotes. Both of them are treated the same:

name = "Fatos"  # Double quotes

name = 'Fatos'  # Single quotes

If we want to include a quote inside a string, we need to let Python know that it should not close the string but simply escape that quote:

greeting = 'Hello. I\'m fine.'  # We escaped the apostrophe in I'm.

double_quote_greeting = "Hello. I'm fine."  # When using double quotes, we do not need to escape the apostrophe

When we want to include a new line in a string, we can include the special character \n:

my_string = "I want to continue \n in the next line"

print(my_string) 
# I want to continue 
# in the next line 

Since strings are arrays of characters, we can index specific characters using indexes. Indexes start from 0 and go all the way until the length of the string minus 1.

We exclude the index that is equal to the length of the string since we start indexing from 0 and not from 1.

Here is an example:

string = "Word"

In this example, if we were to select individual characters of the string, they would unfold as follows:

string = "Word"

print(string[0])  # W
print(string[1])  # o
print(string[2])  # r
print(string[3])  # d

We can use negative indexes as well, which means that we start from the end of the string with -1. We cannot use 0 to index from the end of a string, since -0 = 0:

print(string[-1])  # d
print(string[-2])  # r
print(string[-3])  # o
print(string[-4])  # W

We can also do slicing and include only a portion of the string and not the entire string. For example, if we want to get characters that start from a specific index until a specific index, we should write it in the following way: string[start_index:end_index], excluding the character at index end_index:

string = "Word"

print(string[0:3])  # Wor

If we want to start from a specific index and continue getting all the remaining characters of the string until the end, we can omit specifying the end index, as follows:

string = "Word"

print(string[2:])  # rd

If we want to start from 0 and go until a specific index, we can simply specify the ending index:

string = "Word"

print(string[:2])  # Wo

This means that the value of string is equal to string[:2] (excluding the character at position 2) + string[2:].

Note that strings in Python are immutable. This means that once a string object has been created, it cannot be modified, such as trying to change a character in a string.

As an illustration, let's say that we want to change the first character in the string, namely switching W with A in the following way:

string = "Word"
string[0] = "A"

Now, if we try to print string, we would get an error like the following:

# TypeError: 'str' object does not support item assignment

If we need a new string, we should simply create a new one.

String operators

We can concatenate strings using the + operator:

first = "First"
second = "Second"

concantenated_version = first + " " + second

print(concatenated_version)  # First Second

We can use the multiplication operator * with strings and numbers.

You can use this to repeat the string that many times. For example, if we want to repeat a string 5 times, but we do not want to write it manually five times, we can simply multiply it with the number 5:

string = "Abc"

repeated_version = string * 5

print(repeated_version)  # AbcAbcAbcAbcAbc

String built-in methods

There are a few built-in methods of strings that we can use that can make it easier for us to manipulate with them.

len() method

len() is a method that we can use to get the length of a string:

sentence = "I am fine."

print(len(sentence))  # 10

replace() method

We can use replace() to replace a character or a substring of a string with another character or substring:

string = "Abc"

modified_version = string.replace("A", "Z")

print(modified_version)  # Zbc

strip() method

strip() removes white spaces that can be in the beginning or at the end of a string:

string = " Hi there "

print(string.strip())  # Hi there

split() method

We can use split() to convert a string into an array of substrings based on a specific pattern that is mentioned as the separator.

For example, let's assume that we want to save all words of a sentence in an array of words. These words are separated by white spaces, so we will need to do the splitting based on that:

sentence = "This is a sentence that is being declared here"

print(string.split(" ")) 
# ['This', 'is', 'a', 'sentence', 'that', 'is', 'being', 'declared', 'here']

join() method

join() is the opposite of split(): from an array of strings, it returns a string. The process of concatenation is supposed to happen with a specified separator in between each element of the array that in the end results in a single concatenated string:

words = ["cat", "dog", "rabbit"]

print(" - ".join(words))  # cat - dog - rabbit

count() method

We can use count() to count the number of times a character or a substring appears in a string:

string = "Hi there"
 
print(string.count("h"))  # 1, since, it is case sensitive and 'h' is not equal to 'H'

print(string.count("e"))  # 2

print(string.count("Hi"))  # 1

print(string.count("Hi there"))  # 1

find() method

find() lets us find a character or a substring in a string and returns the index of it. In case it does not find it, it will simply return -1:

string = "Hi there"

print(string.find("3"))  # -1

print(string.find("e"))  # 5

print(string.find("Hi"))  # 0

print(string.find("Hi there"))  # 0

lower()

lower() converts all characters of a string into lower case:

string = "Hi there"

print(string.lower())  # hi there

upper()

upper() converts all characters of a string into lower case:

string = "Hi there"

print(string.upper())  # HI THERE

capitalize() method

We can use capitalize() to covert the first character of a string into uppercase:

string = "hi there"

print(string.capitalize())  # Hi there

title() method

title() converts starting characters of each word (sequences that are separated by white spaces) of a string into uppercase:

string = "hi there"

print(string.title())  # Hi There

isupper() method

isupper() is a method that we can use to check whether all characters in a string are upper case:

string = "are you HERE"
another_string = "YES"

print(string.isupper())  # False
print(another_string.isupper())  # True

islower() method

islower() similarly checks whether all characters are lower case:

string = "are you HERE"
another_string = "no"

print(string.islower())  # False
print(another_string.islower())  # True

isalpha() method

isalpha() returns True if all characters in a string are letters of the alphabet:

string = "A1"
another_string = "aA"

print(string.isalpha())  # False, since it contains 1
print(another_string.isalpha())  # True since both `a` and `A` are letters of the alphabet

isdecimal() method

isdecimal() returns True if all characters in a string are numbers:

string = "A1"
another_string = "3.31"
yet_another_string = "3431"

print(string.isdecimal())  # False, since it contains 'A'
print(another_string.isdecimal())  # False, since it contains '.'
print(yet_another_string.isdecimal())  # True, since it contains only numbers

String Formatting

Formatting a string can be quite useful since you may be using it quite frequently no matter the type of project or script that you are working on.

Let's first illustrate why we need formatting and include string interpolation.

Imagine that I want to develop a software that greets people the moment they come in, such as:

greeting = "Good morning Fatos."

This now looks great, but I am not the only person who uses it, right?

I am just one of the people who gets to use it.

Now if someone comes and signs in, I will have to use their own names, such as:

greeting = "Good morning Besart."

This is just my first real user who is registering. I am not counting myself.

Now let's think that I get lucky and the second user also pops in on a Friday morning and our application should display:

greeting = "Good morning Betim."

As you can see, we are getting somewhere from a business perspective since two new users just showed up, but this is not a scalable implementation. We are writing a very static greeting expression.

You should already remember that we are about to mention something that I introduced back at the beginning.

Yes, we will need to use variables and include a variable next to the string, as follows:

greeting = "Good morning " + first_name

This is much more flexible.

This is one way of doing that.

Another way you can do this is using a method called format().

We can use curly braces to specify places where we want to put dynamic values, such as the following:

greeting = "Good morning {}. Today is {}.".format("Fatos", "Friday")

This is now going to put the first parameter of the method  format() inside the first curly braces, which in our case is Fatos. Then, in the second occurrence of the curly braces, it is going to put the second parameter of the method format().

If we try to print the value of the string, we should get the following:

print(greeting)
# Good morning Fatos. Today is Friday.

We can specify parameters with indexes inside curly braces like the following that can then be used:

greeting = "Today is {1}. Have a nice day {0}".format("Fatos", "Friday")

print(greeting)
# greeting = "Today is {1}. Have a nice day {0}.".format("Fatos", "Friday")

We can also specify parameters inside the format() method and use those specific words inside curly braces as a reference:

greeting = "Today is {day_of_the_week}. Have a nice day {first_name}.".format(first_name="Fatos",
                                                                              day_of_the_week="Friday")
print(greeting)  # Today is Friday. Have a nice day Fatos.

We can combine both types of arguments in a single example, such as the following:

short_bio = 'My name is {name}. My last name is {0}. I love {passion}. I like playing {1}.'.format(
    'Morina',
    'Basketball',
    name='Fatos',
    passion='Programming'
)

print(short_bio)
# My name is Fatos. My last name is Morina. I love Programming. I like playing Basketball.

As you can see, using named arguments as opposed to positional ones can be less error-prone, since their ordering in the format() method does not matter.

We can also use another way of formatting strings which consists of beginning a string with f or F before the opening quotation marks or triple quotation marks and including names of the variables that we want to be included in the end:

first_name = "Fatos"
day_of_the_week = "Friday"
continent = "Europe"

greeting = f'Good morning {first_name}. Today is {day_of_the_week}'

print(greeting)  # Good morning Fatos. Today is Friday.

Here is another example where we are using a triple quotient after the F:

continent = "Europe"

i_am_here = F'''I am in {continent}'''

print(i_am_here)  # I am in Europe

Lists in Python

If you take a look at a bookshelf, you can see that the books are stacked and put closely together. You can see that there are many examples of collecting, and structuring elements in some way.

This is also quite important in computer programming. We cannot just continue declaring countless variables and manage them that easily.

Let's say that we have a class of students and want to save their names. We can start saving their names according to the way they are positioned in the classroom:

first = "Albert"
second = "Besart"
third = "Fisnik"
fourth = "Festim"
fifth = "Gazmend"

The list can keep on going which will make it quite hard for us to keep track of all of them.

There is fortunately an easier way for us to put these in a collection in Python called a list.

Let's create a list called students and store in that list all the names declared in the previous code block:

students = ["Albert", "Besart", "Fisnik", "Festim", "Gazmend"]

This is prettier, right?

Moreover, this way, it is easier for us to manage and also manipulate the elements in the list.

You may think that, "Well it was easier for me to just call first and get the value stored in there. Now it is impossible to get a value from this new list, called students".

If we couldn't read and use those elements that we just stored in a list, that would make it less helpful.

Fortunately, lists have indexes, which start from 0. This means that if we want to get the first element in a list, we need to use index 0 and not index 1 as you may think.

In the example above, the list items have these corresponding indexes:

students = ["Albert", "Besart", "Fisnik", "Festim", "Gazmend"]
# Indexes 0, 1, 2, 3, 4 

Now, if we want to get the first element, we simply write:

students[0]

If we want to get the second element, we just write:

students[1]

As you can probably see, we simply need to write the name of the list and also the corresponding index of the element that we want to get in the square brackets.

This list is, of course, not static. We can add elements to it, like when a new student joins the class.

Let's add a new element in the list students with the value Besfort:

students.append("Besfort")

We can also change the value of an existing element. To do that, we need to simply reinitialize that specific element of the list with a new value.

For example, let's change the name of the first student:

students[0] = "Besim"

Lists can contain contain different types of variables, for example, we can have a string that contains integers, float numbers, and strings:

combined_list = [3.14, "An element", 1, "Another element here"]

Slicing

Similar to strings, lists can also be sliced, which as a result returns a new list. This means that the original list remains unchanged.

Let's see how we can get the first three elements of a list using slicing:

my_list = [1, 2, 3, 4, 5]

print(my_list[0:3])  # [1, 2, 3]

As you can see, we have specified 0 as the starting index and 3 as the index where the slicing should stop, excluding the element at the ending index.

If we want to simply start from an index and get all the remaining elements in the list, meaning that the end_index should be the last index, then we can omit and not have to write the last index at all:

my_list = [1, 2, 3, 4, 5]

print(my_list[3:])  # [4, 5]

Similarly, if we want to start from the beginning of the list and do the slicing until a specific index, then we can omit writing the 0 index entirely, since Python is smart enough to infer that:

my_list = [1, 2, 3, 4, 5]

print(my_list[:3])  # [1, 2, 3]

Strings in Python are immutable, whereas lists are mutable, meaning that we can modify lists' content after we declare them.

As an illustration, let's say that we want to change the first character in the string, namely switching S with B in the following way:

string = "String"
string[0] = "B"

Now, if we try to print string, we would get an error like the following:

# TypeError: 'str' object does not support item assignment

Now if we have a list and want to modify its first element, then we can successfully do so:

my_list = ["a", "b", "c", "d", "e"]

my_list[0] = 50

print(my_list)  # [50, 'b', 'c', 'd', 'e']

We can expand a list by concatenating it with another list using the + operator:

first_list = [1, 2, 3]

second_list = [4, 5]

first_list = first_list + second_list 

print(first_list)  # [1, 2, 3, 4, 5]

How to nest a list inside another list

We can nest a list inside another list like this:

math_points = [30, "Math"]

physics_points = [53, "Phyiscs"]

subjects = [math_points, physics_points]

print(subjects)  # [[30, 'Math'], [53, 'Phyiscs']]

These lists do not need even have to have the same length.

To access elements of a list which is inside a list we need to use double indexes.

Let's see how we can access the element math_points inside the subjects list. Since math_points is an element in the subjects list positioned at index 0, we simply need to do the following:

print(subjects[0])  # [30, 'Math']

Now let's assume that we want to access Math inside the subjects list. Since Math is at index 1, we are going to need to use the following double indexes:

print(subjects[0][1])  # 'Math'

List methods

len() is a method that you can use to find the length of a list:

my_list = ["a", "b", 1, 3]

print(len(my_list))  # 4

How to add elements to a list

We can also expand lists by adding new elements, or we can also delete elements.

We can add new elements at the end of a list using the append() method:

my_list = ["a", "b", "c"]

my_list.append("New element")

my_list.append("Yet another new element")

print(my_list)  
# ['a', 'b', 'c', 'New element', 'Yet another new element']

If we want to add elements at specific indexes in a list, we can use the insert() method. We specify the index in the first argument and the element that we want to add in the list as a second argument:

my_list = ["a", "b"]

my_list.insert(1, "z")

print(my_list)  # ['a', 'z', 'b']

How to delete elements from a list

We can delete elements from lists using the pop() method, which removes the last element in the list:

my_list = [1, 2, 3, 4, 5]

my_list.pop()  # removes 5 from the list

print(my_list)  # [1, 2, 3, 4]

my_list.pop()  # removes 4 from the list

print(my_list)  # [1, 2, 3]

We can also specify the index of an element in the list that indicates which element in the list we should delete:

my_list = [1, 2, 3, 4, 5]

my_list.pop(0)  # Delete the element at index 0

print(my_list)  # [2, 3, 4, 5]

We can also delete elements from lists using the del statement and then specifying the value of the element that we want to delete:

my_list = [1, 2, 3, 4, 1]

del my_list[0]  # Delete element my_list[0]

print(my_list)  # [2, 3, 4, 5]

We can also delete slices of lists using del:

my_list = [1, 2, 3, 4, 1]

del my_list[0:3]  # Delete elements: my_list[0], my_list[1], my_list[2]

print(my_list)  # [4, 1]

We can do this using remove():

my_list = [1, 2, 3, 4]

my_list.remove(3) 

print(my_list)  # [1, 2, 4]

reverse() lets us reverse the elements in a list. This is quite easy and straightforward:

my_list = [1, 2, 3, 4]

my_list.reverse()

print(my_list)  # [4, 3, 2, 1]

Index search

Getting elements of a list using indexes is simple. Finding indexes of elements of a list is also easy. We simply need to use the method index() and mention the element that we want to find inside a list:

my_list = ["Fatos", "Morina", "Python", "Software"]

print(my_list.index("Python"))  # 2

Membership

This is quite intuitive and related to real life: We get to ask ourselves whether something is part of something or not.

Is my phone in my pocket or bag?

Is my coworker's email included in the CC?

Is my friend in this coffee shop?

In Python, if we want to check whether a value is part of something, that we can use the operator in:

my_list = [1, 2, 3]  # This is a list

print(1 in my_list)  # True

Since 1 is included in the array [1, 2, 3], the expression evaluates to True.

We can also use it not only with arrays of numbers, but with arrays of characters as well:

vowels = ['a', 'i', 'o', 'u']
print('y' in vowels)  # False

Since y is not a vowel and not included in the declared array, the expression in the second line of the previous code snippet is going to result in False.

Similarly, we can also check whether something is not included using not in:

odd_numbers = [1, 3, 5, 7]
print(2 not in odd_numbers)  # True

Since 2 is not included in the array, the expression is going to evaluate to True.

How to sort elements in a list

Sorting elements in a list is something that you may need to do from time to time. sort() is a built-in method that makes it possible for you to sort elements in a list in an ascending order alphabetically or numerically:

my_list = [3, 1, 2, 4, 5, 0]

my_list.sort()

print(my_list)  # [0, 1, 2, 3, 4, 5]

alphabetical_list = ['a', 'c', 'b', 'z', 'e', 'd']

alphabetical_list.sort()

print(alphabetical_list)  # ['a', 'b', 'c', 'd', 'e', 'z']

There are other methods of lists that we have not included in here.

List comprehension

List comprehension represents a concise way in which we use a for loop to create a new list from an existing one. The result is always a new list in the end.

Let's start with an example where we want to multiply each number of a list with 10 and save that result in a new list. First, let's do this without using list comprehension:

numbers = [2, 4, 6, 8]  # Complete list

numbers_tenfold = []  # Empty list

for number in numbers:
    number = number * 10  # Multiply each number with 10
    numbers_tenfold.append(number)  # Add that new number in the new list
    
print(numbers_tenfold)  # [20, 40, 60, 80]

We can implement that using list comprehension in the following way:

numbers = [2, 4, 6, 8]  # Complete list

numbers_tenfold = [number * 10 for number in numbers]  # List comprehension

print(numbers_tenfold)  # [20, 40, 60, 80]

We can also include conditions when doing these list comprehensions.

Let's assume that we want to save a list of positive numbers.

Before we write the way we would implement this using list comprehension, let's write a way in which we would create a list of only numbers that are greater than 0 in another list and increase those positive numbers by 100:

positive_numbers = []  # Empty list

numbers = [-1, 0, 1, -2, -3, -4, 3, 2]  # Complete list

for number in numbers:
    if number > 0:  # If the current number is greater than 0
        positive_numbers.append(number + 100)  # add that number inside the list positive_numbers

        
print(positive_numbers)  # [101, 103, 102]

We can do the same using list comprehension:

numbers = [-1, 0, 1, -2, -3, -4, 3, 2]  # Compelete list

positive_numbers = [number + 100 for number in numbers if number > 0]  # List comprehension

print(positive_numbers)  # [101, 103, 102]

As you can see, this is much shorter and should take less time to write.

We can also use list comprehension with multiple lists as well.

Let's take an example where we want to add each element of a list with each element in another list:

first_list = [1, 2, 3]
second_list = [50]

double_lists = [first_element +
                second_element for first_element in first_list for second_element in second_list]

print(double_lists)  # [51, 52, 53]

In the end, we are going to get a resulting list that has the same number of elements as the list with the longest length.

Tuples in Python

Tuples are collections that are ordered and immutable, meaning that their content cannot be changed. They are ordered and we can access their elements using indexes.

Let's start with our first tuple:

vehicles = ("Computer", "Smartphone", "Smart watch", "Tablet")

print(vehicles)

# ('Computer', 'Smartphone', 'Smart watch', 'Tablet')

All the indexing and slicing operations that we have seen in the list section apply for tuples as well:

print(len(vehicles))  # 4

print(vehicles[3])  # Tablet

print(vehicles[:3])  # ('Computer', 'Smartphone', 'Smart watch')

You can find the index of an element inside a tuple using the index() method:

print(vehicles.index('tablet'))  # 3

We can also concatenate or merge two tuples using the + operator:

natural_sciences = ('Chemistry', 'Astronomy',
                    'Earth science', 'Physics', 'Biology')

social_sciences = ('Anthropology', 'Archaeology', 'Economics', 'Geography',
                   'History', 'Law', 'Linguistics', 'Politics', 'Psychology', 'Sociology')

sciences = natural_sciences + social_sciences

print(sciences)
# ('Chemistry', 'Astronomy', 'Earth science', 'Physics', 'Biology', 'Anthropology', 'Archaeology', 'Economics', 'Geography', 'History', 'Law', 'Linguistics', 'Politics', 'Psychology', 'Sociology')

Membership check

We can check whether an element is part of a tuple using the operators in and not in just like with lists:

vehicles = ('Car', 'Bike', 'Airplane')

print('Motorcycle' in vehicles)  # False, since Motorcycle is not included in vehicles

print('Train' not in vehicles)  # True, since Train is not included in vehicles

How to nest two tuples

Instead of merging, we can also nest tuples into a single tuple by using tuples that we want to nest inside the parenthesis:

natural_sciences = ('Chemistry', 'Astronomy',
                    'Earth science', 'Physics', 'Biology')

social_sciences = ('Anthropology', 'Archaeology', 'Economics', 'Geography',
                   'History', 'Law', 'Linguistics', 'Politics', 'Psychology', 'Sociology')

sciences = (natural_sciences, social_sciences)

print(sciences)
# (('Chemistry', 'Astronomy', 'Earth science', 'Physics', 'Biology'), ('Anthropology', 'Archaeology', 'Economics', 'Geography', 'History', 'Law', 'Linguistics', 'Politics', 'Psychology', 'Sociology'))

Immutability

Since tuples are immutable, we can't change them after we create them. This means that we cannot add or delete elements in them, or append a tuple to another tuple.

We cannot even modify existing elements in a tuple. If we try to modify an element in a tuple, we are going to face a problem like the following:

vehicles = ('Car', 'Bike', 'Airplane')

vehicles[0] = 'Truck'

print(vehicles)
# TypeError: 'tuple' object does not support item assignment

Dictionaries in Python – Key-Value Data Structures

As we saw previously, elements in lists are associated with indexes that we can use to reference those elements.

There is another data structure in Python that allows us to specify our own custom indexes and not just numbers. These are called dictionaries, and they are similar to dictionaries that we use to find the meaning of words we do not understand.

Let's assume that you are trying to learn German and there is a new word that you have not had the chance to learn before that you just saw at a market: Wasser.

Now, you can pick up your phone and check its corresponding meaning in English using Google Translate or any other application of your choice. But if you were to use a physical dictionary, you would need to find this word by going to that specific page and check its meaning sitting right beside it. The reference or the key for the meaning of this word would be the term Wasser.

Now, if we want to implement this in Python, we should not use lists that have indexes only as numbers. We should use dictionaries instead.

For dictionaries, we use curly braces and have each element that has two parts: the key and the value.

In our previous example, the key was the German word, whereas the value was its translation in English, as you can see in the following example:

german_to_english_dictionary = {
    "Wasser": "Water",
    "Brot": "Bread",
    "Milch": "Milk"
}

Now, when we want to access specific elements in the dictionary, we simply use keys. For example, let's assume that we want to get the meaning of the word Brot in English. To do that, we can simply reference that element using that key:

brot_translation = german_to_english_dictionary["Brot"]
print(translation)  # Bread

When we print the value that we get, we are going to get the translation in English.

Similarly, we can get the English translation of the word Milch by getting the value of the element that has Milch as the key:

milch_translation = german_to_english_dictionary["Milch"]
print(milch_translation)  # Milk

We can also get the value of an element in a dictionary using get() and specifying the key of the item that we want to get:

german_to_english_dictionary.get("Wasser")

Both keys and values can be of any data type.

Dictionaries can have duplicate values, but the all the keys should be unique. Take a look at this example to see what I mean:

my_dictionary = dict([
  ('a', 1),
  ('b', 1),
  ('c', 2)
])

We can create dictionaries using dict():

words = dict([
    ('abandon', 'to give up to someone or something on the ground'),
    ('abase', 'to lower in rank, office, or esteem'),
    ('abash', 'to destroy the self-possession or self-confidence of')
])

print(words)
# {'abandon': 'to give up to someone or something on the ground', 'abase': 'to lower in rank, office, or esteem', 'abash': 'to destroy the self-possession or self-confidence of'}

How to add new values to a dict

We can add new values inside dictionaries by specifying a new key and a corresponding value. Then Python is going to create a new element inside that dictionary:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

words['g'] = 'gama'

print(words)
# {'a': 'alfa', 'b': 'beta', 'd': 'delta', 'g': 'gama'}

If we specify the key of an element that is already part of the dictionary, that element is going to be modified:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

words['b'] = 'bravo'


print(words)
# {'a': 'alfa', 'b': 'bravo', 'd': 'delta'}

How to remove elements from a dict

If we want to remove elements from a dictionary, we can use the method pop() and also specify the key of the element that we want to delete:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

words.pop('a')

print(words)  # {'b': 'beta', 'd': 'delta'}

We can also delete values using popitem() which removes the last inserted key-value pair starting from Python 3.7. In earlier versions, it deletes a random pair:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

words['g'] = 'gamma'

words.popitem()

print(words)  
# {'a': 'alfa', 'b': 'beta', 'd': 'delta'}

There is another way that we can delete elements, namely by using  del statement:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

del words['b']

print(words)  # {'a': 'alfa', 'd': 'delta'}

How to get the length of a dict

We can get the length of a dictionary using len() just like with lists and tuples:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

print(len(words))  # 3

Membership

If we want to check whether a key is already part of a dictionary so that we avoid overriding it, we can use the operator in and not in just like with lists and tuples:

words = {
    'a': 'alfa',
    'b': 'beta',
    'd': 'delta',
}

print('a' in words)  # True
print('z' not in words)  # True

Comprehension

We can use comprehension just like with lists to create dictionaries in a quick way.

To help us with that, we are going to need to use a method called items() that converts a dictionary into a list of tuples. The element in index 0 is a key, whereas in position with index 1, we have a value.

Let's first see the method items() in action:

points = {
    'Festim': 50,
    'Zgjim': 89,
    'Durim': 73
}

elements = points.items()

print(elements) # dict_items([('Festim', 50), ('Zgjim', 89), ('Durim', 73)])

Now let's create a new dictionary from this existing dictionary points using comprehension.

We can assume that a professor is in a good mood and generous enough to reward each student with a bonus of 10 points. We want to add these new points to each student by saving these new points in a new dictionary:

points = {
    'Festim': 50,
    'Zgjim': 89,
    'Durim': 73
}

elements = points.items()

points_modified = {key: value + 10 for (key, value) in elements}

print(points_modified)  # {'Festim': 60, 'Zgjim': 99, 'Durim': 83}

Sets in Python

Sets are unordered and unindexed collections of data. Since elements in sets are not ordered, we cannot access elements using indexes or using the method get().

We can add tuples, but we cannot add dictionaries or lists in a set.

We cannot add duplicate elements in sets. This means that when we want to remove duplicate elements from another type of collection, we can make use of this uniqueness in sets.

Let's start creating our first set using curly brackets as follows:

first_set = {1, 2, 3}

We can also create sets using the set() constructor:

empty_set = set()  # Empty set

first_set = set((1, 2, 3))  # We are converting a tuple into a set

Like all data structures, we can find the length of a set using the method len():

print(len(first_set))  # 3

How to add elements to a set

We can add one element in a set using the method add():

my_set = {1, 2, 3}

my_set.add(4)

print(my_set)  # {1, 2, 3, 4}

If we want to add more than one element, then we need to use method update(). We use as an input for this method a list, tuple, string or another set:

my_set = {1, 2, 3}

my_set.update([4, 5, 6])

print(my_set)  # {1, 2, 3, 4, 5, 6}

my_set.update("ABC")

print(my_set)  # {1, 2, 3, 4, 5, 6, 'A', 'C', 'B'}

How to delete elements from a set

If we want to delete elements from sets, we can use methods discard() or remove():

my_set = {1, 2, 3}

my_set.remove(2)

print(my_set)  # {1, 3}

If we try to delete an element that is not part of the set using remove(), then we are going to get an error:

my_set = {1, 2, 3}

my_set.remove(4)

print(my_set)  # KeyError: 4

To avoid such errors when removing elements from sets, we can use the method discard():

my_set = {1, 2, 3}

my_set.discard(4)

print(my_set)  # {1, 2, 3}

Set Theory Operations

If you remember high school math lessons, you should already know about union, intersection, and the difference between two sets of elements. These operations are supported for sets in Python as well.

Union

Union represents the collection of all unique elements from both sets. We can find the union of two sets using the pipe operator | or the union() method:

first_set = {1, 2}
second_set = {2, 3, 4}

union_set = first_set.union(second_set)

print(union_set)  # {1, 2, 3, 4}

Intersection

Intersection represents the collection that contains elements that are in both sets. We can find it using operator & or the intersection() method:

first_set = {1, 2}
second_set = {2, 3, 4}

intersection_set = first_set.intersection(second_set)

print(union_set)  # {2}

Difference

The difference between two sets represents the collection that contains only the elements that are in the first set, but not in the second. We can find the difference between two sets using the - operator or the method difference()

first_set = {1, 2}
second_set = {2, 3, 4}

difference_set = first_set.difference(second_set)

print(difference_set)  # {1}

As you can probably remember from high school, ordering of sets when we find the difference of two sets matters, which is not the case with the union and intersection.

This is similar to arithmetic, where 3 - 4 is not equal to 4 - 3:

first_set = {1, 2}
second_set = {2, 3, 4}

first_difference_set = first_set.difference(second_set)

print(first_difference_set)  # {1}

second_difference_set = second_set.difference(first_set)

print(second_difference_set)  # {3, 4}

Type Conversions in Python

Conversions Between Primitive Types

Python is an object oriented programming language. That is why it uses constructor functions of classes to do conversions from one type into another.

int() method

int() is a method that you use do a conversion of an integer literal, float literal (rounding it to its previous integer number, that is 3.1 to 3), or a string literal (with the condition that the string represents an int or float literal):

three = int(3)  # converting an integer literal into an integer
print(three)  # 3

four = int(4.8)  # converting a float number into its previous closest integer
print(four)  # 4

five = int('5')  # converting a string into an integer
print(five)  # 5

float() method

float() is similarly used to create float numbers from an integer, float, or string literal (with the condition that the string represents an int or float literal):

int_literal = float(5)
print(int_literal)  # 5.0

float_literal = float(1.618)
print(float_literal)  # 1.618

string_int = float("40")
print(string_int)  # 40.0

string_float = float("37.2")
print(string_float)  # 37.2

str() method

We can use str() to create strings from strings, integer literals, float literals, and many other data types:

int_to_string = str(3)
print(int_to_string)  # '3'

float_to_string = str(3.14)
print(float_to_string)  # '3.14'

string_to_string = str('hello')
print(string_to_string)  # 'hello'

Other Conversions

To convert from one type of data structure into another type, we do the following:

destination_type(input_type)

Let us get started with specific types, so that it becomes much clearer.

Conversions to lists

We can convert a set, tuple, or dictionary into a list using the list() constructor.

books_tuple = ('Book 1', 'Book 2', 'Book 3')
tuple_to_list = list(books_tuple)  # Converting tuple to list
print(tuple_to_list)  # ['Book 1', 'Book 2', 'Book 3']


books_set = {'Book 1', 'Book 2', 'Book 3'}
set_to_list = list(books_set)  # Converting set to list
print(set_to_list)  # ['Book 1', 'Book 2', 'Book 3']

When converting a dictionary into a list, only its keys are going to make it into a list:

books_dict = {'1': 'Book 1', '2': 'Book 2', '3': 'Book 3'}
dict_to_list = list(books_dict)  # Converting dict to list
print(dict_to_list)  # ['1', '2', '3']

If we want to keep both keys and values of a dictionary, we need to use the method items() to first convert it into a list of tuples where each tuple is a key and a value:

books_dict = {'1': 'Book 1', '2': 'Book 2', '3': 'Book 3'}

dict_to_list = list(books_dict.items())  # Converting dict to list

print(dict_to_list)
# [('1', 'Book 1'), ('2', 'Book 2'), ('3', 'Book 3')]

Conversions to tuples

All data structures can be converted to a tuple using the tuple() constructor method, including a dictionary In that case we get a tuple with the keys of the dictionary:

books_list = ['Book 1', 'Book 2', 'Book 3']
list_to_tuple = tuple(books_list)  # Converting tuple to tuple
print(list_to_tuple)  # ('Book 1', 'Book 2', 'Book 3')


books_set = {'Book 1', 'Book 2', 'Book 3'}
set_to_tuple = tuple(books_set)  # Converting set to tuple
print(set_to_tuple)  # ('Book 1', 'Book 2', 'Book 3')


books_dict = {'1': 'Book 1', '2': 'Book 2', '3': 'Book 3'}
dict_to_tuple = tuple(books_dict)  # Converting dict to tuple
print(dict_to_tuple)  # ('1', '2', '3')

Conversions to sets

Similarly, all data structures can be converted to a set using the set() constructor method, including a dictionary. In that case we get a set with the keys of the dictionary:

books_list = ['Book 1', 'Book 2', 'Book 3']
list_to_set = set(books_list)  # Converting list to set
print(list_to_set)  # {'Book 2', 'Book 3', 'Book 1'}


books_tuple = ('Book 1', 'Book 2', 'Book 3')
tuple_to_set = set(books_tuple)  # Converting tuple to set
print(tuple_to_set)  # {'Book 2', 'Book 3', 'Book 1'}


books_dict = {'1': 'Book 1', '2': 'Book 2', '3': 'Book 3'}
dict_to_set = set(books_dict)  # Converting dict to set
print(dict_to_set)  # {'1', '3', '2'}

Conversions to dictionaries

Conversions into dictionaries cannot be done with any type of sets, lists, or tuples, since dictionaries represent data structures where each element contains both a key and a value.

Converting a list, or a tuple into a dictionary can be done if each element in a list is also a list with two elements, or a tuple with two elements.

books_tuple_list = [(1, 'Book 1'), (2, 'Book 2'), (3, 'Book 3')]
tuple_list_to_dictionary = dict(books_tuple_list)  # Converting list to set
print(tuple_list_to_dictionary)  # {1: 'Book 1', 2: 'Book 2', 3: 'Book 3'}

books_list_list = [[1, 'Book 1'], [2, 'Book 2'], [3, 'Book 3']]
tuple_list_to_dictionary = dict(books_list_list)  # Converting list to set
print(tuple_list_to_dictionary)  # {1: 'Book 1', 2: 'Book 2', 3: 'Book 3'}


books_tuple_list = ([1, 'Book 1'], [2, 'Book 2'], [3, 'Book 3'])
tuple_list_to_set = dict(books_tuple_list)  # Converting tuple to set
print(tuple_list_to_set)  # {'Book 2', 'Book 3', 'Book 1'}

books_list_list = ([1, 'Book 1'], [2, 'Book 2'], [3, 'Book 3'])
list_list_to_set = dict(books_list_list)  # Converting tuple to set
print(list_list_to_set)  # {'Book 2', 'Book 3', 'Book 1'}

In case when we want to convert a set into a dictionary, we need to have each element as a tuple of length 2.

books_tuple_set = {('1', 'Book 1'), ('2', 'Book 2'), ('3', 'Book 3')}
tuple_set_to_dict = dict(books_tuple_set)  # Converting dict to set
print(tuple_set_to_dict)  # {'1', '3', '2'}

If we try to do a conversion of a set that has each element as a list of length 2 into a dictionary, we are going to get an error:

books_list_set = {['1', 'Book 1'], ['2', 'Book 2'], ['3', 'Book 3']}
list_set_to_dict = dict(books_list_set)  # Converting dict to set
print(list_set_to_dict)  # {'1', '3', '2'}

After we run the last code block, we are going to get an error:

TypeError: unhashable type: 'list'

Wrapping Up Data Types

In conclusion, Python has a variety of data types that you can use to store data. These data types are important to know so that you can choose the right one for your needs.

Be sure to use the right data type for the task that is in front of you to avoid errors and optimize performance.

Control Flow in Python

Conditional statements

When you think about ways we think and also communicate with each other, you may get the impression that we are indeed always using conditions.

  • If it's 8 am, I take the bus and go to work.
  • If I am hungry, I eat.
  • If this item is cheap, I can afford it.

This is also something that you can do in programming. We can use conditions to control the flow of the execution.

To do that, we use the reserved term if and an expression that evaluates to a True or False value. We can then also use an else statement where we want the flow to continue in cases when the if condition is not met.

To make it easier to understand, let's assume that we have an example where we want to check whether a number is positive:

if number > 0:
    print("The given number is positive")
else:
    print("The given number is not positive")

If we were to have number = 2: we would enter into the if branch and execute the command that is used to print the following text in the console:

The given number is positive

If we would have another number, such as -1, we would see in the console the following message being printed:

The given number is not positive

We can also add additional conditions – and not just 2 like above – by using elif which is evaluated when the if expression is not evaluated.

Let's see an example to make it easier for you to understand:

if number > 0:
    print("The given number is positive")
elif number == 0:
    print("The given number is 0")
else:
    print("The given number is negative")

Now if we were to have number = 0, the first condition is not going to be met, since the value is not greater than 0. As you can guess, since the given number is equal to 0, we are going to see the following message being printed in the console:

The given number is 0

In cases when the value is negative, our program is going to pass the first two conditions since they are not satisfied and then jump into the else branch and print the following message in the console:

The given number is negative

Looping / Iterator

Looping represents the ability of the program to execute a set of instructions over and over again until a certain condition is met. We can do it with both while and for.

Let's first see the iteration with for.

for loop in Python

This looping is simple and quite straightforward. All you have to do is specify a starting state and mention the range in which it should iterate, as you can see in the following example:

for number in range(1, 7):
    print(number)

In this example, we are iterating from 1 to 7 and printing each number (from 1 up to 7 excluding 7) in the console.

We can change both the starting and the ending numbers in the range as we want. This way, we can be quite flexible depending on our specific scenarios.

while loop in Python

Let's now describe iterations with while. This is also another way of doing iterations that is also quite straightforward and intuitive.

Here we need to specify a starting condition before the while block and also update the condition accordingly.

The while loop needs a “loop condition.” If it stays True, it continues iterating. In this example, when num is 11 the loop condition equals False.

number = 1

while number < 7:
    print(number)
    number += 1  # This part is necessary for us to add so that the iteration does not last forever

This while block is going to print the same statements as the code we used with the for block.

Iteration: Looping Through Data Structures

Now that we have covered both iteration and lists, we can jump into ways of iterating through lists.

We do not just store things in data structures and leave them there for ages. We are supposed to be able to use those elements in different scenarios.

Let's take our list of students from before:

students = ["Albert", "Besart", "Fisnik", "Festim", "Gazmend"]

Now, to iterate through the list, we can simply type:

for student in students:
    print(student)

Yes, it's that simple. We are iterating through each element in the list and printing their values.

We can do this for dictionaries as well. But since elements in dictionaries have 2 parts (key and the value), we need to specify both the key and the value as follows:

german_to_english_dictionary = {
    "Wasser": "Water",
    "Brot": "Bread",
    "Milch": "Milk"
}

for key, value in german_to_english_dictionary:
    print("The German word " + key + " means " + value + " in English")

We can also get only keys from the elements of the dictionary:

for key in german_to_english_dictionary:
    print(key)

Note that key and value are simply variable names that we have chosen to illustrate the iteration. But we can use any name that we want for our variables, such as the following example:

for german_word, english_translation in german_to_english_dictionary:
    print("The German word " + german_word + " means " + english_translation + " in English")

This iteration is going to print the same thing in the console as the code block before the last one.

We can also have nested for loops. For example, let's say that we want to iterate through a list of numbers and find a sum of each element with each other element of a list. We can do that using nested for loops:

numbers = [1, 2, 3]
sum_of_numbers = []  # Empty list

for first_number in numbers:
    for second_number in numbers:  # Loop through the list and add the numbers
        current_sum = first_number + second_number
        # add current first_number from the first_list to the second_number from the second_list
        sum_of_numbers.append(current_sum)


print(sum_of_numbers)
# [2, 3, 4, 3, 4, 5, 4, 5, 6]

How to stop a for-loop

Sometimes we may need to exit a for loop before it reaches the end. This may be the case when a condition has been met or we have found what we were looking for and there is no need to continue any further.

In those situations, we can use break to stop any other iteration of the for loop.

Let's assume that we want to check whether there is a negative number in a list. In case we find that number, we stop searching for it.

Let's implement this using break:

my_list = [1, 2, -3, 4, 0]

for element in my_list:
    print("Current number: ", element)
    if element < 0:
        print("We just found a negative number")
        break

# Current number:  1
# Current number:  2
# Current number:  -3
# We just found a negative number

As we can see, the moment we reach -3, we break from the for loop and stop.

How to skip an iteration

There can also be cases when we want to skip certain iterations since we are not interested in them and they do not matter that much. We can do that using continue which prevents code execution below it in that code block and moves the execution procedure towards the next iteration:

my_sum = 0
my_list = [1, 2, -3, 4, 0]

for element in my_list:
    if element < 0:  # Do not include negative numbers in the sum
        continue
    my_sum += element

print(my_sum)  # 7

pass is a statement we can use to help us when we are about to implement a method or something but we haven't done it yet and do not want to get errors.

It helps us execute the program even if some parts of the code are missing:

my_list = [1, 2, 3]

for element in my_list:
    pass  # Do nothing

Conditional Statement Wrap Up

In conclusion, Python offers conditional statements to help you control the flow of your program.

The if statement lets you run a block of code only if a certain condition is met. The elif statement lets you run a block of code only if another condition is met. And the else statement lets you run a block of code only if no other condition is met.

These statements are very useful for controlling the flow of your program.

Functions in Python

There are plenty of cases when we need to use the same code block again and again. Our first guess would be to write it as many times as we want.

Objectively, it does work, but the truth is, this is a really bad practice. We are doing repetitive work that can be quite boring and it's also prone to more mistakes that we might overlook.

This is the reason why we need to start using code blocks that we can define once and then use that same code anywhere else.

Just think about this in real life: You see a YouTube video that has been recorded and uploaded to YouTube once. It is then going to be watched by many other people, but the video still remains the same one that was uploaded initially.

In other words, we use methods as a representative of a set of coding instructions that are then supposed to be called anywhere else in the code and that we do not have to write it repeatedly.

In cases when we want to modify this method, we simply change it at the place where it was first declared and other places where it is called do not have to do anything.

To define a method in Python, we start by using the def keyword, then the name of the function and then a list of arguments that we expect to be used. After that, we need to start writing the body of the method in a new line after an indentation.

def add(first_number, second_number):
    our_sum = first_number + second_number
    return our_sum

As you can see from the syntax highlighting, both def and return are keywords in Python that you cannot use to name your variables.

Now, everywhere we want this add() to be called, we can just call it there and not have to worry about implementing it entirely.

Since we have defined this method, we can call it in the following way:

result = add(1, 5)

print(result)  # 6

You might think that this is such a simple method and start asking, why are we even bothering to write a method for it?

You are right. This was a very simple method just to introduce you to the way we can implement functions.

Let's write a function that finds the sum of numbers that are between two specified numbers:

def sum_in_range(starting_number, ending_number):
    result = 0
    
    while starting_number < ending_number:
        result = result + starting_number
        starting_number = starting_number + 1
        
    return result

This is now a set of instructions that you can call in other places and do not have to write all of it again.

result = sum_in_range(1, 5)

print(result)  # 10

Note that functions define a scope, which means that variables which are defined in that scope are not accessible outside it.

For example, we cannot access the variable named product outside the scope of the function:

def multiply_in_range(starting_number, ending_number):
    product = 1
    while starting_number < ending_number:
        product = product * starting_number
        starting_number = starting_number + 1
    return product

product is accessible only inside the body of this method.

Default Arguments in Functions

When we call functions, we may make some of the arguments optional by writing an initial value for them at the header of the function.

Let's take an example of getting a user's first name as a required argument and let the second argument be an optional one.

def get_user(first_name, last_name=""):
    return f"Hi {first_name} {last_name}"

We'll now call this function with both arguments:

user = get_user("Durim", "Gashi")

print(user)  # Hi Durim Gashi

We can now call that same function even though the the second argument is not specified:

user = get_user("Durim")

print(user)  # Hi Durim

Keyword Argument List

We can define arguments of functions as keywords:

# The first argument is required. The other two are optional
def get_user(number, first_name='', last_name=''):
    return f"Hi {first_name} {last_name}"

Now, we can call this function by writing arguments as keywords:

user = get_user(1, last_name="Gashi")

print(user)  # Hi  Gashi

As you can see, we can omit first_name since it is not required. We can also change the ordering of the arguments when calling the function and it will still work the same:

user = get_user(1, last_name="Gashi", first_name='Durim')

print(user)  # Hi Durim Gashi

Data Lifecycle

Variables that are declared inside a function cannot be accessed outside it. They are isolated.

Let's see an example to illustrate this:

def counting():
    count = 0  # This is not accessible outside of the function.


counting()

print(count)  # This is going to throw an error when executing, since count is only declared inside the function and is not acessible outside that

Similarly, we cannot change variables inside functions that have been declared outside functions and that are not passed as arguments:

count = 3331


def counting():
    count = 0  # This is a new variable


counting()

print(count)  # 3331
# This is declared outside the function and has not been changed

How to Change Data Inside Functions

We can change mutable data that is passed through a function as arguments. Mutable data represents data that we can modify even after it has been declared, Lists, for example, are mutable data.

names = ["betim", "durim", "gezim"]


def capitalize_names(current_list):

    for i in range(len(current_list)):
        current_list[i] = current_list[i].capitalize()

    print("Inside the function:", current_list)

    return current_list


capitalize_names(names)  # Inside the function: ['Betim', 'Durim', 'Gezim']

print("Outside the function:", names)  # Outside the function: ['Betim', 'Durim', 'Gezim']

In case of immutable data, we can only modify the variable inside a function, but the actual value outside that function is going to remain unchanged. Immutable data are strings and numbers:

name = "Betim"


def say_hello(current_param):
    current_param = current_param + " Gashi"
    name = current_param  # name is a local variable
    print("Value inside the function:", name)
    return current_param


say_hello(name)  # Value inside the function: Betim Gashi

print("Value outside the function:", name)  # Value outside the function: Betim

If we really want to update immutable variables through a function, we can assign a return value of a function to the immutable variable:

name = "Betim"


def say_hello(current_param):
    current_param = current_param + " Gashi"
    name = current_param  # name is a local variable
    print("Value inside the function", name)
    return current_param


# Here we are assigning the value of name to the current_param that is returned from the function
name = say_hello(name)  # Value inside the function Betim Gashi

# Value outside the function: Betim Gashi
print("Value outside the function:", name)

Lambda Functions

Lambda functions are anonymous functions that we can use to return an output. We can write lambda functions using the following syntax pattern:

lambda parameters: expression

The expression can only be written in a single line.

Let's start illustrating these anonymous functions using a few examples.

We'll start with a function that multiples each input with 10:

tenfold = lambda number : number * 10

print(tenfold(10))  # 100

Let's write another example in which we check whether the given argument is positive or not:

is_positive =  lambda a : f'{a} is positive' if a > 0 else f'{a} is not positive'


print(is_positive(3))  # 3 is positive

print(is_positive(-1))  # -1 is not positive

Note that we cannot use the if clause without the else clause inside a lambda function.

At this point, you may wonder, why do we need to use lambda functions, since they seem to be almost the same as other functions?

We can see that illustrated in the following section.

Functions as arguments of functions

So far, we have seen ways of calling functions using numbers and strings. We can actually call functions with any type of Python object.

We can even provide an entire function as the argument of a function, which can provide a level of abstraction that can be quite useful.

Let's see an example where we want to do a few conversions from one unit into another:

def convert_to_meters(feet):
    return feet * 0.3048


def convert_to_feet(meters):
    return meters / 0.3048


def convert_to_miles(kilometers):
    return kilometers / 1.609344


def convert_to_kilometers(miles):
    return miles * 1.609344

Now, we can make a general function and pass another function as an argument:

def conversion(operation, argument):
    return operation(argument)

We can now call conversion() like this:

result = conversion(convert_to_miles, 10)

print(result)  # 6.2137119223733395

As you can see, we have written convert_to_miles as a parameter of the function conversion(). We can use other already defined functions like that:

result = conversion(convert_to_feet, 310)

print(result)  # 1017.0603674540682

We can now make use of lambdas and make this type of abstraction much simpler.

Instead of writing all those four functions, we can simply write a concise lambda function and use it as a parameter when calling the conversion() function:

def conversion(operation, argument):
    return operation(argument)


result = conversion(lambda kilometers: kilometers / 1.609344, 10)

print(result)  # 6.2137119223733395

This is of course simpler.

Let's use a few other examples with built-in functions.

map() function

map() is a built-in function that creates a new object by getting results by calling a function on each element of an existing list:

map(function_name, my_list)

Let's see an example of writing a lambda function as the function of a map.

Let's triple each number in a list using list comprehension:

my_list = [1, 2, 3, 4]

triple_list = [x * 3 for x in my_list]

print(triple_list)  # [3, 6, 9, 12]

We can implement that using a map() function and a lambda function:

my_list = [1, 2, 3, 4]

triple_list = map(lambda x: x * 3, my_list)

print(triple_list)  # [3, 6, 9, 12]

This creates a new list. The old list is not changed.

filter() function

This is another built-in function that we can use to filter elements of a list that satisfy a condition.

Let's first filter out negative elements from a list using list comprehension:

my_list = [3, -1, 2, 0, 14]

non_negative_list = [x for x in my_list if x >= 0]

print(non_negative_list)  # [3, 2, 0, 14]

Now, we'll filter elements using filter() and a lambda function. This function returns an object which we can convert into a list using list():

my_list = [3, -1, 2, 0, 14]

non_negative_filter_object = filter(lambda x: x >= 0, my_list)

non_negative_list = list(non_negative_filter_object)

print(non_negative_list)  # [3, 2, 0, 14]

You should now understand how you can call functions with other functions as arguments and why lambdas are useful and important.

Decorators in Python

A decorator represents a function that accepts another function as an argument.

We can think of it as a dynamic way of changing the way a function, method, or class behaves without having to use subclasses.

Once a function is being passed as an argument to a decorator, it will be modified and then returned as a new function.

Let's start with a basic function that we want to decorate:

def reverse_list(input_list):
    return input_list[::-1]

In this example, we are simply returning a reversed list.

We can also write a function that accepts another function as an argument:

def reverse_list(input_list):
    return input_list[::-1]


def reverse_input_list(another_function, input_list):
    # we are delegating the execution to another_function() 
    return another_function(input_list)


result = reverse_input_list(reverse_list, [1, 2, 3])

print(result)  # [3, 2, 1]

We can also nest a function inside another function:

def reverse_input_list(input_list):
    # reverse_list() is now a local function that is not accessible from the outside
    def reverse_list(another_list):
        return another_list[::-1]

    result = reverse_list(input_list)
    return result               # Return the result of the local function


result = reverse_input_list([1, 2, 3])
print(result)  # [3, 2, 1]

In this example, reverse_list() now is a local function and cannot be called outside the scope of the reverse_input_list() function.

Now we can write our first decorator:

def reverse_list_decorator(input_function):
    def function_wrapper():
        returned_result = input_function()
        reversed_list = returned_result[::-1]
        return reversed_list

    return function_wrapper

reverse_list_decorator() is a decorator function that takes as input another function. To call it, we need to write another function:

# Function that we want to decorate
def get_list():
    return [1, 2, 3, 4, 5]

Now we can call the decorator with our new function as an argument:

decorator = reverse_list_decorator(get_list)  # This returns a reference to the function

result_from_decorator = decorator()  # Here we call the actual function using parenthesis

# We can now print the result in the console
print(result_from_decorator)  # [5, 4, 3, 2, 1]

Here is the complete example:

def reverse_list_decorator(input_function):
    def function_wrapper():
        returned_result = input_function()
        reversed_list = returned_result[::-1]
        return reversed_list

    return function_wrapper

# Function that we want to decorate
def get_list():
    return [1, 2, 3, 4, 5]


# This returns a reference to the function
decorator = reverse_list_decorator(get_list)

# Here we call the actual function using the parenthesis
result_from_decorator = decorator()

# We can now print the result in the console
print(result_from_decorator)  # [5, 4, 3, 2, 1]

We can also call a decorator using annotations. To do that, we use the @ sign before the name of the decorator that we want to call and put it right above the name of the function:

# Function that we want to decorate
@reverse_list_decorator  # The annotation of the decorator function
def get_list():
    return [1, 2, 3, 4, 5]

Now, we can simply call the functionget_list() and the decorator is going to be applied in it:

result_from_decorator = get_list()

print(result_from_decorator)  # [5, 4, 3, 2, 1]

How to stack decorators

We can also use more than one decorator for a single function. Their order of execution starts from top to bottom, meaning that the decorator that has been defined first is applied first, then the second one, and so on.

Let's do a simple experiment and apply the same decorator that we defined in the previous section twice.

First let's understand what that means.

So we first call the decorator to reverse a list:

[1, 2, 3, 4, 5] to [5, 4, 3, 2, 1]

Then we apply it again, but now with the returned result from the previous calling of the decorator:

[5, 4, 3, 2, 1] => [1, 2, 3, 4, 5]

In other words, reversing a list and then reversing that reversed list again is going to return the original ordering of the list.

Let's see this with decorators:

@reverse_list_decorator
@reverse_list_decorator
def get_list():
    return [1, 2, 3, 4, 5]


result = get_list()

print(result)  # [1, 2, 3, 4, 5]

I'll explain this with another example.

Let's implement another decorator that only returns numbers that are larger than 1. We then want to reverse that returned list with our existing decorator.

def positive_numbers_decorator(input_list):
    def function_wrapper():
        # Get only numbers larger than 0
        numbers = [number for number in input_list() if number > 0]
        return numbers

    return function_wrapper

Now we can call this decorator and the other decorator that we have implemented:

@positive_numbers_decorator
@reverse_list_decorator
def get_list():
    return [1, -2, 3, -4, 5, -6, 7, -8, 9]


result = get_list()
print(result)  # [9, 7, 5, 3, 1]

Here is the complete example:

def reverse_list_decorator(input_function):
    def function_wrapper():
        returned_result = input_function()
        reversed_list = returned_result[::-1]  # Reverse the list
        return reversed_list

    return function_wrapper


# First decoorator
def positive_numbers_decorator(input_list):
    def function_wrapper():
        # Get only numbers larger than 0
        numbers = [number for number in input_list() if number > 0]
        return numbers

    return function_wrapper

# Function that we want to decorate


@positive_numbers_decorator
@reverse_list_decorator
def get_list():
    return [1, -2, 3, -4, 5, -6, 7, -8, 9]


result = get_list()
print(result)  # [9, 7, 5, 3, 1]

How to pass arguments to decorator functions

We can also pass arguments to decorator functions:

def add_numbers_decorator(input_function):
    def function_wrapper(a, b):
        result = 'The sum of {} and {} is {}'.format(
            a, b, input_function(a, b))  # calling the input function with arguments
        return result
    return function_wrapper


@add_numbers_decorator
def add_numbers(a, b):
    return a + b


print(add_numbers(1, 2))  # The sum of 1 and 2 is 3

Built-in decorators

Python comes with multiple built-in decorators, such as @classmethod, @staticmethod, @property, and so on. We'll cover these in the next chapter.

Function Wrap Up

Python is an excellent language for writing functions because they are easy to write.

Lambda functions are a great way to make small, concise functions in Python. They're perfect for when you don't need a full-blown function, or when you just want to test out a snippet of code.

Python decorators are a great way to improve code readability and maintainability. They allow you to modularize your code and make it more organized. You can also use them to perform various tasks such as logging, exception handling, and testing. So if you're looking for a way to clean up your Python code, consider using decorators.

Object Oriented Programming in Python

If you go to buy a cookie at a local store, you are going to get a version of the cookie that has been produced in many other copies.

There's a cookie cutter at a factory that has been used to produce a large number of cookies that are then distributed all throughout different stores where those cookies are then served to the end customers.

We can think of that cookie cutter as a blueprint that has been designed once and is used many times afterwards. We also use this sort of blueprint in computer programming.

A blueprint that is used to create countless other copies is called a class. We can think of a class like a class called Cookie, Factory, Building, Book, Pencil, and so on. We can use the class of cookie as a blueprint to create as many instances as we want of it that we call objects.

In other words, blueprints are classes that are used as cookie cutters, whereas the cookies that are served at different stores are objects.

Object Oriented Programming represents a way of organizing a program using classes and objects. We use classes to create objects. Objects interact with each other.

We do not use the exact same blueprint for every object that is out there. There is a blueprint for producing books, another one for producing pencils, and so on. We need to categorize them based on attributes and their functionalities.

An object that is created from the Pencil class can have a color type, a manufacturer, a specific thickness, and so on. These are the attributes. A pencil object can also write which represents its functionality, or its method.

We use classes and objects in different programming languages, including Python.

Let's see how a very basic Bicycle class looks in Python:

class Bicycle:
    pass

We have used the keyword class to indicate that we are about to start writing a class and then we type the name of the class.

We have added the pass because we don't want the Python interpreter to yell at us by throwing errors for not continuing to write the remaining part of the code that belongs to this class.

Now, if we want to create new objects from this class Bicycle, we can simply write the name of the object (which can be any variable name that you want) and initiailize it with the constructor method Bicycle() that is used to create new objects:

favorite_bike = Bicycle()

In this case, favorite_bike is an object that is created from the class Bicycle. It gets all the functionalities and attributes of the class Bicycle.

We can enrich our Bicycle class and include additional attributes so that we can have custom bikes, tailored to our needs.

To do that, we can define a constructor method called init as follows:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self.manufacturer = manufacturer
        self.color = color
        self.is_mountain_bike = is_mountain_bike

Note the usage of underscores before and after the name init of the method. They represent indicators to the Python interpreter to treat that method as a special method.

This is a method that does not return anything. It is a good practice to define it as the first method of the class, so that other developers can also see it being at a specific line.

Now, if we want to create new objects using this blueprint of bicycles, we can simply write:

bike = Bicycle("Connondale", "grey", True)

We have provided our custom parameters for this bike and are passing them to the constructor method. Then we get a new bike with those specific attributes in return. As you can probably tell, we are creating a grey mountain bike of the brand Connondale.

We can also create objects from classes by using optional arguments as follows:

class Bicycle:
    # All the following attributes are optional
    def __init__(self, manufacturer=None, color='grey', is_mountain_bike=False):
        self.manufacturer = manufacturer
        self.color = color
        self.is_mountain_bike = is_mountain_bike

Now we have just created this object with these attributes, which are not currently accessible outside the scope of the class.

This means that we have created this new object from the Bicycle class, but its corresponding attributes are not accessible. To access them, we can implement methods that help us access them.

To do that, we are going to define getters and setters, which represent methods that we use to get and set values of attributes of objects.  We are going to use an annotation called @property to hep us with that.

Let’s see it with code:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self._manufacturer = manufacturer
        self._color = color
        self._is_mountain_bike = is_mountain_bike

    @property
    def manufacturer(self):
        return self._manufacturer

    @manufacturer.setter
    def manufacturer(self, manufacturer):
        self._manufacturer = manufacturer


bike = Bicycle("Connondale", "Grey", True)

print(bike.manufacturer)  # Connondale

We can write getters and setters for all the attributes of the class:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self._manufacturer = manufacturer
        self._color = color
        self._is_mountain_bike = is_mountain_bike

    @property
    def manufacturer(self):
        return self._manufacturer

    @manufacturer.setter
    def manufacturer(self, manufacturer):
        self._manufacturer = manufacturer

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, color):
        self._color = color

    @property
    def is_mountain_bike(self):
        return self._is_mountain_bike

    @is_mountain_bike.setter
    def is_mountain_bike(self, is_mountain_bike):
        self.is_mountain_bike = is_mountain_bike

bike = Bicycle("Connondale", "Grey", True)

Now that we have defined them, we can call these getter methods as attributes:

print(bike.manufacturer)  # Connondale
print(bike.color)  # Grey
print(bike.is_mountain_bike)  # True

We can also modify the value that we initially used for any attribute by simply typing the name of object and the attribute where we want to change the content:

bike.is_mountain_bike = False
bike.color = "Blue"
bike.manufacturer = "Trek"

Our classes can also have other methods as well and not just getters and setters.

Let's define a method inside the class Bicycle that we can then call from any object that we have created from that class:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self._manufacturer = manufacturer
        self._color = color
        self._is_mountain_bike = is_mountain_bike

    def get_description(self):
        desc = "This is a " + self._color + " bike of the brand " + self._manufacturer
        return desc

We have created a very simple method in which we are preparing a string as a result from the attributes of the object that we are creating. We can then call this method like any other method.

Let's see this in action:

bike = Bicycle("Connondale", "Grey", True)

print(bike.get_description())  # This is a Grey bike of the brand Connondale

Methods in Python

Methods are similar to functions, which we covered above.

In a nutshell, we group a few statements in a code block called method. There we perform some operations that we expect to be done more than once and do not want to write them again and again. In the end, we may not return any result at all.

There are three types of methods in Python:

  • instance methods
  • class methods
  • static methods

Let's briefly talk about the overall structure of methods and then dive a little more into detail for each method type.

Parameters

Parameters of a method make it possible for us to pass on dynamic values that can then be taken into consideration when executing the statements that are inside the method.

The return statement represents the statement that is going to be the last one to be executed in that method. It is an indicator for the Python interpreter to stop the execution of any other line and return a value.

The self argument

The first argument of a method in Python is self which is also one of the differences between a method and a function. It represents a reference to the object to which it belongs to. If we don't specify as the first argument of the method when being declared, the first argument is then treated as a reference to the object.

We only write it when we declare the method, but we do not need to include it when we invoke that particular method using an object as a caller.

It is not required that we name it self, but it is a convention that is widely practiced by developers writing Python code all around the world.

Let's define an instance method inside the class Bicycle that we can then call from any object that we have created from that class:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self._manufacturer = manufacturer
        self._color = color
        self._is_mountain_bike = is_mountain_bike

    def get_description(self):
        desc = "This is a " + self._color + " bike of the brand " + self._manufacturer
        return desc

We have created a very simple method in which we are preparing a string as a result from the attributes of the object that we are creating. We can then call this method like any other method:

bike = Bicycle("Connondale", "Grey", True)

print(bike.get_description())  # This is a Grey bike of the brand Connondale
# We are not passing any argument when calling the method get_description() since we do not need to include self at all

Class methods

We have covered instance methods so far. These are methods that we can call with objects.

Class methods are methods that we can call using class names and that we can access without needing to create any new object at all.

Since it is a specific type of method, we need to tell the Python interpreter that it is actually different. We do that by making a change in the syntax.

We use the annotation @classmethod above a class method and cls similar to the usage of self for instance methods. cls is just a conventional way of referring to the class that is calling the method – you don't have to use this name.

Let's declare our first class method:

class Article:
    blog = 'https://www.python.org/'

    # the init method is called when an instance of the class is created
    def __init__(self, title, content):
        self.title = title
        self.content = content

    @classmethod
    def get_blog(cls):
        return cls.blog

Now let's call this class method that we have just declared:

print(Article.get_blog())  # https://www.python.org/

Note that we did not have to write any argument when calling the get_blog() method. On the other hand, when we declare methods and instance methods, we should always include at least one argument.

Static methods

These are methods that do not have direct relations to class variables or instance variables. You can think of them as utility functions that are supposed to help us do something with arguments that are passed when calling them.

We can call them by using both the class name and an object that is created by that class where this method is declared. This means that they do not need to have their first argument related to the object or class calling them (as was the case with using parameters self for instance methods and cls for class methods).

There is no limit to the number of arguments that we can use to call them.

To create it, we need to use the @staticmethod annotation.

Let's create a static method:

class Article:
    blog = 'https://www.python.org/'

    # the init method is called when an instance of the class is created
    def __init__(self, title, content):
        self.title = title
        self.content = content

    @classmethod
    def get_blog(cls):
        return cls.blog

    @staticmethod
    def print_creation_date(date):
        print(f'The blog was created on {date}')


article = Article('First Article', 'This is the first article')

# Calling the static method using the object
article.print_creation_date('2022-07-18')  # The blog was created on 2022-07-18

# Calling the static method using the class name
Article.print_creation_date('2022-07-21')  # The blog was created on 2022-07-21

Static methods cannot modify class or instance attributes. They are meant to be like utility functions.

If we try to change a class, we are going to get errors:

class Article:
    blog = 'https://www.python.org/'

    # the init method is called when an instance of the class is created
    def __init__(self, title, content):
        self.title = title
        self.content = content

    @classmethod
    def get_blog(cls):
        return cls.blog

    @staticmethod
    def set_title(self, date):
        self.title = 'A random title'

If we try to call this static method now, we are going to get an error:

# Calling the static method using the class name
Article.set_title('2022-07-21')
TypeError: set_title() missing 1 required positional argument: 'date'

This is because static methods do not have any reference to self as they are not directly related to objects or classes and so they cannot modify attributes.

Access modifier

When creating classes, we can restrict access to certain attributes and methods so that they are not accessible that easily.

We have publicand private access modifiers.

Let's see how both of them work.

Public attributes

Public attributes are the ones that are accessible from both inside and outside the class.

By default, all attributes and methods are public in Python. If we want them to be private, we need to specify that.

Let's see an example of public attributes:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self.manufacturer = manufacturer
        self.color = color
        self.is_mountain_bike = is_mountain_bike

    def get_manufacturer(self):
        return self.manufacturer

In the previous code block, both color and get_manufacturer() are accessible outside the class since they are public and can be accessed both inside and outside the class:

bike = Bicycle("Connondale", "Grey", True)

print(bike.color)  # Grey
print(bike.get_manufacturer())  # Connondale

Private attributes

Private attributes can be accessed directly only from inside the class.

We can make properties attributes by using the double underscore, as you can see in the following example:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike, old):
        self.manufacturer = manufacturer
        self.color = color
        self.is_mountain_bike = is_mountain_bike
        self.__old = old  # This is a private property

Now if we try to access __old, we are going to get an error:

bike = Bicycle("Connondale", "Grey", True, False)

print(bike.__old)  # AttributeError: 'Bicycle' object has no attribute '__old'

Let's now see an example where we are declaring private methods using the double underscore in front of the name of the method that we want to make private:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike, old):
        self.manufacturer = manufacturer
        self.color = color
        self.is_mountain_bike = is_mountain_bike
        self.__old = old  # This is a private property

    def __get_old(self):  # This is a private method
        return self.__old

Now, if we want to call this private method from outside the class, an error is going to be thrown:

bike = Bicycle("Connondale", "Grey", True, False)

print(bike.__get_old())  # AttributeError: 'Bicycle' object has no attribute '__get_old'

It is not a common practice to have private variables in Python. However, developers may find it necessary to restrict access so that specific variables are not carelessly accessed and modified.

How to Hide Information in Python

When you go out there and use a coffee machine, you aren't expected to know all the engineering details that are behind that machine.

This is the same with your car. When you sit in your driver's seat, you do not analyze and understand all the details of every part of the car. You have some basic idea about them, but other than that, you just focus on driving.

This is a sort of restriction of access from people outside, so that they do not have to worry about exact details that are going on inside.

We can do that in Python as well.

We have seen so far the foundational blocks of object oriented programming, such as classes and objects.

Classes are blueprints that are used to create instances called objects. We can use objects of different classes to interact with each other and build a robust program.

When we work on our own programs, we may need to not let everyone know about all the details that our classes have. So we can limit access to them, so that certain attributes are less likely to be accessed unintentionally and be modified wrongfully.

To help us with that, we hide parts of a class and simply provide an interface that has fewer details about the inner workings of our class.

We can hide data in two ways:

  1. Encapsulation
  2. Abstraction

Let's begin with Encapsulation.

What is Encapsulation?

Encapsulation is not something special and unique just for Python. Other programming languages use it as well.

In a nutshell, we can define it as binding data and methods in a class. We then use this class to create objects.

We encapsulate classes by using private access modifiers that can then restrict direct access to such attributes. This can restrict control.

We are then supposed to write public methods that can provide access to the outside world.

These methods are called getters and setters.

A getter method is a method that we use to get the value of an attribute.

A setter is a method that we use to set the value of an attribute.

Let's define first define a getter and a setter method that we can use to get values:

class Smartphone:
    def __init__(self, type=None):  # defining initializer for case of no argument
        self.__type = type  # setting the type here in the beginning when the object is created

    def set_type(self, value):
        self.__type = value

    def get_type(self):
        return (self.__type)

Now, let's use this class to set the type and also get the type:

smartphone = Smartphone('iPhone')  # we are setting the type using the constructor method

# getting the value of the type
print(smartphone.get_type())   # iPhone

# Changing the value of the type
smartphone.set_type('Samsung')  

# getting the new value of the type
print(smartphone.get_type())    # Samsung

What we have done so far is set and also read the value of a private attribute of an object created from the Smartphone class.

We can also define getters and setters using the @property annotation.

Let’s see it with code:

class Bicycle:
    def __init__(self, manufacturer, color):
        self._manufacturer = manufacturer
        self._color = color

    @property
    def manufacturer(self):
        return self._manufacturer

    @manufacturer.setter
    def manufacturer(self, manufacturer):
        self._manufacturer = manufacturer

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, color):
        self._color = color


bike = Bicycle("Connondale", "Grey")

Now that we have defined them, we can call these getter methods as attributes:

print(bike.manufacturer)  # Connondale
print(bike.color)  # Grey

We can also modify the value that we initially used for any attribute by simply typing the name of the object and the attribute that we want to modify:

bike.is_mountain_bike = False
bike.color = "Blue"

Our classes can also have other methods as well, and not just getters and setters.

Let's define a method inside the class Bicycle that we can then call from any object that we have created from that class:

class Bicycle:
    def __init__(self, manufacturer, color, is_mountain_bike):
        self._manufacturer = manufacturer
        self._color = color
        self._is_mountain_bike = is_mountain_bike

    def get_description(self):
        desc = "This is a " + self._color + " bike of the brand " + self._manufacturer
        return desc

We have created a very simple method in which we are preparing a string as a result from the attributes of the object that we are creating. We can then call this method like any other method.

Let's see this in action:

bike = Bicycle("Connondale", "Grey", True)

print(bike.get_description())  # This is a Grey bike of the brand Connondale

But why do we need encapsulation?

This looks quite promising and fancy, but you may not get it quite yet. You might need some additional reasons why you need this type of hiding.

To drive this home, let's take another class, where we have a private attribute called salary. Let's say that we don't care about encapsulation and we are only trying to build a class fast and use it in our project for our accountant client.

Let's say that we have the following class:

class Employee:
    def __init__(self, name=None, email=None, salary=None):
        self.name = name
        self.email = email
        self.salary = salary

Now, let's create a new employee object and initialize its attributes accordingly:

# We are creating an object
betim = Employee('Betim', 'betim@company.com', 5000)

print(betim.salary)  # 5000

Since salary is not being protected in any way, we can set a new salary for this new object without any problem:

betim.salary = 25000

print(betim.salary)  # 25000

As we can see, this person got five times the salary of what he was getting previously without going through any type of evaluation or interviewing at all. In fact, it happened in a matter of seconds. That's probably going to hit the budget of the company heavily.

We do not want to do that. We want to restrict access to the salary attribute so that it is not called from other places. We can do that by using the double underscore before the attribute name as you can see below:

class Employee:
    def __init__(self, name=None, email=None, salary=None):
        self.__name = name
        self.__email = email
        self.__salary = salary

Let's create a new object:

# We are creating an object
betim = Employee('Betim', 'betim@company.com', 1000)

Now, if we try to access its attributes, we cannot do so, since they are private attributes:

print(betim.salary)  # 1000

Trying to access any of the attributes is going to be followed with an error:

AttributeError: 'Employee' object has no attribute 'salary'

We can simply implement a method that returns the attributes but we are not providing any way for someone to increase their salary sneakily:

class Employee:
    def __init__(self, name=None, email=None, salary=None):
        self.__name = name
        self.__email = email
        self.__salary = salary

    def get_info(self):
        return self.__name, self.__email, self.__salary

Now, we can access the information of objects created by this class:

# We are creating an object
betim = Employee('Betim', 'betim@company.com', '5000')

print(betim.get_info())  # ('Betim', 'betim@company.com', '5000')

In summary, encapsulation helps us protect properties of objects and provides access them in a controlled fashion.

Inheritance in Python

In real life, we can share many characteristics with other human beings.

We all need to eat food, drink water, work, sleep, move, and so on. These and many other behaviors and characteristics are shared among billions of people all around the world.

They are not something unique that only our generation has. These traits have been around as long as humans have.

This is also something that is going to last for future generations to come.

We can also have certain shared characteristics between objects and classes that we implement ourselves in computer programming using inheritance. This includes both attributes and methods.

Let's imagine that we have a class called Book. It should contain a title, an author, a number of pages, a category, an ISBN, and so on. We are going to keep our class simple and use only two attributes:

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

    def get_short_book_paragraph(self):
        short_paragraph = "This is a short paragraph of the book."
        return short_paragraph

Now, we can create an object from this class and access it:

first_book = Book("Atomic Habits", "James Clear")

print(first_book.title)  # Atomic Habits
print(first_book.author)  # James Clear
print(first_book.get_short_book_paragraph())  # This is a short paragraph of the book.

Let's now create a subclass of the class Book that inherits attributes and methods from the class Book, but also has an additional method called get_book_description():

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        
    def get_short_book_paragraph(self):
        short_paragraph = "This is a short paragraph of the book."
        return short_paragraph

    
class BookDetails(Book):
    def __init__(self, title, author):
        Book.__init__(self, title, author)
        # Here we are call the constructor of the parent class Book

    def get_book_details(self):
        description = "Title: " + self.title + ". "
        description += "Author: " + self.author
        return description

Note the syntax in which we tell Python that BookDetails is a subclass of the class Book:

class BookDetails(Book):

If we try to access this new method from objects of the class Book, we are going to get an error:

first_book = Book("Atomic Habits", "James Clear")

print(first_book.get_book_details())
# AttributeError: 'Book' object has no attribute 'get_book_details'

This happens because this method get_book_details() can be accessed only from objects of BookDetails:

first_book_details = BookDetails("Atomic Habits", "James Clear")

print(first_book_details.get_book_details())
# Title: Atomic Habits. Author: James Clear

We can, however, access any method that is defined in the parent class, which in our case is the Book class:

first_book_details = BookDetails("Atomic Habits", "James Clear")

print(first_book_details.get_short_book_paragraph())
# This is a short paragraph of the book.

In the previous classes, Book is considered a parent class or a superclass, whereas BookDetails is considered a child class, or a subclass.

super() function

There is a special function called super() that we can use from a child class to refer to its parent class without writing the exact name of the parent class.

We use it with initializers, or when calling properties or methods of parent classes.

Let's see all three of them illustrated with examples.

How to use super() with initializers

We can use super() inside the constructor method of the subclass and even call the constructor of the super class:

class Animal():
    def __init__(self, name, age):
        self.name = name
        self.age = age


class Cat(Animal):
    def __init__(self, name, age):
        super().__init__(name, age)  # calling the parent class constructor
        self.health = 100  # initializing a new attribute that is not in the parent class

We can also replace super() with the name of the parent class, which is going to work in the same way again:

class Animal():
    def __init__(self, name, age):
        self.name = name
        self.age = age


class Cat(Animal):
    def __init__(self, name, age):
        Animal.__init__(name, age)  # calling the parent class constructor
        self.health = 100  # initializing a new attribute that is not in the parent class

Even changing the order of the lines inside the child's constructor will not cause any error at all.

How to use super() with class properties of the parent class

We can use super() to access class properties of the parent class, which can be useful especially when both the parent and the child class use the same name for an attribute.

To see that in action, let's assume that we have a class attribute called name which is present both in the parent and the child class. We want to access this variable from both the parent class and the child class.

To do that, we simply need to write super() and then the name of the variable:

class Producer:  # parent class
    name = 'Samsung'


class Seller(Producer):  # child class
    name = 'Amazon'

    def get_product_details(self):
        # Calling the variable from the parent class
        print("Producer:", super().name)

        # Calling the variable from the child class
        print("Seller:", self.name)

Now, if we call method get_product_details(), we are going to get the following printed in the console:

seller = Seller()

seller.get_product_details()

# Producer: Samsung
# Seller: Amazon

How to use super() with methods of the parent class

We can similarly call methods in the parent class using super().

class Producer:  # parent class
    name = 'Samsung'

    def get_details(self):
        return f'Producer name: {self.name}'


class Seller(Producer):  # child class
    name = 'Amazon'

    def get_details(self):
        # Calling the method from the parent class
        print(super().get_details())

        # Calling the variable from the child class
        print(f'Seller name: {self.name}')


seller = Seller()
seller.get_details()

# Producer name: Amazon
# Seller name: Amazon

This is all you need to know about super().

Types of inheritance

We can have different types of inheritance based on the relationship of parent classes and child classes:

  1. Single
  2. Multi-level
  3. Hierarchical
  4. Multiple
  5. Hybrid

1. Single inheritance

We can have a class that inherits only from another class:

class Animal:
    def __init__(self):
        self.health = 100

    def get_health(self):
        return self.health


class Cat(Animal):
    def __init__(self, name):
        super().__init__()
        self.health = 150
        self.name = name

    def move(self):
        print("Cat is moving")

cat = Cat("Cat")

# Calling the method from the parent class
print(cat.get_health())  # 150

# Calling the method from the child class
cat.move()  # Cat is moving

2. Multi-level inheritance

This is another type of inheritance where a class inherits from another class which inherits from another class: Class A inherits from Class B which inherits from Class C.

Let's implement this in Python:

class Creature:
    def __init__(self, alive):
        self.alive = alive

    def is_it_alive(self):
        return self.alive


class Animal(Creature):
    def __init__(self):
        super().__init__(True)
        self.health = 100

    def get_health(self):
        return self.health


class Cat(Animal):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def move(self):
        print("Cat is moving")


cat = Cat("Cat")

# Calling the method from the parent of the parent class
print(cat.is_it_alive())

# Calling the method from the parent class
print(cat.get_health())  # 150

# Calling the method from the child class
cat.move()  # Cat is moving

3. Hierarchical inheritance

When we derive multiple child classes from the same parent class, then we have hierarchical inheritance. These child classes inherit from the parent class:

class Location:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_location(self):
        return self.x, self.y


class Continent(Location):
    pass


class Country(Location):
    pass


continent = Continent(0, 0)
print(continent.get_location())  # (0, 0)

country = Country(10, 30)
print(country.get_location())  # (10, 30)

4. Multiple inheritance

We can have another type of inheritance, namely multiple inheritance which can help us inherit from more than one class at the same time.

Let's assume that we have a class called Date and another one called Time.

We can then implement another class then inherits from both classes:

class Date:
    date = '2022-07-23'  # Hardcoded date

    def get_date(self):
        return self.date


class Time:
    time = '20:20:20'  # Hardcoded time

    def get_time(self):
        return self.time


class DateTime(Date, Time):  # Inheriting from both
    def get_date_time(self):
        return self.get_date() + ' ' + self.get_time()  # getting methods from its parent classes


date_time = DateTime()
print(date_time.get_date_time())  # 2022-07-23 20:20:20

5. Hybrid inheritance

Hybrid inheritance is a combination of multiple and multi-level inheritance:

class Vehicle:
    def print_vehicle(self):
        print('Vehicle')


class Car(Vehicle):
    def print_car(self):
        print('Car')


class Ferrari(Car):
    def print_ferrari(self):
        print('Ferrari')


class Driver(Ferrari, Car):
    def print_driver(self):
        print('Driver')

Now, if we create an object from the class Driver, we can call all methods in all classes:

driver = Driver()

# Calling all methods from the subclass
driver.print_vehicle()  # Vehicle
driver.print_car()  # Car
driver.print_ferrari()  # Ferrari
driver.print_driver()  # Driver

Polymorphism in Python

This is another important concept from Object Oriented Programming that refers to the possibility of an object behaving like different forms and calling different behaviors.

An example of a built-in function that uses polymorphism is the method len() which can be used for both strings and lists:

print(len('Python'))  # 6

print(len([2, 3, -43]))  # 3

We can take another example with a class called House. We can have different subclasses that inherit methods and attributes from that superclass, namely classes such as Condo, Apartment, SingleFamilyHouse, MultiFamilyHouse, and so on.

Let's assume that we want to implement a method in the House class that is supposed to get the area.

Each type of living residence has a different size, so each one of the subclasses should have different implementations.

Now we can define methods into subclasses such as:

  • getAreaOfCondo()
  • getAreaOfApartment()
  • getAreaOfSingleFamilyHouse()
  • getAreaOfMultiFamilyHouse()

This would force us to remember the names of each subclass, which can be tedious and also prone to errors when we call them.

Luckily, there is a simpler method that we can use that comes from polymorphism.

We can have polymorphism using both methods and inheritance.

Let's first see how we can implement polymorphism using methods.

Polymorphism using methods

Let's say that we have two classes, namely Condo and Apartment. Both of them have the method get_area() that returns a value.

Each of them is going to have a custom implementation.

Now the method that we are going to call depends on the class type of the object:

class Condo:
    def __init__(self, area):
        self.area = area

    def get_area(self):
        return self.area


class Apartment:
    def __init__(self, area):
        self.area = area

    def get_area(self):
        return self.area

Let's create two objects from these classes:

condo = Condo(100)

apartment = Apartment(200)

Now, we can put both of them in a list and call the same method for both objects:

places_to_live = [condo, apartment]

for place in places_to_live:
    print(place.get_area())  # same method for both objects

After we execute that, we are going to see the following in the console:

# 100
# 200

This is how you implement polymorphism with methods.

Polymorphism with inheritance

We can not only call a method from a superclass. We can also use the same name but have a different implementation for it for each subclass.

Let's first define a superclass:

class House:
    def __init__(self, area):
        self.area = area

    def get_price(self):
        pass

Then we'll implement subclasses Condo and Apartment of the superclass House:

class House:
    def __init__(self, area):
        self.area = area

    def get_price(self):
        pass


class Condo(House):
    def __init__(self, area):
        self.area = area

    def get_price(self):
        return self.area * 100 


class Apartment(House):
    def __init__(self, area):
        self.area = area

    def get_price(self):
        return self.area * 300

As we can see, both subclasses have the method get_price() but different implementations.

We can now create new objects from subclasses and call this method which is going to polymorph based on the object that calls it:

condo = Condo(100)

apartment = Apartment(200)

places_to_live = [condo, apartment]

for place in places_to_live:
    print(place.get_price())

After we execute that, we are going to see the following in the console:

# 10000
# 60000

This is another example of polymorphism where we have specific implementation of a method that has the same name.

Importing in Python

One of the main benefits of using a popular language such as Python is its large number of libraries that you can use and benefit from.

Many developers around the world are generous with their time and knowledge and publish a lot of really useful libraries. These libraries can save us plenty of time both in our professional work, but also on our side projects that we may do for fun.

Here are some of the modules with very useful methods that you can immediately start using in your projects:

  • time: Time access and conversions
  • csv: CSV File Reading and Writing
  • math: Math functions
  • email: Create, send, and process email
  • urllib: Work with URLs

To import one or more modules, we only need to write import and then the name of the modules that we want to import.

Let's import our first module:

import os

Now, let's import multiple modules at once:

import os, numbers, math

Once we have imported a module, we can start using methods that are inside it.

import math

print(math.sqrt(81))  # 9.0

We can also use new names for our imported modules by specifying an alias for them as alias where alias is any variable name that you want:

import math as math_module_that_i_just_imported

result = math_module_that_i_just_imported.sqrt(4)

print(result)  # 2.0

How to Limit What We Want to Import

There are times when we do not want to import a whole package with all its methods. This is because we want to avoid overriding methods or variables that are in the module with the ones that we want to implement ourselves.

We can specify parts that we want to import by using the following form:

from module import function

Let's take an example of importing only the square root function from math module:

from math import sqrt

print(sqrt(100))  # 10.0

Issues with Importing Everything from a Module

We can also import everything from a module, which can turn out to be a problem. Let's illustrate this with an example.

Let's assume that we want to import everything that is included in the math module. We can do that by using the asterisk like this:

from math import *  # The asterisk is an indicator to include everything when importing

Now, let's assume that we want to declare a variable called sqrt:

sqrt = 25

When we try to call the function sqrt() from the math module, we are going to get an error, since the interpreter is going to call the latest sqrt variable that we have just declared in the previous code block:

print(sqrt(100))
TypeError: 'float' object is not callable

How to Handle Exceptions in Python

When we are implementing Python scripts or doing any type of implementation, we are going to get many errors that are thrown even when the syntax is correct.

These types of errors that happen during execution are called exceptions.

We indeed do not have to surrender and not do anything regarding them. We can write handlers that are there to do something so that the execution of the program does not stop.

Common Exceptions in Python

Here are some of the most common exceptions that happen in Python with definitions taken from the Python documentation:

  • Exception – This is a class that is as a superclass of most other exception types that happen.
  • NameError – Raised when a local or global name is not found.
  • AttributeError – Raised when an attribute reference or assignment fails.
  • SyntaxError – Raised when the parser encounters a syntax error.
  • TypeError – Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch.
  • ZeroDivisionError – Raised when the second argument of a division or modulo operation is zero.
  • IOError – Raised when an I/O operation (such as a print statement, the built-in open() function or a method of a file object) fails for an I/O-related reason, e.g., “file not found” or “disk full”.
  • ImportError – Raised when an import statement fails to find the module definition or when a from … import fails to find a name that is to be imported.
  • IndexError – Raised when a sequence subscript is out of range.
  • KeyError – Raised when a mapping (dictionary) key is not found in the set of existing keys.
  • ValueError – Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as IndexError.

There are many other error types, but you don't really need to see about them now. It is also very unlikely that you are going to see all types of errors all the time.

You can see more types of exception in the Python documentation.

How to Handle Exceptions in Python

Let's start with a very simple example and write a program that throws an error on purpose so that we can then fix it.

We are going to do a division by zero, which is something that you have probably seen at school:

print(5 / 0)

If we try to execute that, we are going to be greeted with the following error in the console:

ZeroDivisionError: division by zero

If we were to have such occurrences inside a Python program of any kind, we should catch and wrap this error inside a try/except block.

We need to write inside the try block the part of the code that we expect is going to throw errors. We then catch those types of errors inside the except block by also specifying the type of error that we except to happen.

Let's see the first example.

Let's see how we can deal with that error so that we also get informed that such error happened:

try:
    5 / 0
except ZeroDivisionError:
    print('You cannot divide by 0 mate!')

As you can see, we are printing a message in the console once we have reached the part where a division by 0 is happening.

We can also omit the part ZeroDivisionError completely:

try:
    5 / 0
except:
    print('You cannot divide by 0 mate!')

However, this is not recommended, since we are catching all types of errors in a single except block and we are not sure what type of errors are being caught (which would be quite useful for us).

Let's continue with another type of error.

Now we'll try to use a variable that is not defined at all:

name = 'User'

try:
    person = name + surname  # surname is not declared
except NameError:
    print('A variable is not defined')

In the previous example, we have used variable surname before declaring it, therefore a NameErroris going to be thrown.

Let's continue with another example that can be quite common.

When we use lists, it can be a common mistake to use an index that is out of range. This means that the index we've used is larger or smaller than the range of indexes of the elements in that list.

Let's illustrate this with an example, where an IndexError is going to be thrown:

my_list = [1, 2, 3, 4]

try:
	print(my_list[5])
    # This list only has 4 elements, so its indexes range from 0 to 3
except IndexError:
    print('You have used an index that is out of range')

We can also use a single try block with multiple except errors:

my_list = [1, 2, 3, 4]

try:
    print(my_list[5])
    # This list only has 4 elements, so its indexes range from 0 to 3
except NameError:
    print('You have used an invalid value')
except ZeroDivisionError:
    print('You cannot divide by zero')
except IndexError:
    print('You have used an index that is out of range')

In the previous example, we try to initially catch whether there is any variable that is used but not declared. If this error happens, then this except block is going to be taking over the execution flow. This execution flow is going to stop there.

Then, we try to check whether we are dividing by zero. If this error is thrown, then this except block is going to take over the execution and everything that is inside it is going to be executed. Similarly, we continue with the rest of the errors declared.

We can also put more than one error inside parenthesis to catch multiple exceptions. But this is not going to be helpful for us, since we do not know what specific error has been thrown. In other words, the following method does work, but it is not recommended:

my_list = [1, 2, 3, 4]

try:
    print(my_list[5])
    # This list only has 4 elements, so its indexes range from 0 to 3
except (NameError, ZeroDivisionError, IndexError):
    print('A NameError, ZeroDivisionError, or IndexError occurred')

The finally keyword

After the try and except are passed, there is another block that we can declare and execute. This block starts with the finally keyword and it is executed no matter whether we have an error is being thrown or not:

my_list = ['a', 'b']

try:
    print(my_list[0])
except IndexError:
    print('An IndexError occurred')
finally:
    print('The program is ending. This is going to be executed.')

If we execute the previous block of code, we are going to see the following in the console:

The program is ending. This is going to be executed.

We usually write code that we want to be as a cleanup inside the finally block. This includes things like closing a file, stopping a connection with a database, exiting the program entirely, and so on.

try, else, except

We can write statements inside try and except, but we can also use an else block where we can write code that we want to be executed if there are no errors being thrown:

my_list = ['a', 'b']

try:
    print(my_list[0])
except IndexError:
    print('An IndexError occurred')
else:
    print('No error occurred. Congratulations!')

If we execute the code above, we are going to get the following printed in the console:

No error occurred. Congratulations!

Exception wrap up

Hopefully you now understand exceptions and the various ways that you can use to handle them. If you handle them correctly, there shouldn't be any sudden interruptions that cause your program to fail unexpectedly.

User Input in Python

When you want to develop an interactive program and get user input in the command line, you can call a function called input().

It is very simple and all you have to do is declare a variable where you want to save the value that the user types:

user_input = input("Please type in your name.")

We can than use that value and print it:

print(f'Hello {user_input}. Nice to have you here')

Wrapping Up

This book represents my attempt to make it quick and easy for you to learn the essentials of Python. There are many other things to know about Python that I didn't cover in this book, but we will leave it here.

I hope this is a useful reference for you.

Now that you have had the chance to learn how to write Python, go out there and make a positive impact with your lines of code.

Get the book as a PDF

You can read this book as a PDF by downloading it here.

Original article source at https://www.freecodecamp.org

#python #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment #datascience #machinelearning

Everything You Need to Know about Python Programming (Free Book)
Connor Mills

Connor Mills

1669010047

Learn HTML for Absolute Beginners

In this tutorial, you'll learn HTML for absolute beginners. Learn how to create website for absolute beginners. Learn HTML from scratch

This course is designed for absolute beginners who have no prior knowledge in programming. The instructor will take you from very basics. You will also learn CSS in this course and how to apply styles in your HTML page. So if you want to create your own website what are you waiting for.

Course Contains :

  •        HTML Introduction
  •        Create Your First HTML Page
  •        Opening an HTML Page in Notepad
  •        HTML Page Structure
  •        How to Add Heading in HTML
  •        HTML is Case Insensitive
  •        How to Add Paragraph in HTML
  •        How to Add an Image in HTML 
  •        How to Start a New Line in HTML 
  •        Text Formatting Tags in HTML 
  •        How to Add Color to Text in HTML 
  •        How to Change Text Font, Size & Alignment in HTML 
  •        How to Add Comments in HTML 
  •        How to Open Another HTML Page 
  •        How to Use Image as a Link in HTML 
  •        Introduction to Tables in HTML 
  •        Introduction to Lists in HTML 
  •        Introduction to Div Tag in HTML 
  •        Introduction to iFrame Tag in HTML 
  •        HTML File Paths 
  •        HTML Editor Notepad++ 
  •        HTML Entities 
  •        How to Get User Input in HTML 

What you’ll learn

  •        Student will learn about HTML coding
  •        Student will able to create their own website

Are there any course requirements or prerequisites?

  •        In this video you will learn HTML from scratch. No prerequisite is required. Just Relax and watch this video if you wanna create your own website.

Who this course is for:

  •        This course is for beginners who have no knowledge in programming and want to create their own website

#html #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

Learn HTML for Absolute Beginners

Learn TypeScript for Beginners

Learn fundamentals of TypeScript programming. In this tutorial, you'll learn: Typization in TypeScript, Use the main fundamentals of TS, Use object types, interfaces and classes in TS, Use generics, TS OOP features and more

What is TypeScript?

  • If you watch this course, you already know that TypeScript is a programming language that is very similar to JavaScript - but with more typization and features, that help you to write your code effectively and control quality.

The main focus of this course

  •    The main focus of this course is to teach how to work with TypeScript. We gonna learn the main things that you need to know - when you gonna start building projects that use this programming language.

What you gonna learn in this course

  •    You gonna learn everything about typization, classes, interfaces, and other things in TypeScript. You will know how to work with all these important things. And you will see how it's cool to use TypeScript in your projects.

What do you need for this course?

  •    First, you need to have some junior experience in JavaScript and Node.js programming. The next thing is to install Node.js with the NPM package manager. And the last thing that you will need - is a code editor. I'm gonna use Visual Studio Code in this course as a Code editor.

What you’ll learn

  •        Typization in TypeScript
  •        Use the main fundamentals of TS
  •        Use object types, interfaces and classes in TS
  •        Use generics, TS OOP features

Are there any course requirements or prerequisites?

  •        Basics in JavaScript/Node programming

Who this course is for:

  •        Beginners in Node programming
  •        Beginners in JavaScript app development

#typescript #javascript #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

Learn TypeScript for Beginners
Joshua Yates

Joshua Yates

1669003274

How to Build a Responsive Landing Page Website with Bootstrap

Learn how to build a responsive landing page with Bootstrap. Build a modern one-product landing page with Bootstrap 4 basics. Learn how to use Bootstrap 4 to design a responsive landing page.

So if you have a working knowledge about HTML and CSS, then you will learn how to create a responsive landing page in 2 hours. This course doesn't cover everything in Bootstrap 4. But if you need to learn how to build a landing page with Bootstrap 4, then this is the course for you. No prior knowledge of Bootstrap 3 or any Bootstrap version is required.

This course is primarily focused on building a Bootstrap based responsive landing page to sell a product. 

This landing page includes the following parts

  •        A basic header
  •        A "buy now" section with a call to action 
  •        Author description section
  •        Product descriptions section
  •        Testimonials section
  •        Bonus products section
  •        A call to action section with discounted pricing

What you’ll learn

  •        Build a responsive sales page with Bootstrap 4
  •        Learn how to adjust the website content for every screen size
  •        Learn basics of converting traditional HTML and CSS into Bootstrap
  •        Understand the best practices about the Bootstrap grids and columns
  •        Basic layout techniques of Bootstrap

Are there any course requirements or prerequisites?

  •        You should be having a basic knowledge of HTML and CSS
  •        You can use a text editor such as Sublime Text or Brackets
  •        The willingness to become a better web developer

Who this course is for:

  •        Students who need to learn about responsive web design with Bootstrap
  •        Students who need to convert static web designs into responsive websites
  •        Freelancers who need to create responsive sales pages quickly
  •        Web designers who need to build responsive websites fast

#bootstrap #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

How to Build a Responsive Landing Page Website with Bootstrap

What's New in Node.js 19?

The release of Node.js 19 is now available! What's New in Node.js 19? Node.js 19 has a number of new features and improvements, including experimental node watch mode and HTTP(S)/1.1 KeepAlive by default, along with V8 JavaScript engine 10.7 feature. It is the Current release until node.js 20 is released.

Tune in with me as we explore what Node.js 19 is all about. Let's understand the latest features and benefits it comes with.

Details of Node.js 19 new features, including experimental node watch mode and HTTP(S)/1.1 KeepAlive by default

Node.js 19 was released on October 18, 2022. It becomes the Current release. It comes with 6 major features:

  • Experimental node watch mode
  • HTTP(S)/1.1 KeepAlive by default
  • Stable WebCrypto
  • Custom ESM resolution adjustments
  • Dropped DTrace/SystemTap/ETW support
  • V8 JavaScript engine is updated to V8 10.7

Let’s explore what they are and how to use them.

Use NVM to explore node

Run the command to install node 19.0.0:

% nvm install 19.0.0
Downloading and installing node v19.0.0...
Downloading https://nodejs.org/dist/v19.0.0/node-v19.0.0-darwin-x64.tar.xz...
##################################################################################################################### 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v19.0.0 (npm v8.19.2)

On any window, run the command to use node 19:

% nvm use 19
Now using node v19.0.0 (npm v8.19.2)

Now we’re ready to explore:

% node --version
v19.0.0

Experimental node watch mode

We created server/index.js:

const express = require("express");
const path = require("path");
const app = express();
app.use(express.static(path.join(__dirname, "../build")));

app.listen(8080, () =>
  console.log("Express server is running on localhost:8080")
);

The server was running with nodemon, a tool that helps to develop Node.js applications by automatically restarting the application when file changes are detected. The command is nodemon server.

With node.js 19, we no longer need to install the additional tool. Instead, we can execute node --watch to automatically restart the application when file changes are detected.

% node --watch server
(node:67643) ExperimentalWarning: Watch mode is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Express server is running on localhost:8080

HTTP(S)/1.1 KeepAlive by default

Node.js 19 sets keepAlive to true by default. This means that any outgoing HTTP(s) connection will automatically use HTTP 1.1 keepAlive. The default keepAlive duration is 5 seconds.

Change the above server/index.js to:

const http = require('node:http');
console.log(http.globalAgent);
const https = require('node:https');
console.log(https.globalAgent);

Execute the server code using node.js 16:

% nvm use 16
Now using node v16.0.0 (npm v7.10.0)
% node server
Agent {
  _events: [Object: null prototype] {
    free: [Function (anonymous)],
    newListener: [Function: maybeEnableKeylog]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  defaultPort: 80,
  protocol: 'http:',
  options: [Object: null prototype] { path: null },
  requests: [Object: null prototype] {},
  sockets: [Object: null prototype] {},
  freeSockets: [Object: null prototype] {},
  keepAliveMsecs: 1000,
  keepAlive: false,
  maxSockets: Infinity,
  maxFreeSockets: 256,
  scheduling: 'lifo',
  maxTotalSockets: Infinity,
  totalSocketCount: 0,
  [Symbol(kCapture)]: false
}
Agent {
  _events: [Object: null prototype] {
    free: [Function (anonymous)],
    newListener: [Function: maybeEnableKeylog]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  defaultPort: 443,
  protocol: 'https:',
  options: [Object: null prototype] { path: null },
  requests: [Object: null prototype] {},
  sockets: [Object: null prototype] {},
  freeSockets: [Object: null prototype] {},
  keepAliveMsecs: 1000,
  keepAlive: false,
  maxSockets: Infinity,
  maxFreeSockets: 256,
  scheduling: 'lifo',
  maxTotalSockets: Infinity,
  totalSocketCount: 0,
  maxCachedSessions: 100,
  _sessionCache: { map: {}, list: [] },
  [Symbol(kCapture)]: false
}
  • At line 18, it shows http.globalAgent sets keepAlive false.
  • At line 40, it shows https.globalAgent sets keepAlive false.

Execute the server code using node.js 19:

% nvm use 19
Now using node v19.0.0 (npm v8.19.2)
% node server
Agent {
  _events: [Object: null prototype] {
    free: [Function (anonymous)],
    newListener: [Function: maybeEnableKeylog]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  defaultPort: 80,
  protocol: 'http:',
  options: [Object: null prototype] {
    keepAlive: true,
    scheduling: 'lifo',
    timeout: 5000,
    noDelay: true,
    path: null
  },
  requests: [Object: null prototype] {},
  sockets: [Object: null prototype] {},
  freeSockets: [Object: null prototype] {},
  keepAliveMsecs: 1000,
  keepAlive: true,
  maxSockets: Infinity,
  maxFreeSockets: 256,
  scheduling: 'lifo',
  maxTotalSockets: Infinity,
  totalSocketCount: 0,
  [Symbol(kCapture)]: false
}
Agent {
  _events: [Object: null prototype] {
    free: [Function (anonymous)],
    newListener: [Function: maybeEnableKeylog]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  defaultPort: 443,
  protocol: 'https:',
  options: [Object: null prototype] {
    keepAlive: true,
    scheduling: 'lifo',
    timeout: 5000,
    noDelay: true,
    path: null
  },
  requests: [Object: null prototype] {},
  sockets: [Object: null prototype] {},
  freeSockets: [Object: null prototype] {},
  keepAliveMsecs: 1000,
  keepAlive: true,
  maxSockets: Infinity,
  maxFreeSockets: 256,
  scheduling: 'lifo',
  maxTotalSockets: Infinity,
  totalSocketCount: 0,
  maxCachedSessions: 100,
  _sessionCache: { map: {}, list: [] },
  [Symbol(kCapture)]: false
}
  • At line 14, it shows http.globalAgent sets keepAlive true.
  • At line 16, it shows the default keepAlive duration is 5 seconds (5000 ms).
  • At line 42, it shows https.globalAgent sets keepAlive true.
  • At line 44, it shows the default keepAlive duration is 5 seconds (5000 ms).

Enable keepAlive will deliver better throughput as connections are reused by default.

Additionally, the agent is able to parse the response keepAlive that the servers might send. This header instructs the client on how much longer to stay connected.

On the other side, the HTTP server will automatically disconnect idle clients when close() is invoked. It is accomplished by http(s).Server.close calling closeIdleConnections internally.

With these changes, HTTP(S)/1.1 requests may experience a better throughput/performance by default.

Stable WebCrypto

The WebCrypto API is an interface to build systems using cryptography. With node.js 19, the WebCrypto API is stable (with the exception of these algorithms: Ed25519, Ed448, X25519, and X448).

We can use globalThis.crypto or require('node:crypto').webcrypto to access this module. The following server/index.js use subtle as an example, where the SubtleCrypto interface provides a number of low-level cryptographic functions:

const { subtle } = globalThis.crypto;

(async function() {

  const key = await subtle.generateKey({
    name: 'HMAC',
    hash: 'SHA-256',
    length: 256
  }, true, ['sign', 'verify']);

  console.log('key =', key);

  const enc = new TextEncoder();
  const message = enc.encode('I love cupcakes');

  console.log('message =', message);

  const digest = await subtle.sign({
    name: 'HMAC'
  }, key, message);

  console.log('digest =', digest);

})();
  • At lines 5–9, An HMAC key is generated. HMAC is a specific type message authentication code (MAC) that involves a cryptographic hash function and a secret cryptographic key. The generated key can be used to simultaneously verify the data integrity and authenticity of a message.
  • At lines 13–14, a message, I love cupcakes, is encoded.
  • At lines 18–20, a message digest is created with key and message. A message digest is a cryptographic hash function that contains a string of digits created by a one-way hashing formula.

The following console information shows the values of key, message, and digest:

% node server
key = CryptoKey {
  type: 'secret',
  extractable: true,
  algorithm: { name: 'HMAC', length: 256, hash: [Object] },
  usages: [ 'sign', 'verify' ]
}
message = Uint8Array(15) [
   73, 32, 108, 111, 118,
  101, 32,  99, 117, 112,
   99, 97, 107, 101, 115
]
digest = ArrayBuffer {
  [Uint8Contents]: <30 01 7a 5c d9 e2 82 55 6b 55 90 4f 1d de 36 d7 89 dd fb fb 1a 9e a0 cc 5d d8 49 13 38 2f d1 bc>,
  byteLength: 32
}

Custom ESM resolution adjustments

Node.js has removed the --experimental-specifier-resolution flag, because its functionality can be achieved via custom loaders.

Clone the example repository:

git clone https://github.com/nodejs/loaders-test.git

Go to the example directory:

% cd loaders-test/commonjs-extension-resolution-loader

Install the packages:

% yarn install

Here is loaders-test/commonjs-extension-resolution-loader/test/basic-fixtures/index.js:

import { version } from 'process';

import { valueInFile } from './file';
import { valueInFolderIndex } from './folder';

console.log(valueInFile);
console.log(valueInFolderIndex);
  • Line 1 is unused.
  • At line 3, valueInFile is imported from './file' without specifying the file extension. Without a custom loader, node’s ESM specifier resolution does not automatically resolve file extensions, such as ./file.js or ./file.mjs.

Here is loaders-test/commonjs-extension-resolution-loader/test/basic-fixtures/file.js:

export const valueInFile = 'hello from file.js';
  • At line 4, valueInFolderIndex is imported from './folder' without specifying the index file name. Without a custom loader, node’s ESM specifier resolution does not have the ability to import directories that include an index file, such as ./folder/index.js or ./folder/index.mjs.

Here is loaders-test/commonjs-extension-resolution-loader/test/basic-fixtures/folder/index.js:

export const valueInFolderIndex = 'hello from folder/index.js';

We have mentioned in another article that there are two ways to execute ESM code:

  1. Set "type": "module" in the package.json.
  2. Change index.js to index.mjs, and run node index.mjs.

Regardless, the following two commands will fail.

% node test/basic-fixtures/index
% node test/basic-fixtures/index.js

However, all these issues can be resolved by the custom loader, loaders-test/commonjs-extension-resolution-loader/loader.js:

import { isBuiltin } from 'node:module';
import { dirname } from 'node:path';
import { cwd } from 'node:process';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { promisify } from 'node:util';

import resolveCallback from 'resolve/async.js';

const resolveAsync = promisify(resolveCallback);

const baseURL = pathToFileURL(cwd() + '/').href;


export async function resolve(specifier, context, next) {
  const { parentURL = baseURL } = context;

  if (isBuiltin(specifier)) {
    return next(specifier, context);
  }

  // `resolveAsync` works with paths, not URLs
  if (specifier.startsWith('file://')) {
    specifier = fileURLToPath(specifier);
  }
  const parentPath = fileURLToPath(parentURL);

  let url;
  try {
    const resolution = await resolveAsync(specifier, {
      basedir: dirname(parentPath),
      // For whatever reason, --experimental-specifier-resolution=node doesn't search for .mjs extensions
      // but it does search for index.mjs files within directories
      extensions: ['.js', '.json', '.node', '.mjs'],
    });
    url = pathToFileURL(resolution).href;
  } catch (error) {
    if (error.code === 'MODULE_NOT_FOUND') {
      // Match Node's error code
      error.code = 'ERR_MODULE_NOT_FOUND';
    }
    throw error;
  }

  return next(url, context);
}

With the loader, the above failed commands work well:

% node --loader=./loader.js test/basic-fixtures/index  
(node:56149) ExperimentalWarning: Custom ESM Loaders is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
hello from file.js
hello from folder/index.js

% node --loader=./loader.js test/basic-fixtures/index.js
(node:56160) ExperimentalWarning: Custom ESM Loaders is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
hello from file.js
hello from folder/index.js

With custom loaders, there is no need for the --experimental-specifier-resolution flag.

Dropped DTrace/SystemTap/ETW Support

For the following two reasons, Node.js has dropped the support for DTrace/SystemTap/ETW:

  • There are no clear indicators anyone is using DTrace, SystemTap, or ETW.
  • The complexity to maintain supporting these tools has proved not worth the effort.

V8 JavaScript engine is updated to V8 10.7

Node.js 19 has updated V8 JavaScript engine to V8 10.7, which includes a new function, Intl.NumberFormat, for language-sensitive number formatting.

Intl.NumberFormat(locales, options)

locales is an optional parameter, which is a BCP 47 language tag, or an array of such strings. Here is the BCP 47 language tag list:

 

options is also an optional parameter, which is an object with some or all of these properties: compactDisplay, currency, currencyDisplay, currencySign, localeMatcher, notation, numberingSystem, signDisplay, style, unit, unitDisplay, useGrouping, roundingMode, roundingPriority, roundingIncrement, trailingZeroDisplay, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits, and maximumSignificantDigits.

Among them, style chooses the formatting style, with the following supported values:

  • "decimal" for plain number formatting (default).
  • "currency" for currency formatting.
  • "percent" for percent formatting.
  • "unit" for unit formatting.

If style is set to 'currency', the currency property is required. currency takes ISO 4217 currency code that is listed in this table. By default, minimumFractionDigits and maximumFractionDigits are both set to 2.

Let’s take a look at this example:

const number = 123456.789;

console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number));
console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));
console.log(new Intl.NumberFormat('ar-SA', { style: 'currency', currency: 'EGP' }).format(number));
console.log(new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }).format(number));
  • At line 3, 'de-DE' is for German. 'EUR' is for Euro. The printed value is 123.456,79 €, with default of 2 fraction digits.
  • At line 4, 'ja-JP' is for Japanese. 'JPY' is for Japanese Yen. The printed value is ¥123,457, as the Japanese Yen does not use a minor unit.
  • At line 5, 'ar-SA' is for Arabic. 'EGP' is for Egyptian Pound. The printed value is ١٢٣٬٤٥٦٫٧٩ ج.م.‏, with default of 2 fraction digits.
  • At line 6, 'zh-CN' is for Chinese. 'CNY' is for Chinese Yuan. The printed value is ¥123,456.79, with default of 2 fraction digits.

Conclusion

Node.js 19 has a number of new features and improvements, including experimental node watch mode and HTTP(S)/1.1 KeepAlive by default, along with V8 JavaScript engine 10.7 feature. It is the Current release until node.js 20 is released.

#javascript #reactjs #nodejs #node #programming #developer #softwaredeveloper #computerscience #webdev #webdeveloper #webdevelopment 

What's New in Node.js 19?

The Difference Between Three Print Functions in Java

In this tutorial, you'll learn how to use the Print Function in Java and the difference between three Print Functions in Java. 

Often, you'll need to print something to the console output when you're coding in Java. And the first thing that likely comes to your mind is the print function or print statement.

But very few people know about the three different print functions/statements in Java. In this article, I am going to tell you about them and show you how they work, with examples.

How to Use the println() Function in Java

The println() function adds a new line after printing the value/data inside it. Here, the suffix ln works as the newline character, \n. If you consider the following example:

public class Main{
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You might not figure out exactly what is happening under the hood as you are printing only one line, and you get the following output:

Hello World!

But if you try to print several different expressions using the println() then you'll see the difference clearly!

public class Main{
    public static void main(String[] args) {
        System.out.println("Hello World!");
        System.out.println("Welcome to freeCodeCamp");
    }
}

Here, you can see that after executing the first print statement, it is adding one new line character ( \n ). So you are getting the second print statement, Welcome to freeCodeCamp, in the next line.

The whole output will be like below:

Hello World!
Welcome to freeCodeCamp

You can check out this video of mine where I talk about this println() function in detail.

 

But, isn't there a way of avoiding the automatically generated newline character in the print function?

YES! There is. In that case, you'll want to use the print() statement.

How to Use the print() Function in Java

For this function, let me use the example I have used just now. You should be able to see the difference right away:

public class Main{
    public static void main(String[] args) {
        System.out.print("Hello World!");
        System.out.print("Welcome to freeCodeCamp");
    }
}

Here, you see that I used print instead of using println like I did earlier. The print doesn't add the additional \n (new line character) after executing the task in it. This means that you will not get any new line after executing any print statement like above.

The output will be like this:

Hello World!Welcome to freeCodeCamp

If you want, then you can also solve this issue using \n like below:

public class Main{
    public static void main(String[] args) {
        System.out.print("Hello World!\n");
        System.out.print("Welcome to freeCodeCamp");
    }
}

This time, the \n will work as the new line character and you will get the second string in a new line. The output is like below:

Hello World!
Welcome to freeCodeCamp

You can also print the two strings using only one print statement like below:

public class Main{
    public static void main(String[] args) {
        System.out.print("Hello World!\nWelcome to freeCodeCamp");
    }
}

The output will be the same this time:

Hello World!
Welcome to freeCodeCamp

How to Use the printf() Function in Java

This printf() function works as a formatted print function. Think about the two scenarios given below:

Scenario 1: Your friend Tommy wants you to provide him your notebook's PDF via an email. You can simply compose an email, provide a subject as you like (such as, hey Tommy, it's Fahim). You can also avoid writing anything to the body part of the email and send that email after attaching the PDF with the email. As simple as that – you don't need to maintain any courtesy with your friend, right?

Scenario 2: You couldn't come to your class yesterday. Your professor asked you to provide the valid reasons with proof and submit the documents via an email.

Here, you can't mail your professor like you did for you friend, Tommy. In this case, you need to maintain formality and proper etiquette. You have to provide a formal and legit subject and write the necessary information in the body part. Last but not least, you have to attach your medical records with your email after renaming them with the proper naming convention. Here, you formatted your email as the authority wants!

In the printf()function, we follow the second scenario. If we want to specify any specific printing format/style, we use the printf()function.

Let me give you a short example of how this works:

public class Main{
    public static void main(String[] args) {
        double value = 2.3897;
        System.out.println(value);
        System.out.printf("%.2f" , value);
    }
}

Here, I am declaring a double type variable named value and I am assigning 2.3897 to it. Now when I use the println() function, it prints the whole value with the 4 digits after the radix point.

This is the output:

2.3897
2.39

But after that, when I am using the printf() function, I can modify the output stream of how I want the function to print the value. Here, I am telling the function that I want exactly 2 digits to be printed after the radix point. So the function prints the rounded value up to 2 digits after the radix point.

In this type of scenario, we normally use the printf() function. But keep in mind that it has a wide variety of uses in the Java programming language. I will try to write a detailed article later based on that. 😄

Conclusion

In this article, I have given you a very basic idea about the difference between three print functions in Java. Let me know if this helps you. 😄

If you have any suggestions for me, or if you want to have a little chat with me, then my twitter and LinkedIn accounts are always open for you. Also, make sure to endorse me on LinkedIn if you think I have expertise in the relevant skills. 😊

If you are interested in open-source, then you can also follow me on GitHub, and you can always check out my website and blogs.

I also have two YouTube channels where I try to publish programming related content regularly.

📹 English Brand Channel: Fahim Bin Amin - English
📹 Bengali Brand Channel: Fahim Bin Amin - Bengali
😃 Fun fact: I also teach and mentor students in some popular programming languages.

Thank you!

Original article source at https://www.freecodecamp.org

#java #programming #developer #softwaredeveloper #computerscience 

The Difference Between Three Print Functions in Java