In: Computer Science
For Python, explain as much as you can please
1) What are namespaces and how are they used in Python?
2) What is the difference between Inheritance and Composition?
1) What are namespaces and how are they used in Python?
A name in Python is just a way to access a variable like in any other languages. However, Python is more flexible when it comes to the variable declaration. You can declare a variable by just assigning a name to it.
You can use names to reference values.
num = 5
str = 'Z'
seq = [0, 1, 1, 2, 3, 5]
You can even assign a name to a function.
def function():
print('It is a function.')
foo = function
foo()
You can also assign a name and then reuse it. Check the below example; it is alright for a name to point to different values.
test = -1
print("type <test> :=", type(test))
test = "Pointing to a string now"
print("type <test> :=", type(test))
test = [0, 1, 1, 2, 3, 5, 8]
print("type <test> :=", type(test))
What Are Namespaces In Python?
A namespace is a simple system to control the names in a program. It ensures that names are unique and won’t lead to any conflict. Python implements namespaces in the form of dictionaries. It maintains a name-to-object mapping where names act as keys and the objects as values. Multiple namespaces may have the same name but pointing to a different variable.
Local Namespace
This namespace covers the local names inside a function. Python creates this namespace for every function called in a program. It remains active until the function returns.
Global Namespace
This namespace covers the names from various imported modules used in a project. Python creates this namespace for every module included in your program. It’ll last until the program ends.
Built-in Namespace
This namespace covers the built-in functions and built-in exception names. Python creates it as the interpreter starts and keeps it until you exit.
Example:
# var1 is in the global namespace
var1 = 5
def some_func():
# var2 is in the local namespace
var2 = 6
def some_inner_func():
# var3 is in the nested local namespace
var3 = 7
Mostly, each variable name is checked in the local namespace i.e. the body of the function, the module, etc., and then checked in the global namespace. Variables are generally created only in a local namespace. The global and nonlocal statements can create variables in other than the local namespace.
What Is Scope In Python?
Namespaces make our programs immune from name conflicts. However, it doesn’t give us a free ride to use a variable name anywhere we want. Python restricts names to be bound by specific rules known as a scope. The scope determines the parts of the program where you could use that name without any prefix.
The following code will provide you the basic idea of namespace.
name = 'Andy' # define name
def printBob():
name = 'Bob' # define name in function
print('printing from the def: ', name) # print from function
# the main function
print('printing from the main: ', name) # print from the main
printBob() # call the function to print
The produced output will be
printing from the main:Andy
printing from the def:Bob
So, you can see that two different object has same name but they are in different scope. Hence, their output differs.
2) What is the difference between Inheritance and Composition?
Inheritance and composition are two major concepts in object oriented programming that model the relationship between two classes. They drive the design of an application and determine how the application should evolve as new features are added or requirements change.
Both of them enable code reuse, but they do it in different ways.
Inheritance models what is called an is a relationship. This means that when you have a Derived class that inherits from a Base class, you created a relationship where Derived is a specialized version of Base.
In an inheritance relationship:
Composition is a concept that models a has a relationship. It enables creating complex types by combining objects of other types. This means that a class Composite can contain an object of another class Component. This relationship means that a Composite has a Component.
Classes that contain objects of other classes are usually referred to as composites, where classes that are used to create more complex types are referred to as components. Composition enables you to reuse code by adding objects to other objects, as opposed to inheriting the interface and implementation of other classes.
Let's look at an example of inheritance. In the following example, Rocket is the base class and MarsRover is the inherited class.
class Rocket:
def __init__(self, name, distance):
self.name = name
self.distance = distance
def launch(self):
return "%s has reached %s" % (self.name, self.distance)
class MarsRover(Rocket): # inheriting from the base class
def __init__(self, name, distance, maker):
Rocket.__init__(self, name, distance)
self.maker = maker
def get_maker(self):
return "%s Launched by %s" % (self.name, self.maker)
if __name__ == "__main__":
x = Rocket("simple rocket", "till stratosphere")
y = MarsRover("mars_rover", "till Mars", "ISRO")
print(x.launch())
print(y.launch())
print(y.get_maker())
The output of the code above is shown below:
Documents python rockets.py
simple rocket has reached till stratosphere
mars_rover has reached till Mars
mars_rover Launched by ISRO
In composition, we do not inherit from the base class but establish relationships between classes through the use of instance variables that are references to other objects. Talking in terms of pseudocode you may say that
class GenericClass:
define some attributes and methods
class ASpecificClass:
Instance_variable_of_generic_class = GenericClass
# use this instance somewhere in the class
some_method(Instance_variable_of_generic_class)
So you will instantiate the base class and then use the instance variable for any business logic.
To achieve composition you can instantiate other objects in the class and then use those instances. For example in the below example we instantiate the Rocket class using self.rocket and then using self.rocket in the method get_maker.
class MarsRoverComp():
def __init__(self, name, distance, maker):
self.rocket = Rocket(name, distance) # instantiating the base
self.maker = maker
def get_maker(self):
return "%s Launched by %s" % (self.rocket.name, self.maker)
if __name__ == "__main__":
z = MarsRover("mars_rover2", "till Mars", "ISRO")
print(z.launch())
print(z.get_maker())
The output of the total code which has both inheritance and composition is shown below:
Documents python rockets.py
simple rocket has reached till stratosphere
mars_rover has reached till Mars
mars_rover Launched by ISRO
mars_rover2 has reached till Mars
mars_rover2 Launched by ISRO