Lesson 1

Helpful Materials

Object Oriented Programming:

Classes and Objects in Python:

Python Basics:

Generative Grammar:

Intro to Python

This will be a quick introduction to python and some basics of programming for those people in this project that have not used python or have not really coded before. This introduction is meant to give you an overview of coding, specifically in python. You will have to learn as you go through out this project but this will give you a good foundation to begin with.

What is python?

Python is a high-level object-oriented programming language that was created by Guido van Rossum. It is also called general-purpose programming language as it is used in almost every domain we can think of as mentioned below:

This list can go on as we go but why python is so much popular let’s see it in the next topic.

Why Python Programming?

You guys might have a question in mind that, why python? why not another programming language? So let me explain:

Every Programming language serves some purpose or use-case according to a domain. for example, Javascript is the most popular language amongst web developers as it gives the developer the power to handle applications via different frameworks like react, vue, angular which are used to build beautiful User Interfaces. Similarly, they have pros and cons at the same time. so if we consider python it is general-purpose which means it is widely used in every domain and the reason is it’s very simple to understand and it is scalable because the speed of development is so fast. Now you get the idea why. Besides learning python, it doesn’t require any programming background so that’s why it’s popular amongst developers as well. Python has simpler syntax to the English language and also the syntax allows developers to write programs with fewer lines of code. Since it is open-source there are many libraries available that make developers’ jobs easy ultimately results in high productivity. They can easily focus on business logic and Its demanding skills in the digital era where information is available in large data sets. So that is why we are using it for this programming project. Essentially, it is easy to understand for beginners and relatively easy to write code in. IEEE spectrum list of top programming language 2021. The list of programming languages is based on popularity.

How do we get started?

Now in the era of the digital world, there is a lot of information available on the internet that might confuse us believe me. what we can do is follow the documentation which is a good start point. Once we are familiar with concepts or terminology we can dive deeper into this.

Real-World Examples

1) NASA (National Aeronautics and Space Agency): One of Nasa’s Shuttle Support Contractors, United Space Alliance developed a Workflow Automation System (WAS) which is fast. Internal Resources Within critical project stated that: “Python allows us to tackle the complexity of programs like the WAS without getting bogged down in the language”. Nasa also published a website (https://code.nasa.gov/) where there are 400 open source projects which use python.

2) Netflix: There are various projects in Netflix which use python as follow:

Amongst all projects, Regional failover is the project they have as the system decreases outage time from 45 minutes to 7 minutes with no additional cost.

3) Instagram: Instagram also uses python extensively. They have built a photo-sharing social platform using Django which is a web framework for python. Also, they are able to successfully upgrade their framework without any technical challenges.

Applications of Python Programming

1) Web Development: Python offers different frameworks for web development like Django, Pyramid, Flask. This framework is known for security, flexibility, scalability. 2) Game Development: PySoy and PyGame are two python libraries that are used for game development 3) Artificial Intelligence and Machine Learning: There is a large number of open-source libraries which can be used while developing AI/ML applications. 4) Desktop GUI: Desktop GUI offers many toolkits and frameworks using which we can build desktop applications.PyQt, PyGtk, PyGUI are some of the GUI frameworks.

How to Become Better Programmer

The last but most important thing is how you get better at what programming you choose is practice practice practice. Practical knowledge only acquired by playing with things so you will get more exposure to real-world scenarios. Consistency is more important than anything because if you practice it for some days and then you did nothing then when you start again it will be difficult to practice consistently. So I request you guys to learn by doing projects so it will help you understand how things get done and important thing is to have fun at the same time.

Step 1: Start with a “Hello World” Program

If you happened to learn some programming languages, then I am sure you are aware of what I am talking about. The “Hello World” program is like a tradition in the developer community. If you want to master any programming language, this should be the very first line of code we should be seeking for. Simple Hello World Program in Python:


print("Hello World")

Step 2: Start learning about variables

Now once we have mastered the “Hello World” program in Python, the next step is to master variables in python. Variables are like containers that are used to store values.

Variables in Python:


my_var = 100

Step-3: Start learning about Data Types and Data Structures

The next outpost is to learn about data types. Here I have seen that there is a lot of confusion between data types and data structures. The important thing to keep in mind here is that data types represent the type of data. For example. in Python, we have something like int, string, float, etc. Those are called data types as they indicate the type of data we are dealing with.

While data structures are responsible for deciding how to store this data in a computer’s memory.

String data type in Python:


my_str = "ABCD"

As you can see here, we have assigned a value “ABCD” to a variable my_str. This is basically a string data type in Python.

Data Structure in Python:


my_dict={1:100,2:200,3:300}

This is known as a dictionary data structure in Python. Again this is just the tip of the iceberg. There are lots of data types and data structures in Python. To give a basic idea about data structures in Python, here is the complete list: 1.Lists 2.Dictionary 3.Sets 4.Tuples 5.Frozenset

Step-4: Start learning about conditionals and loops

In any programming language, conditionals and loops are considered one of the backbone. Python is no exception for that as well. This is one of the most important concepts that we need to master. IF-ELIF-ELSE conditionals:


if(x < 10):
    print("x is less than 10")
elif(x > 10):
    print("x is greater than 10")
else:
    print("Do nothing")

As you can see in the above example, we have created what is known as the if-elif-else ladder For loop:


for i in "Python":
    print(i)

The above code is basically an example of for loop in python. While Loop:


While i<2:
    print(i)
    i++

The above code is basically an example of while loop in python.

Intro to Object Oriented Programming

Again this is meant to just provide a basic foundation to move off of on your programming journey and we will continue to learn more in depth as we move forward with the project.

What is object-oriented programming?

Object-oriented programming (OOP) is a method of structuring a program by bundling related properties and behaviors into individual objects. In this tutorial, you’ll learn the basics of object-oriented programming in Python.

Conceptually, objects are like the components of a system. Think of a program as a factory assembly line of sorts. At each step of the assembly line a system component processes some material, ultimately transforming raw material into a finished product.

An object contains data, like the raw or preprocessed materials at each step on an assembly line, and behavior, like the action each assembly line component performs.

What Is Object-Oriented Programming in Python?

Object-oriented programming is a programming paradigm that provides a means of structuring programs so that properties and behaviors are bundled into individual objects.

For instance, an object could represent a person with properties like a name, age, and address and behaviors such as walking, talking, breathing, and running. Or it could represent an email with properties like a recipient list, subject, and body and behaviors like adding attachments and sending. Put another way, object-oriented programming is an approach for modeling concrete, real-world things, like cars, as well as relations between things, like companies and employees, students and teachers, and so on. OOP models real-world entities as software objects that have some data associated with them and can perform certain functions.

Another common programming paradigm is procedural programming, which structures a program like a recipe in that it provides a set of steps, in the form of functions and code blocks, that flow sequentially in order to complete a task.

The key takeaway is that objects are at the center of object-oriented programming in Python, not only representing the data, as in procedural programming, but in the overall structure of the program as well.

Define a Class in Python

Primitive data structures —like numbers, strings, and lists—are designed to represent simple pieces of information, such as the cost of an apple, the name of a poem, or your favorite colors, respectively. What if you want to represent something more complex?

For example, let’s say you want to track employees in an organization. You need to store some basic information about each employee, such as their name, age, position, and the year they started working.

One way to do this is to represent each employee as a list:

kirk = ["James Kirk", 34, "Captain", 2265]
spock = ["Spock", 35, "Science Officer", 2254]
mccoy = ["Leonard McCoy", "Chief Medical Officer", 2266]

There are a number of issues with this approach.

First, it can make larger code files more difficult to manage. If you reference kirk[0] several lines away from where the kirk list is declared, will you remember that the element with index 0 is the employee’s name?

Second, it can introduce errors if not every employee has the same number of elements in the list. In the mccoy list above, the age is missing, so mccoy[1] will return “Chief Medical Officer” instead of Dr. McCoy’s age.

A great way to make this type of code more manageable and more maintainable is to use classes.

Classes vs. Instances

Classes are used to create user-defined data structures. Classes define functions called methods, which identify the behaviors and actions that an object created from the class can perform with its data.

We’ll create a Dog class that stores some information about the characteristics and behaviors that an individual dog can have.

A class is a blueprint for how something should be defined. It doesn’t actually contain any data. The Dog class specifies that a name and an age are necessary for defining a dog, but it doesn’t contain the name or age of any specific dog.

While the class is the blueprint, an instance is an object that is built from a class and contains real data. An instance of the Dog class is not a blueprint anymore. It’s an actual dog with a name, like Miles, who’s four years old.

Put another way, a class is like a form or questionnaire. An instance is like a form that has been filled out with information. Just like many people can fill out the same form with their own unique information, many instances can be created from a single class.

How to define a Class

All class definitions start with the class keyword, which is followed by the name of the class and a colon. Any code that is indented below the class definition is considered part of the class’s body.

Here’s an example of a Dog class:


class Dog:
    pass

The body of the Dog class consists of a single statement: the pass keyword. pass is often used as a placeholder indicating where code will eventually go. It allows you to run this code without Python throwing an error.

There are a number of properties that we can choose from, including name, age, coat color, and breed. To keep things simple, we’ll just use name and age. The properties that all Dog objects must have are defined in a method called .__init__(). Every time a new Dog object is created, .__init__() sets the initial state of the object by assigning the values of the object’s properties. That is, .__init__() initializes each new instance of the class.

You can give .__init__() any number of parameters, but the first parameter will always be a variable called self. When a new class instance is created, the instance is automatically passed to the self parameter in .__init__() so that new attributes can be defined on the object.

Let’s update the Dog class with an .__init__() method that creates .name and .age attributes:


class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

Notice that the .__init__() method’s signature is indented four spaces. The body of the method is indented by eight spaces. This indentation is vitally important. It tells Python that the .__init__() method belongs to the Dog class.

In the body of .__init__(), there are two statements using the self variable:

  1. self.name = name creates an attribute called name and assigns to it the value of the name parameter.
  2. self.age = age creates an attribute called age and assigns to it the value of the age parameter.

Attributes created in .__init__() are called instance attributes. An instance attribute’s value is specific to a particular instance of the class. All Dog objects have a name and an age, but the values for the name and age attributes will vary depending on the Dog instance.

On the other hand, class attributes are attributes that have the same value for all class instances. You can define a class attribute by assigning a value to a variable name outside of .__init__().

For example, the following Dog class has a class attribute called species with the value “Canis familiaris”:


class Dog:
    # Class attribute
    species = "Canis familiaris"

    def __init__(self, name, age):
        self.name = name
        self.age = age

Class attributes are defined directly beneath the first line of the class name and are indented by four spaces. They must always be assigned an initial value. When an instance of the class is created, class attributes are automatically created and assigned to their initial values.

Use class attributes to define properties that should have the same value for every class instance. Use instance attributes for properties that vary from one instance to another.

Now that we have a Dog class, let’s create some dogs!

Instantiate an Object in Python

Creating a new object from a class is called instantiating an object. You can instantiate a new Dog object by typing the name of the class, followed by opening and closing parentheses:


>>>
>>> Dog()
<__main__.Dog object at 0x106702d30>

You now have a new Dog object at 0x106702d30. This funny-looking string of letters and numbers is a memory address that indicates where the Dog object is stored in your computer’s memory. Note that the address you see on your screen will be different. Now instantiate a second Dog object:

>>>
>>> Dog()
<__main__.Dog object at 0x0004ccc90>

The new Dog instance is located at a different memory address. That’s because it’s an entirely new instance and is completely unique from the first Dog object that you instantiated. To see this another way, type the following:

>>>
>>> a = Dog()
>>> b = Dog()
>>> a == b
False

In this code, you create two new Dog objects and assign them to the variables a and b. When you compare a and b using the == operator, the result is False. Even though a and b are both instances of the Dog class, they represent two distinct objects in memory.

Class and Instance Attributes

Now time to create a new Dog class with a class attribute called .species and two instance attributes called .name and .age:

>>> class Dog:
...     species = "Canis familiaris"
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age

To instantiate objects of this Dog class, you need to provide values for the name and age. If you don’t, then Python raises a TypeError:


>>> Dog()
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    Dog()
TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'

To pass arguments to the name and age parameters, put values into the parentheses after the class name:

>>> buddy = Dog("Buddy", 9)
>>> miles = Dog("Miles", 4)

This creates two new Dog instances—one for a nine-year-old dog named Buddy and one for a four-year-old dog named Miles. The Dog class’s .__init__() method has three parameters, so why are only two arguments passed to it in the example? When you instantiate a Dog object, Python creates a new instance and passes it to the first parameter of .__init__(). This essentially removes the self parameter, so you only need to worry about the name and age parameters. After you create the Dog instances, you can access their instance attributes using dot notation:

>>> buddy.name
'Buddy'
>>> buddy.age
9
>>> miles.name
'Miles'
>>> miles.age
4

You can access class attributes the same way:

>>> buddy.species
'Canis familiaris'

One of the biggest advantages of using classes to organize data is that instances are guaranteed to have the attributes you expect. All Dog instances have .species, .name, and .age attributes, so you can use those attributes with confidence knowing that they will always return a value. Although the attributes are guaranteed to exist, their values can be changed dynamically:

>>> buddy.age = 10
>>> buddy.age
10

>>> miles.species = "Felis silvestris"
>>> miles.species
'Felis silvestris'

In this example, you change the .age attribute of the buddy object to 10. Then you change the .species attribute of the miles object to “Felis silvestris”, which is a species of cat. That makes Miles a pretty strange dog, but it is valid Python! The key takeaway here is that custom objects are mutable by default. An object is mutable if it can be altered dynamically. For example, lists and dictionaries are mutable, but strings and tuples are immutable

Instance Methods

Instance methods are functions that are defined inside a class and can only be called from an instance of that class. Just like .__init__(), an instance method’s first parameter is always self.

class Dog:
    species = "Canis familiaris"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    # Instance method
    def description(self):
        return f"{self.name} is {self.age} years old"

    # Another instance method
    def speak(self, sound):
        return f"{self.name} says {sound}"

This Dog class has two instance methods:

  1. .description() returns a string displaying the name and age of the dog.
  2. .speak() has one parameter called sound and returns a string containing the dog’s name and the sound the dog makes.
>>> miles = Dog("Miles", 4)

>>> miles.description()
'Miles is 4 years old'

>>> miles.speak("Woof Woof")
'Miles says Woof Woof'

>>> miles.speak("Bow Wow")
'Miles says Bow Wow'

In the above Dog class, .description() returns a string containing information about the Dog instance miles. When writing your own classes, it’s a good idea to have a method that returns a string containing useful information about an instance of the class. However, .description() isn’t the most pythonic way of doing this. When you create a list object, you can use print() to display a string that looks like the list:

>>> names = ["Fletcher", "David", "Dan"]
>>> print(names)
['Fletcher', 'David', 'Dan']

Let’s see what happens when you print() the miles object:

>>> print(miles)
<__main__.Dog object at 0x00aeff70>

When you print(miles), you get a cryptic looking message telling you that miles is a Dog object at the memory address 0x00aeff70. This message isn’t very helpful. You can change what gets printed by defining a special instance method called .__str__().

class Dog:
    # Leave other parts of Dog class as-is

    # Replace .description() with __str__()
    def __str__(self):
        return f"{self.name} is {self.age} years old"
>>>
>>> miles = Dog("Miles", 4)
>>> print(miles)
'Miles is 4 years old'

Methods like .__init__() and .__str__() are called dunder methods because they begin and end with double underscores. There are many dunder methods that you can use to customize classes in Python. Although too advanced a topic for a beginning Python book, understanding dunder methods is an important part of mastering object-oriented programming in Python.

Intro to Generative Language

What is Generative Grammar?

In linguistics, generative grammar is grammar (the set of language rules) that indicates the structure and interpretation of sentences that native speakers of a language accept as belonging to their language.

Adopting the term generative from mathematics, linguist Noam Chomsky introduced the concept of generative grammar in the 1950s. This theory is also known as transformational grammar, a term still used today.

Grammar refers to the set of rules that structure a language, including syntax (the arrangement of words to form phrases and sentences) and morphology (the study of words and how they are formed). Generative grammar is a theory of grammar that holds that human language is shaped by a set of basic principles that are part of the human brain (and even present in the brains of small children). This “universal grammar,” according to linguists like Chomsky, comes from our innate language faculty.

In Linguistics for Non-Linguists: A Primer With Exercises, Frank Parker and Kathryn Riley argue that generative grammar is a kind of unconscious knowledge that allows a person, no matter what language they speak, to form “correct” sentences. They continue: “Simply put, a generative grammar is a theory of competence: a model of the psychological system of unconscious knowledge that underlies a speaker’s ability to produce and interpret utterances in a language … A good way of trying to understand [Noam] Chomsky’s point is to think of a generative grammar as essentially a definition of competence: a set of criteria that linguistic structures must meet to be judged acceptable,” (Parker and Riley 2009).

Generative Vs. Prescriptive Grammar

Generative grammar is distinct from other grammars such as prescriptive grammar, which attempts to establish standardized language rules that deem certain usages “right” or “wrong,” and descriptive grammar, which attempts to describe language as it is actually used (including the study of pidgins and dialects). Instead, generative grammar attempts to get at something deeper—the foundational principles that make language possible across all of humanity. For example, a prescriptive grammarian may study how parts of speech are ordered in English sentences, with the goal of laying out rules (nouns precede verbs in simple sentences, for example). A linguist studying generative grammar, however, is more likely to be interested in issues such as how nouns are distinguished from verbs across multiple languages.

Principles of Generative Grammar

The main principle of generative grammar is that all humans are born with an innate capacity for language and that this capacity shapes the rules for what is considered “correct” grammar in a language. The idea of an innate language capacity—or a “universal grammar”—is not accepted by all linguists. Some believe, to the contrary, that all languages are learned and, therefore, based on certain constraints. Proponents of the universal grammar argument believe that children, when they are very young, are not exposed to enough linguistic information to learn the rules of grammar. That children do in fact learn the rules of grammar is proof, according to some linguists, that there is an innate language capacity that allows them to overcome the “poverty of the stimulus.”

Examples of Generative Grammar

As generative grammar is a “theory of competence,” one way to test its validity is with what is called a grammaticality judgment task. This involves presenting a native speaker with a series of sentences and having them decide whether the sentences are grammatical (acceptable) or ungrammatical (unacceptable). For example:

A native speaker would judge the first sentence to be acceptable and the second to be unacceptable. From this, we can make certain assumptions about the rules governing how parts of speech should be ordered in English sentences. For instance, a “to be” verb linking a noun and an adjective must follow the noun and precede the adjective.

To Do

All that needs to be done for now is to download Anaconda and the proper libraries to begin the coding portion of the project starting next lesson. You may review this lesson on the IEEE website if you would like to again to hammer down the background material.

If you are having any issues with this process feel free to email me any time for assitance. alynch@ucsbieee.org