#66DayOfData: Day 4

Tyler Nardone
4 min readJan 7, 2022

A Review of What I Learned Today

I am now on day 4 of my first round of #66DaysOfData. My first 3 days involved a lot of review of basics of Python and SQL but today I started diving in deeper to Python.

Following Codecademy’s Intermediate Python 3 course I started to explore some concepts that, while tricky to grasp initially, open up immense possibility for developing with Python as well as just reading other peoples’ code. These include namespaces and scope, lambda functions, higher-order functions, decorators, and the four-pillars of object-oriented programming.

Namespaces and Scope

Any program is likely to have variables — symbolic names assigned to objects. Python keeps track of these name associations in a namespace so that we can recall these objects using their names. As a program grows in complexity it is very easy for there to be 100s or even 1000s of names being used. The chance of error multiplies as we messing up our name assignments.

To make things less messy Python provides four different namespaces.

  1. Built-in namespace: contains references for all of Python’s built-in objects. Accessed with dir(__builtins__) . Includes exceptions, built in functions like len and print and objects like int and list .
  2. Global namespace: has all user-defined names at the level of the main program and names of imported modules. Can see by calling globals()
  3. Local namespace: possesses all those names defined within a function definition. Can be seen by calling locals() . A new namespace is created each time a function is called.
  4. Enclosing namespace: When a function is nested within another function the inner function has its own local namespace, and the outer function (enclosing function) has the enclosing namespace.

Scope is the set of rules that specifies when each namespace is available in your program.

LEGB rule

Local, enclosing, global, built-in. This is the order that the python interpreter looks through namespaces when a variable name is called.

By using multiple namespaces and well-defined rules for which namespaces are accessed in different parts of our program we have a powerful tool for organizing our code and allowing us to increase complexity.

Lambda Functions

Allows you to define anonymous functions in one line. Most useful for when you need a one-time use throwaway function. Best example is when defining a function to pass into higher-order functions like map() or filter() .

Higher-Order Functions and Decorators

Functions are “first-order objects” in python, just like things such as ints, lists, strings, etc. And just like those objects functions can be passed as arguements to or returned by functions. Those latter functions are higher-order functions. As with the other concepts learned today, higher-order functions allow for better organized and more complex programs with less code.

Map, filter, and reduce are 3 major built-in higher-order functions. Each takes in a function than an iterable object. I may dive deeper into these at a later time.

Object-Oriented-Programming

Coding paradigms are a deep topic, they offer different ways of conceptually organizing programs. OOP is a popular paradigm in modern programming, and consists of organizing programs into objects which contain relative data and functions together. Objects are realized versions of the more abstract Class which defines them. Classes are the blueprint, specifying what kind of data and associated functions (methods) every object of that class will have. Objects are the things that are created and physically stored in memory with their own data.

Different languages cater to particular programming paradigms at varying degrees of restriction. For example, Java is a strictly OOP language that requires everything to be defined as a class, Haskell is a strictly functional programming language, while many others allow for a mix of either e.g. Kotlin, Scala, JavaScript, and Python to name a few.

OOP has 4 main “pillars”, concepts that one should try to adhere to in order to get the most out of their program structure.

  1. Inheritance: classes can be made as subclasses to another class. By doing this the subclass (child class) inherits all the attributes and methods of the superclass (parent class). The subclass can then add other methods or attributes as suited, or override the parent methods and attributes. This allows the creation of many related classes while saving on code!
  2. Encapsulation: The data and the methods of an object are enclosed within that object. They are accesssed by that object and otherwise unaccessible to other parts of the program except in the ways the programmer wishes to define. OOP languages often allow you to specify attributes and methods as private or public, private meaning they cannot be accessed outside of the object. Python does not have this feature and it is common practice to define an attribute like ._<attribute> or .__<attribute> to let other programmers know that these are not meant to be accessed outside the object.
  3. Abstraction: All the complexity behind how an object operates is abstracted away. We should be able to work with that object by calling some of its methods and checking its attributes without having to worry how anything is implemented, this is related to encapsulation and polymorphism.
  4. Polymorphism: Methods with the same name can be called, and do different things under different circumstances. A child class can override the funtionality of a parent method. As objects interface with each other through method calls, we can swap out objects but keep the same interfaces in our code.

--

--

Tyler Nardone

BS Physics and Biology. Passionate about ecology, sustainability. Constantly learning Python, SQL, Computer Science, and Data Analysis.