Вы находитесь на странице: 1из 6

LAB 8: Static Methods and class Methods, object memory management

Class Method in Python


The @classmethod decorator, is a built-in function decorator that is an expression that gets
evaluated after your function is defined. The result of that evaluation shadows your function
definition.
A class method receives the class as implicit first argument, just like an instance method receives
the instance
Syntax:
class C(object):
@classmethod
def fun(cls, arg1, arg2, ...):
....
fun: function that needs to be converted into a class method
returns: a class method for function.
● A class method is a method which is bound to the class and not the object of the class.
● They have the access to the state of the class as it takes a class parameter that points to the
class and not the object instance.
● It can modify a class state that would apply across all the instances of the class. For example
it can modify a class variable that will be applicable to all the instances.

Static Method in Python


A static method does not receive an implicit first argument.
Syntax:
class C(object):
@staticmethod
def fun(arg1, arg2, ...):
...
returns: a static method for function fun.
● A static method is also a method which is bound to the class and not the object of the class.
● A static method can’t access or modify class state.
● It is present in a class because it makes sense for the method to be present in class.

Class method vs Static Method


● A class method takes cls as first parameter while a static method needs no specific
parameters.
● A class method can access or modify class state while a static method can’t access or modify
it.
● In general, static methods know nothing about class state. They are utility type methods that
take some parameters and work upon those parameters. On the other hand class methods
must have class as parameter.
● We use @classmethod decorator in python to create a class method and we use
@staticmethod decorator to create a static method in python.

When to use what?


● We generally use class method to create factory methods. Factory methods return class
object (similar to a constructor) for different use cases.
● We generally use static methods to create utility functions.

How to define a class method and a static method?


To define a class method in python, we use @classmethod decorator and to define a static
method we use @staticmethod decorator.
Let us look at an example to understand the difference between both of them. Let us say we want
to create a class Person. Now, python doesn’t support method overloading like C++ or Java so we
use class methods to create factory methods. In the below example we use a class method to
create a person object from birth year.
As explained above we use static methods to create utility functions. In the below example we use
a static method to check if a person is adult or not.
Implementation
# Python program to demonstrate
# use of class method and static method.
from datetime import date

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

# a class method to create a Person object by birth year.


@classmethod
def fromBirthYear(cls, name, year):
return cls(name, date.today().year - year)

# a static method to check if a Person is adult or not.


@staticmethod
def isAdult(age):
return age > 18

person1 = Person('mayank', 21)


person2 = Person.fromBirthYear('mayank', 1996)

print(person1.age)
print(person2.age)

# print the result


print(Person.isAdult(22))
Output
21
23
True

Object Memory Management in Python


Python’s memory allocation and deallocation method is automatic. The user does not have to
preallocate or deallocate memory similar to using dynamic memory allocation in languages such
as C or C++.
Python uses two strategies for memory allocation:
● Reference counting
● Garbage collection
Prior to Python version 2.0, the Python interpreter only used reference counting for memory
management. Reference counting works by counting the number of times an object is referenced
by other objects in the system. When references to an object are removed, the reference count for
an object is decremented. When the reference count becomes zero, the object is deallocated. Ex-
# Literal 9 is an object
b=9

# Reference count of object 9


# becomes 0.
b=4
The literal value 9 is an object. The reference count of object 9 is incremented to 1 in line 1. In line
2 its reference count becomes zero as it is dereferenced. So garbage collector deallocates the
object.
A reference cycle is created when there is no way the reference count of the object can reach.
Reference cycles involving lists, tuples, instances, classes, dictionaries, and functions are
common. The easiest way to create a reference cycle is to create an object which refers to itself
as in the example below:
def create_cycle():

# create a list x
x=[]

# A reference cycle is created


# here as x contains reference to
# to self.
x.append(x)

create_cycle()
Because create_cycle() creates an object x which refers to itself, the object x will not automatically
be freed when the function returns. This will cause the memory that x is using to be held onto until
the Python garbage collector is invoked.

Ways to make an object eligible for garbage collection


x = []
x.append(1)
x.append(2)

# delete the list from memory or


# assigning object x to None(Null)
del x
# x = None
The reference count for the list created is now two. However, since it cannot be reached from
inside Python and cannot possibly be used again, it is considered garbage. In the current version
of Python, this list is never freed.
Automatic Garbage Collection of Cycles
Because reference cycles take computational work to discover, garbage collection must be a
scheduled activity. Python schedules garbage collection based upon a threshold of object
allocations and object deallocations. When the number of allocations minus the number of
deallocations is greater than the threshold number, the garbage collector is run. One can inspect
the threshold for new objects (objects in Python known as generation 0 objects) by importing the
gc module and asking for garbage collection thresholds:
# loading gc
import gc

# get the current collection


# thresholds as a tuple
print("Garbage collection thresholds:",
gc.get_threshold())
Output:
Garbage collection thresholds: (700, 10, 10)
Here, the default threshold on the above system is 700. This means when the number of
allocations vs. the number of deallocations is greater than 700 the automatic garbage collector will
run. Thus any portion of your code which frees up large blocks of memory is a good candidate for
running manual garbage collection.
Manual Garbage Collection
Invoking the garbage collector manually during the execution of a program can be a good idea on
how to handle memory being consumed by reference cycles.
The garbage collection can be invoked manually in the following way:
# Importing gc module
import gc

# Returns the number of


# objects it has collected
# and deallocated
collected = gc.collect()

# Prints Garbage collector


# as 0 object
print("Garbage collector: collected",
"%d objects." % collected)
If few cycles are created, then how manual collection works:
Example:
import gc
i=0

# create a cycle and on each iteration x as a dictionary


# assigned to 1
def create_cycle():
x={}
x[i+1] = x
print(x)

# lists are cleared whenever a full collection or


# collection of the highest generation (2) is run
collected = gc.collect() # or gc.collect(2)
print("Garbage collector: collected "+str(collected)+" objects.")

print("Creating cycles...")
for i in range(10):
create_cycle()

collected = gc.collect()

print("Garbage collector: collected "+str(collected)+" objects.")

Output:
Garbage collector: collected 0 objects.
Creating cycles...
{1: {...}}
{2: {...}}
{3: {...}}
{4: {...}}
{5: {...}}
{6: {...}}
{7: {...}}
{8: {...}}
{9: {...}}
{10: {...}}
Garbage collector: collected 10 objects.
There are two ways for performing manual garbage collection: time-based and event-based
garbage collection.
Time-based garbage collection is simple: the garbage collector is called after a fixed time interval.
Event-based garbage collection calls the garbage collector on event occurrence. For example,
when a user exits the application or when the application enters into idle state.

Write flowchart and Python code on lab notebook ONLY for the below 2 problems and get them
signed by your lab TAs

1. Create a “Calculator class” with following


a. class variables a,b
b. display(result) as a static member function - it will display the result of a class.
c. sum(a,b) as a static member function.
d. modify(a,b,c) as a class method, that will modify the class state as
i. a = a - b
ii. b = c
Create a main, instance using the class method modify and pass variables a,b,c and
display the a-b+c.

2.
2. Design and implement the Class Structure for the following requirement.
a. Software to grade a student’s performance in 6 subjects.
b. Marks for subjects are to be entered by user.
c. Assume max marks for each subject is 100.
d. Design your own grading logic. (Scale of 0-10)
e. If subjects written by student is less than 6, inform the principal that grade cannot
be calculated.
f. Inform that a student has been debarred, when a student has a grade less than
equal to 4

Practice Problems:

1. Briefly describe a possible collection of classes which can be used to represent a music collection (for
example, inside a music player), focusing on how they would be related by composition. You should
include classes for songs, artists, albums and playlists. Hint: write down the four class names, draw a
line between each pair of classes which you think should have a relationship, and decide what kind of
relationship would be the most appropriate.

For simplicity you can assume that any song or album has a single “artist” value (which could represent
more than one person), but you should include compilation albums (which contain songs by a selection of
different artists). The “artist” of a compilation album can be a special value like “Various Artists”. You can
also assume that each song is associated with a single album, but that multiple copies of the same song
(which are included in different albums) can exist.

Write a simple implementation of this model which clearly shows how the different classes are composed.
Write some example code to show how you would use your classes to create an album and add all its
songs to a playlist. Hint: if two objects are related to each other bidirectional, you will have to decide how
this link should be formed – one of the objects will have to be created before the other, so you can’t link
them to each other in both directions simultaneously.

2. Create a problem of reference cycle by creating two lists (of your choice) which are referencing each
other. Make them eligible for garbage collection. Print the the garbage collection threshold value,
number of objects collected by garbage collector and total number of objects in each generation before
and after the execution of garbage collection.

3. Write an “abstract” class, Box, and use it to define some methods which any box object should have:
add, for adding any number of items to the box, empty, for taking all the items out of the box and
returning them as a list, and count, for counting the items which are currently in the box. Write a simple
Item class which has a name attribute and a value attribute – you can assume that all the items you will
use will be Item objects. Now write two subclasses of Box which use different underlying collections to
store items: ListBox should use a list, and DictBox should use a dict.

Write a function, repack_boxes, which takes any number of boxes as parameters, gathers up all the
items they contain, and redistributes them as evenly as possible over all the boxes. Order is unimportant.
There are multiple ways of doing this. Test your code with a ListBox with 20 items, a ListBox with 9 items
and a DictBox with 5 items. You should end up with two boxes with 11 items each, and one box with 12
items.

Вам также может понравиться