How to Loop initilized attributes inside an class definition body?
Supposed a class:
class WakeUp:
def __init__(self,date,time):
self.date = str(date)
self.time = str(time)
self.brush_teeth = brushteeth
.
.
def get_wakeup_activities(self):
return 'date: ' + self.date + 'time' + self.time. + 'brush_teeth', + self.brush_teeth
I intend to avoid the verbose typing, expect to refactor the method as:
def get_wakeup_activities(self):
act_list = ()
for attr in attrs:
act_list.append(attr)
return 'date: %s time:%s brush_teeth: %s' %tuple(act_list)
When the method is called, outputs
date:2017-10-17 time:11:50:27 ...
or more abstract:
def get_wakeup_activities(self):
wakeup_dict = {k:v for k, v in self.attrs}
return wakeup_dict
While command to call:
today_wakeup = Wakeup
today_wakeup.get_wakeup_activities()
Outputs:
{date:2017-10-17, time:11:50:27,....}
class WakeUp:
def __init__(self,date,time, brushteeth):
self.date = str(date)
self.time = str(time)
self.brush_teeth = brushteeth
def get_wakeup_activities(self):
return self.__dict__
today_wakeup = WakeUp('today', '8am', 'YES!')
print(today_wakeup.get_wakeup_activities())
Related
I want to call the file object from decorator to the wrapped function . may codes as below :
from functools import wraps
checkresultfile = './test.txt'
def log_detection_res(detect_items = ''):
def process_reminder_decorator(check_func):
#wraps(check_func)
def addingReminder(*args, **kwargs):
process_begin_reminder = "=" * 10 + detect_items + "start" + "=" * 10
process_stop_reminder = "=" * 10 + detect_items + "end" + "=" * 10
with open(checkresultfile, 'a') as res_file:
res_file.write(process_begin_reminder + '\n')
check_func(*args, **kwargs)
res_file.write(process_stop_reminder + '\n')
return check_func(*args, **kwargs)
return addingReminder
return process_reminder_decorator
#log_detection_res(detect_items = 'filter odd')
def print_odd(array_a):
for _ in array_a:
if _ % 2 == 0:
checkresultfile.write(_)
filter_dd = print_odd([1,2,3,4,5])
out_put
line 21, in print_odd
checkresultfile.write(_)
AttributeError: 'str' object has no attribute 'write'
The error comes due to checkresultfile is a str not file object, the error parts can be fixed by as below :
def print_odd(array_a):
with open (checkresultfile, 'a') as f:
for _ in array_a:
if _ % 2 == 0:
f.write(str(_))
I don't want ot use with open ... as ... in the wrapped function but call the res_file in decorator , is that reliable in such situation ?
Below way works:
from functools import wraps
checkresultfile = './test.txt'
def log_detection_res(detect_items = ''):
def process_reminder_decorator(check_func):
#wraps(check_func)
def addingReminder(*args, **kwargs):
process_begin_reminder = "=" * 10 + detect_items + "start" + "=" * 10
process_stop_reminder = "=" * 10 + detect_items + "end" + "=" * 10
with open(checkresultfile, 'a') as res_file:
res_file.write(process_begin_reminder + '\n')
#adding a key parameter to refer to file object res_file in decorator
check_func(output_file = res_file, *args, **kwargs)
res_file.write(process_stop_reminder + '\n')
return check_func
return addingReminder
return process_reminder_decorator
#log_detection_res(detect_items = 'filter odd')
def print_odd(array_a, output_file):
for _ in array_a:
if _ % 2 == 0:
output_file.write(_)
filter_dd = print_odd(array_a = [1,2,3,4,5])
Is there any difference between the following two codes related to initializing a class in Python?
class summation:
def __init__(self, f, s):
self.first = f
self.second = s
self.summ = self.first + self.second
.
.
.
class summation:
def __init__(self, f, s):
self.first = f
self.second = s
self.summ = f + s
.
.
.
If there exists any difference, what is that, and which code is preferable?
Edit: I am going to write an artificial neural network with Python (and Pytorch). In fact, the above two codes are just some examples. In the actual case, I have seen in various resources that when there exists self.input = input in the initialization of a class, in other parts it is used as self.input, not input.
My questions: What are the differences between these two approaches? Why is the use of self.input preferable, in my case?
Example: (from https://docs.dgl.ai/en/latest/tutorials/models/1_gnn/4_rgcn.html#sphx-glr-tutorials-models-1-gnn-4-rgcn-py)
import torch
import torch.nn as nn
import torch.nn.functional as F
from dgl import DGLGraph
import dgl.function as fn
from functools import partial
class RGCNLayer(nn.Module):
def __init__(self, in_feat, out_feat, num_rels, num_bases=-1, bias=None,
activation=None, is_input_layer=False):
super(RGCNLayer, self).__init__()
self.in_feat = in_feat
self.out_feat = out_feat
self.num_rels = num_rels
self.num_bases = num_bases
self.bias = bias
self.activation = activation
self.is_input_layer = is_input_layer
# sanity check
if self.num_bases <= 0 or self.num_bases > self.num_rels:
self.num_bases = self.num_rels
# weight bases in equation (3)
self.weight = nn.Parameter(torch.Tensor(self.num_bases, self.in_feat,
self.out_feat))
if self.num_bases < self.num_rels:
# linear combination coefficients in equation (3)
self.w_comp = nn.Parameter(torch.Tensor(self.num_rels, self.num_bases))
# add bias
if self.bias:
self.bias = nn.Parameter(torch.Tensor(out_feat))
# init trainable parameters
nn.init.xavier_uniform_(self.weight,
gain=nn.init.calculate_gain('relu'))
if self.num_bases < self.num_rels:
nn.init.xavier_uniform_(self.w_comp,
gain=nn.init.calculate_gain('relu'))
if self.bias:
nn.init.xavier_uniform_(self.bias,
gain=nn.init.calculate_gain('relu'))
def forward(self, g):
if self.num_bases < self.num_rels:
# generate all weights from bases (equation (3))
weight = self.weight.view(self.in_feat, self.num_bases, self.out_feat)
weight = torch.matmul(self.w_comp, weight).view(self.num_rels,
self.in_feat, self.out_feat)
else:
weight = self.weight
if self.is_input_layer:
def message_func(edges):
# for input layer, matrix multiply can be converted to be
# an embedding lookup using source node id
embed = weight.view(-1, self.out_feat)
index = edges.data['rel_type'] * self.in_feat + edges.src['id']
return {'msg': embed[index] * edges.data['norm']}
else:
def message_func(edges):
w = weight[edges.data['rel_type']]
msg = torch.bmm(edges.src['h'].unsqueeze(1), w).squeeze()
msg = msg * edges.data['norm']
return {'msg': msg}
def apply_func(nodes):
h = nodes.data['h']
if self.bias:
h = h + self.bias
if self.activation:
h = self.activation(h)
return {'h': h}
g.update_all(message_func, fn.sum(msg='msg', out='h'), apply_func)
No. there is no difference between these two approaches in your case with this level of information. but could they? Yes. they could. if they have some modifications in their setters or getters. later in my answer I'll show you how.
First of all, I prefer using this one:
class summation:
def __init__(self, f, s):
self.first = f
self.second = s
#property
def summ(self):
return self.first+self.second
the above implementation calculates the summation on demand. so when you change self.first or self.second, summ will be calculated automatically. you can access the sum as you did before.
s = summation(1,9)
print(s.summ)
# 10
s.first = 2
s.second = 3
print(s.summ)
# 5
So, How could they be different?
let's implements them as follows. in setters I doubled the inputs to show you how setters can affect the results. it's just an imaginary example and is not exactly what you wrote.
class summation1:
def __init__(self, f, s):
self.first = f
self.second = s
self.summ = self.first + self.second
#property
def first(self):
return self.__first
#first.setter
def first(self,f):
self.__first = f*2
#property
def second(self):
return self.__second
#second.setter
def second(self,s):
self.__second = s*2
class summation2:
def __init__(self, f, s):
self.first = f
self.second = s
self.summ = f + s
#property
def first(self):
return self.__first
#first.setter
def first(self,f):
self.__first = f*2
#property
def second(self):
return self.__second
#second.setter
def second(self,s):
self.__second = s*2
now let's take a look at the outputs:
a = 3
b = 2
s1 = summation1(a,b)
s2 = summation2(a,b)
print(s1.summ)
# 10
print(s2.summ)
# 5
so, if you are not sure what to choose between those two, maybe the first approach is what you need.
I want to expand the following code in order to calculate the miligrams too. Can someone tell me how to?
class weight:
__metric = {"g" : 1,
"kg" : 1000,
}
def __init__(self, value, unit = "g"):
self.value = value
self.unit = unit
def convert_to_gram(self):
return self.value * weight._metric[self.unit]
def __add__(self,other):
x = self.convert_to_gram() + other.convert_to_gram()
return weight + (x/weight._metric[self.unit], self.unit)
def __str__(self):
return "{} {}".format (self.value, self.unit)
class weight:
def __init__(self, value, unit = "g"):
"""
This method is initialized when the object is created
"""
self.value = value
self.unit = unit
# The value of kg is 0.001 (1E-3) because your logic multiplies the input value. So mg must be 1/1E-3 = 1000
self._metric = {"g" : 1,
"kg" : 0.001,
"mg" : 1000
}
def convert_to_gram(self):
"""
This method converts a self.value to g, kg or mg based on self.unit
"""
return self.value * self._metric[self.unit]
def __add__(self, other):
"""
The __add__ method is a 'magic' (dunder) method which gets called when we add two numbers using the + operator.
this method calls convert_to_gram() methods from this class object and from 'other' class object as well
it then returns the sum of both convertion results from the two objects
"""
x = self.convert_to_gram() + other.convert_to_gram()
return (x/self._metric[self.unit], self.unit)
def __str__(self):
return "{} {}".format (self.value, self.unit)
w1 = weight(100, 'mg') # create object w1
w2 = weight(50, 'mg') # create object w2
# call convert_to_gram() to convert 100 to mg and save the result in result_w1
result_w1 = w1.convert_to_gram()
print(result_w1)
# call convert_to_gram() to convert 50 to mg and save the result in result_w2
result_w2 = w2.convert_to_gram()
print(result_w2)
print(w1 + w2)
Gives:
100000
50000
(150.0, 'mg')
I'm learning Python from this lecture: Lec 19 | MIT 6.00 Introduction to Computer Science and Programming. I'm using Python 3.6.2, lecture example runs on Python 2.x. Whats the proper way to set values of x and y in function ans_quest?
x, y = loc_list[-1].get_coords()
Can this method be called like this? This was the example in the lecture.
Full code:
import math, random, pylab, copy
class Location(object):
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
def move(self, xc, yc):
return Location(self.x+float(xc), self.y+float(yc))
def get_coords(self):
return self.x, self.y
def get_dist(self, other):
ox, oy = other.get_coords()
x_dist = self.x - ox
y_dist = self.y - oy
return math.sqrt(x_dist**2 + y_dist**2)
class Compass_Pt(object):
possibles = ('N', 'S', 'E', 'W')
def __init__(self, pt):
if pt in self.possibles: self.pt = pt
else: raise ValueError('in Compass_Pt.__init__')
def move(self, dist):
if self.pt == 'N': return (0, dist)
elif self.pt == 'S': return (0, -dist)
elif self.pt == 'E': return (dist, 0)
elif self.pt == 'W': return (-dist, 0)
else: raise ValueError('in Compass_Pt.move')
class Field(object):
''' Cartesian plane where object will be located '''
def __init__(self, drunk, loc):
self.drunk = drunk
self.loc = loc
def move(self, cp, dist):
old_loc = self.loc
xc, yc = cp.move(dist)
self.loc = old_loc.move(xc, yc)
def get_loc(self):
return self.loc
def get_drunk(self):
return self.drunk
class Drunk(object):
''' Point itself '''
def __init__(self, name):
self.name = name
def move(self, field, cp, dist = 1):
if field.get_drunk().name != self.name:
raise ValueError('Drunk.move called with drunk not in the field')
for i in range(dist):
field.move(cp, 1)
class Usual_Drunk(Drunk):
def move(self, field, dist = 1):
''' Drunk.move superclass method override. Sends additional cp attribute.'''
cp = random.choice(Compass_Pt.possibles)
Drunk.move(self, field, Compass_Pt(cp), dist)
class Cold_Drunk(Drunk):
def move(self, field, dist = 1):
cp = random.choice(Compass_Pt.possibles)
if cp == 'S':
Drunk.move(self, field, Compass_Pt(cp), 2*dist)
else:
Drunk.move(self, field, Compass_Pt(cp), dist)
class EW_Drunk(Drunk):
def move(self, field, time = 1):
cp = random.choice(Compass_Pt.possibles)
while cp != 'E' and cp != 'W':
cp = random.choice(Compass_Pt.possibles)
Drunk.move(self, field, Compass_Pt(cp), time)
def perform_trial(time, f):
start = f.get_loc()
distances = [0,0]
for t in range(1, time + 1):
f.get_drunk().move(f)
new_loc = f.get_loc()
distance = new_loc.get_dist(start)
distances.append(distance)
return distances
def perform_sim(time, num_trials, drunk_type):
dist_lists = []
loc_lists = []
for trial in range(num_trials):
d = drunk_type('Drunk' + str(trial))
f = Field(d, Location(0, 0))
distances = perform_trial(time, f)
locs = copy.deepcopy(distances)
dist_lists.append(distances)
loc_lists.append(locs)
return dist_lists, loc_lists
def ans_quest(max_time, num_trials, drunk_type, title):
dist_lists, loc_lists = perform_sim(max_time, num_trials, drunk_type)
means = []
for t in range(max_time + 1):
tot = 0.0
for dist_l in dist_lists:
tot += dist_l[t]
means.append(tot/len(dist_lists))
pylab.figure()
pylab.plot(means)
pylab.ylabel('distance')
pylab.xlabel('time')
pylab.title('{} Ave. Distance'.format(title))
lastX = []
lastY = []
for loc_list in loc_lists:
x, y = loc_list[-1].get_coords()
lastX.append(x)
lastY.append(y)
pylab.figure()
pylab.scatter(lastX, lastY)
pylab.ylabel('NW Distance')
pylab.title('{} Final location'.format(title))
pylab.figure()
pylab.hist(lastX)
pylab.xlabel('EW Value')
pylab.ylabel('Number of Trials')
pylab.title('{} Distribution of Final EW Values'.format(title))
num_steps = 50
num_trials = 10
ans_quest(num_steps, num_trials, Usual_Drunk, 'Usual Drunk ' + str(num_trials) + ' Trials')
ans_quest(num_steps, num_trials, Cold_Drunk, 'Cold Drunk ' + str(num_trials) + ' Trials')
ans_quest(num_steps, num_trials, EW_Drunk, 'EW Drunk ' + str(num_trials) + ' Trials')
pylab.show()
Error:
Traceback (most recent call last):
File "/home/tihe/Documents/CODING/Project Home/Python/biased_random_walks.py", line 194, in <module>
ans_quest(num_steps, num_trials, Usual_Drunk, 'Usual Drunk ' + str(num_trials) + ' Trials')
File "/home/tihe/Documents/CODING/Project Home/Python/biased_random_walks.py", line 175, in ans_quest
x, y = loc_list[-1].get_coords()
AttributeError: 'float' object has no attribute 'get_coords'
This method could be called like this if you had a list of Location objects. The error is because the loc_list is populated with distances and not Location objects. That happens in function perform_sim when instead of geting the location you are making a deep copy of distance.
Perhaps you could try something like this:
def perform_trial(time, f):
start = f.get_loc()
distances = [0,0]
locations = []
for t in range(1, time + 1):
f.get_drunk().move(f)
new_loc = f.get_loc()
locations.append(new_loc)
distance = new_loc.get_dist(start)
distances.append(distance)
return distances, locations
def perform_sim(time, num_trials, drunk_type):
dist_lists = []
loc_lists = []
for trial in range(num_trials):
d = drunk_type('Drunk' + str(trial))
f = Field(d, Location(0, 0))
distances, locations = perform_trial(time, f)
dist_lists.append(distances)
loc_lists.append(locations)
return dist_lists, loc_lists
I hope that helped you out.
I want to make 2 instances with same name like,
a = SomeClass(someAttr1)
a = SomeClass(someAttr2)
so that the new one should overwrite the previous one.
I also tried this:
a = SomeClass(someAttr1)
a = None
a = SomeClass(someAttr2)
I tried this but it doesn't overwrite the previous instance and adds it in itself, is there any way to do it?
Here is the code:
### Do not change the Location or Campus classes. ###
### Location class is the same as in lecture. ###
class Location(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, deltaX, deltaY):
return Location(self.x + deltaX, self.y + deltaY)
def getX(self):
return self.x
def getY(self):
return self.y
def dist_from(self, other):
xDist = self.x - other.x
yDist = self.y - other.y
return (xDist ** 2 + yDist ** 2) ** 0.5
def __eq__(self, other):
return (self.x == other.x and self.y == other.y)
def __str__(self):
return '<' + str(self.x) + ',' + str(self.y) + '>'
class Campus(object):
def __init__(self, center_loc):
self.center_loc = center_loc
def __str__(self):
return str(self.center_loc)
class MITCampus(Campus):
""" A MITCampus is a Campus that contains tents """
tents_list = []
def __init__(self, center_loc, tent_loc=Location(0, 0)):
""" Assumes center_loc and tent_loc are Location objects
Initializes a new Campus centered at location center_loc
with a tent at location tent_loc """
# Your code here
Campus.__init__(self, center_loc)
self.tent_loc = tent_loc
self.tents_list.append(self.tent_loc)
def add_tent(self, new_tent_loc):
""" Assumes new_tent_loc is a Location
Adds new_tent_loc to the campus only if the tent is at least 0.5 distance
away from all other tents already there. Campus is unchanged otherwise.
Returns True if it could add the tent, False otherwise. """
# Your code here
new_tent_flag = True
for loc in self.tents_list:
if loc == new_tent_loc or new_tent_loc.dist_from(loc) < 0.5:
new_tent_flag = False
if new_tent_flag:
self.tents_list.append(new_tent_loc)
return True
else:
return False
def get_tents(self):
""" Returns a list of all tents on the campus. The list should contain
the string representation of the Location of a tent. The list should
be sorted by the x coordinate of the location. """
# Your code here
new_list_sorted = sorted(self.tents_list, key=lambda tent: tent.getX())
str_list = []
for x in new_list_sorted:
str_list.append(x.__str__())
return str_list
Test Cases:
Test: 0
c = MITCampus(Location(1,2))
print(c.add_tent(Location(1,2)))
print(c.add_tent(Location(0,0)))
print(c.add_tent(Location(2,3)))
print(c.add_tent(Location(2,3)))
print(c.get_tents())
Output:
True
False
True
False
['<0,0>', '<1,2>', '<2,3>']
Test: 1
init campus with default tent loc
c = MITCampus(Location(-1,-2))
print(sorted(c.get_tents()))
Output:
['<0,0>','<0,0>', '<1,2>', '<2,3>']
Expected Output:
['<0,0>']
As can be seen that the second instance should overwrite the previous one but instead it is adding it. Is the problem in the code? and how to solve it?
Ok,
Your tents_list attribute is a class atribute, so even when your c object is overwrited the tents_list attribute stays the same.
It's better to make your tents_list an object argument so the tents_list attribute is overwrited too.
def __init__(self, center_loc, tent_loc=Location(0, 0)):
Campus.__init__(self, center_loc)
self.tents_list = [] # <--- Add this
self.tent_loc = tent_loc
self.tents_list.append(self.tent_loc)
The object is overwritten but you defined tents_list as a class variable so all of the instances of MITCampus share this list.
So any new instance will add to that list and that seems to you as not "overwritten".
If you want that "overwriting" behavior, move the tents_list into the __init__ method as self.tents_list. Only then it will be unique for each instance.