0% found this document useful (0 votes)
6 views

14classes, Modules, Packages

Uploaded by

tej desai
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

14classes, Modules, Packages

Uploaded by

tej desai
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

Department of Mathematical and Physical Sciences

Concordia University of Edmonton

Creating Classes, Modules and Packages


Part 2
Namespace in Python
Namespaces are one honking great idea -- let's do more of those!

 Name (also called identifier) is simply a name given to objects.


Everything in Python is an object. Name is a way to access the
underlying object.
 Namespace is a collection of names.
 In Python, you can imagine a namespace as a mapping of every
name, you have defined, to corresponding objects.
 Different namespaces can co-exist at a given time but are
completely isolated.
 A namespace containing all the built-in names is created when we
start the Python interpreter and exists as long we don't exit.
https://www.programiz.com/python-programming/namespace
2
Namespace in Python
Namespaces are one honking great idea -- let's do more of those!

 This is the reason that built-in functions like id(), print() etc. are
always available to us from any part of the program.
 Each module creates its own global namespace.
 These different namespaces are isolated. Hence, the same name
that may exist in different modules do not collide.
 Modules can have various functions and classes. A local
namespace is created when a function is called, which has all the
names defined in it. Similar, is the case with class. Following
diagram may help to clarify this concept.

https://www.programiz.com/python-programming/namespace
3
Baidya Nath Saha

Namespace in Python
Namespaces are one honking great idea -- let's do more of those!

https://www.programiz.com/python-programming/namespace
4
Design problem

 It is desired to design an object-oriented employee record system for a company.


Each employee has a name, unique id and salary. Employees belong to different
categories and their salary is determined by their category. The functions to get
Name, getld and compute salary are required. Given the class hierarchy below,
possible locations for these functions are: i. getld is implemented in the
superclass ii. getld is implemented in the subclass iii. getName is an abstract
function in the superclass iv. getName is implemented in the superclass v.
getName is implemented in the subclass vi. getSalary is an abstract function in
the superclass vii. getSalary is implemented in the superclass viii. getSalary is
implemented in the subclass

5
Create a class with methods

Choose the best design


A. (i), (iv), (vi), (viii)
B. (i), (iv), (vii)
C. (i), (iii), (v), (vi), (viii)
D. (ii), (v), (viii)

6
Difference between Abstraction
and Encapsulation

Hide
details Hide details
in design in
level implementation
level

7
Class

 Classes provide a means of bundling data and


functionality together.
 Creating a new class creates a new type of object,
allowing new instances of that type to be made.
 Each class instance can have attributes attached to it for
maintaining its state.
 Class instances can also have methods (defined by its
class) for modifying its state.

8
Class

 Compared with other programming languages, Python’s class


mechanism adds classes with a minimum of new syntax and
semantics.
 It is a mixture of the class mechanisms found in C++ and Modula-3.
 Python classes provide all the standard features of Object Oriented
Programming: the class inheritance mechanism allows multiple base
classes, a derived class can override any methods of its base class or
classes, and a method can call the method of a base class with the
same name.
 Objects can contain arbitrary amounts and kinds of data. As is true
for modules, classes partake of the dynamic nature of Python: they
are created at runtime, and can be modified further after creation.

9
Public, Private and Protected Variables

 Classical object-oriented languages, such as C++ and Java, control


the access to class resources by public, private and protected
keywords. Private members of a class are denied access from the
environment outside the class. They can be handled only from
within the class.
 Public members (generally methods declared in a class) are
accessible from outside the class. The object of the same class is
required to invoke a public method. This arrangement of private
instance variables and public methods ensures the principle of data
encapsulation.

10
Public, Private and Protected Variables

 Protected members of a class are accessible from within the class


and are also available to its sub-classes. No other environment is
permitted access to it. This enables specific resources of the parent
class to be inherited by the child class.
 Python doesn't have any mechanism that effectively restricts access
to any instance variable or method. Python prescribes a convention
of prefixing the name of the variable/method with single or double
underscore to emulate the behavior of protected and private access
specifiers.
 All members in a Python class are public by default. Any member
can be accessed from outside the class environment.

11
Example: Public Attributes

 You can access employee class's


class employee: attributes and also modify their
def __init__(self, name, sal): values, as shown below.
self.name=name
self.salary=sal
e1=employee("Kiran",10000)
print(e1.salary)
e1.salary=20000
(e1.salary)

12
Example: Protected Attributes

class employee:
def __init__(self, name, sal):
self._name=name # protected attribute
self._salary=sal # protected attribute

e1=employee(“Swati",10000)
 Python's convention to make an
instance variable protected is to
print(e1._salary)
add a prefix _ (single underscore)
e1._salary=20000
to it. This effectively prevents it
print(e1._salary)
to be accessed, unless it is from
within a sub-class.

13
Example: Protected Attributes

 In fact, this doesn't prevent instance variables from


accessing or modifying the instance.
 Hence, the responsible programmer would refrain from
accessing and modifying instance variables prefixed with _
from outside its class.

14
Example: Private Attributes

class employee:
def __init__(self, name, sal):
self.__name=name # private attribute
self.__salary=sal # private attribute

e1=employee(“Bill",10000)
 Similarly, a double underscore __
prefixed to a variable makes
print(e1.__salary)
it private. It gives a strong
suggestion not to touch it from
AttributeError: 'employee' object
outside the class. Any attempt to
has no attribute '__salary'
do so will result in an Attribute
Error:
15
Private variables

 “Private” instance variables that cannot be accessed except from


inside an object don’t exist in Python. However, there is a
convention that is followed by most Python code: a name prefixed
with an underscore (e.g. _spam) should be treated as a non-public
part of the API (whether it is a function, a method or a data
member). It should be considered an implementation detail and
subject to change without notice.

16
Private variables : Name mangling

 Python performs name mangling of private variables.


Every member with double underscore will be changed
to object._class__variable. If so required, it can still be
accessed from outside the class, but the practice should
be refrained.

E1=employee(“Bill",10000)
print(e1._employ__salary
e1._employee__salary=20000
print(e1._employee__salary)

17
Private variables: Name mangling

 Since there is a valid use-case for class-private members (namely


to avoid name clashes of names with names defined by
subclasses), there is limited support for such a mechanism, called
name mangling. Any identifier of the form __spam (at least two
leading underscores, at most one trailing underscore) is textually
replaced with _classname__spam, where classname is the current
class name with leading underscore(s) stripped. This mangling is
done without regard to the syntactic position of the identifier, as
long as it occurs within the definition of a class.

18
Private variables: Name mangling
 Name mangling is helpful for letting subclasses override methods
without breaking intraclass method calls. For example:
class Mapping: class MappingSubclass(Mapping):
def __init__(self, iterable): def update(self, keys, values):
self.items_list = [] # provides new signature for
self.__update(iterable) update()
def update(self, iterable): # but does not break __init__()
for item in iterable: for item in (keys, values): s
self.items_list.append(item) self.items_list.append(item)
__update = update
# private copy of original update() method

19
Private variables: Name mangling

 The above example would work even if MappingSubclass were to


introduce a __update identifier since it is replaced with
_Mapping__update in the Mapping class and
_MappingSubclass__update in the MappingSubclass class
respectively.
 Note that the mangling rules are designed mostly to avoid
accidents; it still is possible to access or modify a variable that is
considered private. This can even be useful in special
circumstances, such as in the debugger.

20
Private variables: Name mangling

 Notice that code passed to exec() or eval() does not consider


the classname of the invoking class to be the current class;
this is similar to the effect of the global statement, the effect
of which is likewise restricted to code that is byte-compiled
together. The same restriction applies to getattr(), setattr()
and delattr(), as well as when referencing __dict__ directly.

21
Odds and Ends

 Sometimes it is useful to have a data type similar to the


Pascal “record” or C “struct”, bundling together a few
named data items. An empty class definition will do nicely:
class Employee:
pass
john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = 'John Doe‘
john.dept = 'computer lab'
john.salary = 1000

22
Odds and Ends
 A piece of Python code that expects a particular abstract
data type can often be passed a class that emulates the
methods of that data type instead. For instance, if you have
a function that formats some data from a file object, you can
define a class with methods read() and readline() that get the
data from a string buffer instead, and pass it as an argument.

 Instance method objects have attributes, too: m.__self__ is


the instance object with the method m(), and m.__func__ is
the function object corresponding to the method.

23
Iterators
By now you have probably noticed that most container
objects can be looped over using a for statement:

for element in [1, 2, 3]: for char in "123":


print(element) print (char)
for element in (1, 2, 3): for line in ("myfile.txt"):
print(line, end='')
print(element)
for key in {'one':1, 'two':2}:
print(key)

24
Iterators

 This style of access is clear, concise, and convenient.


 The use of iterators pervades and unifies Python.
 Behind the scenes, the for statement calls iter() on the container
object.
 The function returns an iterator object that defines the method
__next__() which accesses elements in the container one at a
time.
 When there are no more elements, __next__() raises a
StopIteration exception which tells the for loop to terminate.
 You can call the __next__() method using the next() built-in
function; this example shows how it all works:

25
Iterators
>>> s = 'abc‘
>>> it = iter (s)
>>> it Having seen the mechanics behind
<iterator object at 0x00A1DB50> the iterator protocol, it is easy to
>>> next(it) add iterator behavior to your
'a'
>>> next(it)
classes. Define an __iter__()
'b' method which returns an object
>>> next(it) with a __next__() method. If the
'c' class defines __next__(), then
>>> next (it) __iter__() can just return self:
Traceback (most recent call last):
File “<stdin>” , line 1, in <module>
next(it)
StopIteration
26
Iterators
class Reverse: >>> rev = Reverse('spam')
"""Iterator for looping over a sequence >>> iter (rev)
backwards."""
<__main__.Reverse object at
def __init__(self, data):
0x00A1DB50>
self.data = data
self.index = len(data) >>> for char in rev:
def __iter__(self): ... Print (char)
return self
...
def __next__(self):
if self.index == 0: m
raise StopIteration a
self.index = self.index - 1 p
return self.data[self.index]
s

27
Generators
 Generators are a simple and powerful tool for creating iterators.
They are written like regular functions but use the yield
statement whenever they want to return data. Each time next()
is called on it, the generator resumes where it left off (it
remembers all the data values and which statement was last
executed). An example shows that generators can be trivially
easy to create: >>> for char in reverse('golf'):
... print (char)
def reverse(data):
...
for index in range(len(data)-1, -1, -1): f
yield data[index] l
o
g

28
Generators
 Anything that can be done with generators can also be done with
class-based iterators as described in the previous section. What
makes generators so compact is that the __iter__() and __next__()
methods are created automatically.
 Another key feature is that the local variables and execution state
are automatically saved between calls. This made the function
easier to write and much more clear than an approach using
instance variables like self.index and self.data.
 In addition to automatic method creation and saving program state,
when generators terminate, they automatically raise StopIteration.
In combination, these features make it easy to create iterators with
no more effort than writing a regular function.

29
Generator Expressions
Some simple generators can be coded succinctly as expressions using
a syntax similar to list comprehensions but with parentheses instead
of square brackets. These expressions are designed for situations
where the generator is used right away by an enclosing function.
Generator expressions are more compact but less versatile than full
generator definitions and tend to be more memory friendly than
equivalent list comprehensions.
Examples:

30
Generator Expressions

>>> sum (i*i for i in range(10)) # sum of squares


285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum (x*y for x,y in (xvec, yvec)) # dot product
260
>>> unique_words = set (word for line in page for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf‘
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']

31

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy