I am writing my first pretty printer, have some trouble. My gdb is 7.7.
Here is the C++ code I like to debug:
enum Country
{
CHINA,
USA
};
class Foo
{
public:
Foo(int _v, enum Country c) {v = _v; m_country = c;}
~Foo() { v = -1; }
int v;
enum Country m_country;
};
int main()
{
Foo f(10, CHINA);
return 0;
}
Here is my printer:
import gdb
class FooPrinter:
def __init__(self, val):
self.v = val
def to_string(self):
# because v is integer, a simpler way is:
# return self.v['v']
v = "v=" + str(self.v['v'])
f = self.m_country['m_country']
if (f == 0):
c = "CHINA"
elif (f == 1):
c = "USA"
else:
c = "unknown"
c = "c=" + c
ret = v + '\n' + c
return ret
def lookup_type (val):
if str(val.type) == 'Foo':
return FooPrinter(val)
return None
gdb.pretty_printers.append (lookup_type)
When I run the printer in gdb, I get this error:
(gdb) source printer.py
(gdb) p f
Python Exception <class 'AttributeError'> 'FooPrinter' object has no attribute 'm_country':
I guess I need to somehow modify __init__ to take an extra country argument, but if so, how should I update the rest of code?
The problem is this line:
f = self.m_country['m_country']
Here I think you want to examine self.v instead:
f = self.v['m_country']
Note that you can also get all the enumeration constant names from the enum type. So, you can replace the chained if with a simpler lookup. This is nice if the enum is larger than a couple of constants.
Related
For example, the query is:
a = request.GET['country']
b = request.GET['name']
c = request.GET['title']
...
result = models.Data.objects.filter('country' = a, 'name' = b, 'title' = c, ...)
What should I do if one of these a b c is "Any"?
I mean if I receive from the frontend, a="Any", how should I effectively free this limit in filter?
You can make a function to build a Q object from a parameter:
def _get_filter(name, value):
return Q() if value == 'Any' else Q((name, value))
and combine them with &:
q = (
_get_filter('country', request.GET['country']) &
_get_filter('name', request.GET['name']) &
_get_filter('title', request.GET['title'])
)
result = models.Data.objects.filter(q)
If possible, I’d also get the source of the request (frontend?) to send a better value to indicate “Any”, like an empty string.
You don't have to do everything in a single query. The query is not run until after everything is done.
You can use:
result = models.Data.objects.all()
if a != 'any':
result = result.filter('country' = a)
if b != 'any':
result = result.filter('name' = b)
if c != 'any':
result = result.filter('title' = c)
...
The query won't run against the database until everything is finished, so this really doesn't add any extra queries.
I am using pyomo and I want to define a general equation (with general variables) and then replace the specific variables, something like that:
def Variable_trap_eq(model, variable, f_variable, i):
return 0 == variable[i] - variable[i+1] + (m.step/2.0)*( f_variable[i] + f_variable[i+1])
m.Variable_trap_eq_const = Constraint(m.N1, rule = Variable_trap_eq(x, f_x))
m.Variable_trap_eq_const = Constraint(m.N1, rule = Variable_trap_eq(y, f_y))
Something like that, where in the first constraint: variable= model.x, and f_variable = model.f_x, and in the second one: variable= model.y, and f_variable = model.f_y.
Any help?
Thanks,
María
I think the simplest way to do this would be to define two constraint rules and a third function that those two rules then call. E.g.,
def Variable_trap_eq(model, variable, f_variable, i):
return 0 == variable[i] - variable[i+1] + (m.step/2.0)*(f_variable[i] + f_variable[i+1])
def Variable_trap_eq_const1_rule(model, i):
return Variable_trap_eq(model, model.x, model.f_x, i)
m.Variable_trap_eq_const1 = Constraint(m.N1, rule=Variable_trap_eq_const1_rule)
def Variable_trap_eq_const2_rule(model, i):
return Variable_trap_eq(model, model.y, model.f_y, i)
m.Variable_trap_eq_const2 = Constraint(m.N1, rule=Variable_trap_eq_const2_rule)
I have written a bisect function that takes a word list "t" and a word "val". It recursively halves the list until the index of the list is the word or returns false. If it finds the word, it is supposed to return it.
I have read multiple books, the documentation, and all the applicable questions here on SO but I still cannot determine what I am doing wrong: why won't the function return the value? It will print the value just fine, but no return except None.
Any help is greatly appreciated!
def bisect(t, val):
if t[len(t)/2] < val and len(t) > 1:
t = t[len(t)/2:]
bisect(t, val)
elif t[len(t)/2] > val and len(t) > 1:
t = t[:len(t)/2]
bisect(t, val)
elif t[len(t)/2] == val:
t = t[len(t)/2]
#print type(t), t
return t
else:
return False
b = make_list(t)
x = bisect(b, 'and')
print x
The main issue here is that you need to return t from each call to the recursively called function. Picture the call stack using my modified code below:
def main():
b = ['a', 'able', 'ability', 'abort', 'and', 'arc', 'zygote']
x = bisect(b, 'and')
print x
def bisect(t, val):
if t[len(t)/2] < val and len(t) > 1:
t = t[len(t)/2:]
t = bisect(t, val)
elif t[len(t)/2] > val and len(t) > 1:
t = t[:len(t)/2]
t = bisect(t, val)
elif t[len(t)/2] == val:
t = t[len(t)/2]
print type(t), t
else:
return False
return t
if __name__ == '__main__':
main()
The first time bisect is called, t is set to ['abort', 'and', 'arc', 'zygote'].
On the second call to bisect, t is set to ['abort', 'and']
On the third call, we have 'and' located, and return that value.
IF you returned as you had (only returning from the exact match or False result), then you return to the second call (['abort', 'and']), then the first call (['abort', 'and', 'arc', 'zygote']), and finally you return without hitting a return t in that first call. Thus, nothing is returned.
Rewriting your original code as I have, everything is the same until we find the match. However, with my code, the final call returns t back into the t variable used in the second call. That returns the value to the first call, which returns the result back to the calling code.
Hopefully, that clears up your question.
This modified version works:
def bisect(t, val):
mid = len(t)//2
mid_ele = t[mid]
end = len(t)
if mid_ele < val and end > 1:
t = t[mid:]
return bisect(t, val)
elif mid_ele > val and end > 1:
t = t[:mid]
return bisect(t, val)
elif mid_ele == val:
t = mid_ele
return t
else:
return False
b = ['she', 'he', 'you', 'and', 'me']
print(bisect(b, 'and'))
prints the desired:
and
I made it Python 3 proof using // for integer division and added two returnsbefore the recursive call.
hey guys:)im sorry for all the code but i feel its necessary for u to see everything..
i tried everything... i hidden prints in the code, debugging for ten times, triple checked the built in methods, and still, the .crawl() method dosnt remove any object from the final_list.
the object of my assignment is to built two classes:
Web_page : holds data of a web page.(the pages come in the form of html files saved in a folder on my desktop. Crawler: compare between pages and hold a list of the uniqe pages---> final_list
import re
import os
def remove_html_tags(s):
tag = False
quote = False
out = ""
for c in s:
if c == '<' and not quote:
tag = True
elif c == '>' and not quote:
tag = False
elif (c == '"' or c == "'") and tag:
quote = not quote
elif not tag:
out = out + c
return out
def lev(s1, s2):
return lev_iter(s1, s2, dict())
def lev_iter(s1, s2, mem):
(i,j) = (len(s1), len(s2))
if (i,j) in mem:
return mem[(i,j)]
s1_low = s1.lower()
s2_low = s2.lower()
if len(s1_low) == 0 or len(s2_low) == 0:
return max(len(s1_low), len(s2_low))
d1 = lev_iter(s1_low[:-1], s2_low, mem) + 1
d2 = lev_iter(s1_low, s2_low[:-1], mem) + 1
last = 0 if s1_low[-1] == s2_low[-1] else 1
d3 = lev_iter(s1_low[:-1], s2_low[:-1], mem) + last
result = min(d1, d2, d3)
mem[(i,j)] = result
return result
def merge_spaces(content):
return re.sub('\s+', ' ', content).strip()
""" A Class that holds data on a Web page """
class WebPage:
def __init__(self, filename):
self.filename = filename
def process(self):
f = open(self.filename,'r')
LINE_lst = f.readlines()
self.info = {}
for i in range(len(LINE_lst)):
LINE_lst[i] = LINE_lst[i].strip(' \n\t')
LINE_lst[i] = remove_html_tags(LINE_lst[i])
lines = LINE_lst[:]
for line in lines:
if len(line) == 0:
LINE_lst.remove(line)
self.body = ' '.join(LINE_lst[1:])
self.title = LINE_lst[0]
f.close()
def __str__(self):
return self.title + '\n' + self.body
def __repr__(self):
return self.title
def __eq__(self,other):
n = lev(self.body,other.body)
k = len(self.body)
m = len(other.body)
return float(n)/max(k,m) <= 0.15
def __lt__(self,other):
return self.title < other.title
""" A Class that crawls the web """
class Crawler:
def __init__(self, directory):
self.folder = directory
def crawl(self):
pages = [f for f in os.listdir(self.folder) if f.endswith('.html')]
final_list = []
for i in range(len(pages)):
pages[i] = WebPage(self.folder + '\\' + pages[i])
pages[i].process()
for k in range(len(final_list)+1):
if k == len(final_list):
final_list.append(pages[i])
elif pages[i] == final_list[k]:
if pages[i] < final_list[k]:
final_list.append(pages[i])
final_list.remove(final_list[k])
break
print final_list
self.pages = final_list
everything works fine besides this freaking line final_list.remove(final_list[k]). help please? whats wrong here?
I'm not sure why your code doesn't work, it's difficult to test it because I don't know what kind of input should end up calling remove().
I suggest following these steps:
Make sure that remove() is called at some point.
remove() relies on your __eq__() method to find the item to remove, so make sure that __eq__() isn't the culprit.
As a side note, you will probably want to replace this:
self.folder + '\\' + pages[i]
with:
import os.path
# ...
os.path.join(self.folder, page[i])
This simple change should make your script work on all operating systems, rather than on Windows only. (GNU/Linux, Mac OS and other Unix-like OS use “/” as path separator.)
Please also consider replacing loops of this form:
for i in range(len(sequence)):
# Do something with sequence[i]
with:
for item in sequence:
# Do something with item
If you need the item index, use enumerate():
for i, item in enumerate(sequence):
What would be the best approach to create a type that is a saturated integer in python ?
i.e.:
v = SaturatedInteger(0, 100)
# That should create an integer that will always be in between 0 and 100,
# and have all default operations
v += 68719
print v #Should print '100'.
I can think of inheriting int type, but where should the saturating logic be implemented then ?
If you need a new (quick and dirty) class for it, I would implement it as follows.
class SaturatedInteger:
def __init__(self, val, lo, hi):
self.real, self.lo, self.hi = val, lo, hi
def __add__(self, other):
return min(self.real + other.real, self.hi)
def __sub__(self, other):
return max(self.real - other.real, self.lo)
...
Add as many of the other operators in the docs as you feel you will need (and their 'r' variants).
By storing the value in the instance name real, you can do your arithmetic with regular integers, floats, etc. too:
a = SaturatedInteger(60, 0, 100)
print(a)
60
print(a+30)
90
print(a+40)
100
print(a+50.)
100
print(a-70.)
0
print(a+a)
100
Though, of course you only add the real part if you're adding a complex number to your SaturatedInteger, so watch out. (For a much more complete and robust version, #jonrsharpe's answer is the way to go).
In general, I would implement using a #property to protect an instance's value attribute, then emulate a numeric type, rather than inheriting from int:
class SaturatedInteger(object):
"""Emulates an integer, but with a built-in minimum and maximum."""
def __init__(self, min_, max_, value=None):
self.min = min_
self.max = max_
self.value = min_ if value is None else value
#property
def value(self):
return self._value
#value.setter
def value(self, new_val):
self._value = min(self.max, max(self.min, new_val))
#staticmethod
def _other_val(other):
"""Get the value from the other object."""
if hasattr(other, 'value'):
return other.value
return other
def __add__(self, other):
new_val = self.value + self._other_val(other)
return SaturatedInteger(self.min, self.max, new_val)
__radd__ = __add__
def __eq__(self, other):
return self.value == self._other_val(other)
if __name__ == '__main__':
v = SaturatedInteger(0, 100)
v += 68719
assert v == 100
assert 123 + v == 100
I've only implemented __add__, __radd__ and __eq__, but you can probably see how the rest could be built out as required. You might want to think about what happens when two SaturatedIntegers are used together - should the result have e.g. min(self.min, other.min) as its own min?
I wrote a sample class that has an add function:
class SatInt:
def __init__(self, low, up):
self.lower = low
self.upper = up
self.value = 0
def add(self, n):
if n+self.value > self.upper:
self.value = self.upper
else:
self.value = self.value + n
x = SatInt(0,100)
x.add(32718)
print(x.value)
100