I don't know what is wrong with this python code - python

class FC():
def data(self, a, b):
self.n1 = a
self.n2 = b
def add(self):
return (self.n1 + self.n2)
>>> def pbnc(start, num):
pb = FC()
pb.data(start, start)
while (num > 0):
print(pb.add())
pb.data(pb.n2, pb.add())
num -= 1
>>> def pbnc(1, 10)
SyntaxError: invalid syntax
I'm currently learning 'Class' in python. And I can't find the wrong thing in this code. Is it wrong to use classes in other functions?

Appears to be a simple indentation error, this should be fine:
class FC():
def data(self, a, b):
self.n1 = a
self.n2 = b
def add(self):
return (self.n1 + self.n2)
def pbnc(self, start, num):
pb = FC()
pb.data(start, start)
while (num > 0):
print(pb.add())
pb.data(pb.n2, pb.add())
num -= 1
'''
# Uncomment this part if you want this method outside of the class
def pbnc(start, num):
pb = FC()
pb.data(start, start)
while (num > 0):
print(pb.add())
pb.data(pb.n2, pb.add())
num -= 1
'''

Related

Question about implementing static Arrays class in python

Recently I am studying mit cs6.006. In the recitation 2, sattic arrays are implemented as following:
class Array_Seq:
def __init__(self) -> None:
self.A=[]
self.size=0
def __len__(self): # My question here
return self.size
def __iter__(self):
yield from self.A
def build(self,X): # My question here
self.A=[a for a in X]
self.size=len(self.A)
def get_at(self,i):
return self.A[i]
def set_at(self,i,x):
self.A[i]=x
def _copy_forward(self,i,n,A,j):
for k in range(n):
A[j+k]=self.A[i+k]
def _copy_backward(self,i,n,A,j):
for k in range(n-1,-1,-1):
A[j+k]=self.A[i+k]
def insert_at(self, i, x): # O(n)
n = len(self)
A = [None] * (n + 1)
self._copy_forward(0, i, A, 0)
A[i] = x
self._copy_forward(i, n - i, A, i + 1)
self.build(A)
def delete_at(self, i): # O(n)
n = len(self)
A = [None] * (n - 1)
self._copy_forward(0, i, A, 0)
x = self.A[i]
self._copy_forward(i + 1, n - i - 1, A, i)
self.build(A)
return x
def insert_first(self, x): self.insert_at(0, x)
def delete_first(self): return self.delete_at(0)
def insert_last(self, x): self.insert_at(len(self), x)
def delete_last(self): return self.delete_at(len(self) - 1)
My question
I don't know how the function len() and build() work for the size:
when I use build(), this function will let self.size=len(), however, in the definition of len(), it will return self.size. I don't understand how it works.

Parametrized RuleBasedStateMachine

After watching https://www.youtube.com/watch?v=zi0rHwfiX1Q I tried to port the example from C (implementation) and Erlang (testing) to Python and Hypothesis. Given this implementation (the rem function emulates %'s C behavior):
import math
def rem(x, y):
res = x % y
return int(math.copysign(res,x))
class Queue:
def __init__(self, capacity: int):
self.capacity = capacity + 1
self.data = [None] * self.capacity
self.inp = 0
self.outp = 0
def put(self, n: int):
self.data[self.inp] = n
self.inp = (self.inp + 1) % self.capacity
def get(self):
ans = self.data[self.outp]
self.outp = (self.outp + 1) % self.capacity
return ans
def size(self):
return rem((self.inp - self.outp), self.capacity)
and this test code
import unittest
from hypothesis.stateful import rule, precondition, RuleBasedStateMachine
from hypothesis.strategies import integers
from myqueue import Queue
class QueueMachine(RuleBasedStateMachine):
cap = 1
def __init__(self):
super().__init__()
self.queue = Queue(self.cap)
self.model = []
#rule(value=integers())
#precondition(lambda self: len(self.model) < self.cap)
def put(self, value):
self.queue.put(value)
self.model.append(value)
#rule()
def size(self):
expected = len(self.model)
actual = self.queue.size()
assert actual == expected
#rule()
#precondition(lambda self: self.model)
def get(self):
actual = self.queue.get()
expected = self.model[0]
self.model = self.model[1:]
assert actual == expected
TestQueue = QueueMachine.TestCase
if __name__ == "__main__":
unittest.main()
The actual question is how to use Hypothesis to also parametrize over QueueMachine.cap instead of setting it manually in the test class.
You can set self.queue in an initialize method rather than __init__, using a suitable integers strategy for the capacity.

Implementing fractions in python

I tried to implement fractions using classes in python, but when I ran it,
it showed the error 'function gcd is not defined'. I can't seem to figure out how.
However, when I defined GCD outside the class it was working perfectly fine.
class frac:
def gcd(a, b):
if(b == 0):
return a
else:
return gcd(b, a%b)
def __init__(self, numer, denom):
if(denom == 0):
raise Exception("WTF")
else:
self.numer = numer
self.denom = denom
self.ratify()
def ratify(self):
g = gcd(self.numer, self.denom)
self.numer = self.numer/g
self.denom = self.denom/g
def add(self, b):
n,d = self.numer, self.denom
self.numer = n*b.denom + d*b.numer
self.denom = d*b.denom
self.ratify()
What is going wrong?
Your gcd method needs to look like:
def gcd(self, a, b):
if(b == 0):
return a
else:
return self.gcd(b, a%b)

How to replace an integer with a different class when it is assigned

I have a class called newInteger, and a variable called num, but I would like num to be a newInteger() instead of an int(). Code below.
class newInteger(int):
def __init__(self, value):
self.value = value
num = 10
I want the line num = 10 to act as if it is num = newInteger(10). Thanks to anyone who can help me with this.
You can run a small thread parallel to your main program that replaces all created integers to newInteger:
import threading
import time
class newInteger(int):
def __init__(self, value):
self.value = value
def __str__(self):
return "newInteger " + str(self.value)
def replace_int():
while True:
g = list(globals().items())
for n, v in g:
if type(v) == int:
globals()[n] = newInteger(v)
threading.Thread(target=replace_int, daemon=True).start()
num = 10
time.sleep(1)
print(num)
But this is unpythonic and will be realy hard to debug. You should just use a explicit conversion like #johnashu proposed
I am not sure if this is what you mean but if youassign the class to a variabl. then it will be an instance of that class..
example:
class newInteger(int):
def __init__(self, value):
self.value = value
num = 10
if num == 10:
num = newInteger(10)
prints:
hello

How to write this statement more compactly without a ++ operator?

Here's what I want to write:
groups[m][n] = groups[m - 1][n] or ++gid
Here's what I have to write:
g = groups[m - 1][n]
if g:
groups[m,n] = g
else:
gid += 1
groups[m][n] = gid
Is there no more compact way of writing that in Python simply because it lacks a ++ operator?
A larger sample from a method I'm working on:
groups = [[0] * self.columns] * self.rows
gid = 0
for m in xrange(self.rows):
for n in xrange(self.columns):
stone = self[m, n]
if stone == self[m - 1, n]:
if groups[m - 1][n]:
groups[m][n] = groups[m - 1][n]
else:
gid += 1
groups[m][n] = gid
elif stone == self[m, n - 1]:
if groups[m][n - 1]:
groups[m][n] = groups[m][n - 1]
else:
gid += 1
groups[m][n] = gid
I think it's a lot harder to read when I have to blow it out like that, plus I'm evaluating m-1 twice... I'm not sure how I can condense it though.
This is what I came up with:
I created a wrapper class around int:
class Int(object):
def __init__(self, i):
self.i = i
def pre(self, a=1):
self.i += a
return Int(self.i)
def post(self, a=1):
cpy = Int(self.i)
self.i += a
return cpy
def __repr__(self):
return str(self.i)
def __nonzero__(self):
return self.i != 0
Which can be used like this:
def group_stones(self):
groups = [[None for _ in xrange(self.cols)] for _ in xrange(self.rows)]
gid = Int(0)
for m in xrange(self.rows):
for n in xrange(self.cols):
stone = self[m, n]
if stone == self[m - 1, n]:
groups[m][n] = groups[m - 1][n] or gid.pre()
elif stone == self[m, n - 1]:
groups[m][n] = groups[m][n - 1] or gid.pre()
else:
groups[m][n] = gid.pre()
Much like I would do in other languages.
gid = [0] # list - mutable object
def incremented(gid):
gid[0] += 1
return gid[0]
groups[m][n] = groups[m - 1][n] or incremented(gid)
You can add some "magic" to your Int class:
class C(object):
...
def __add__(self, other):
self.i += other
return self.__class__(self.i)
def __radd__(self, other):
cpy = self.__class__(self.i)
self.i += other
return cpy
>>> print Int(2) + 1 # pre
3
>>> i = Int(2)
>>> print 1 + i # post
2
>>> print i
3
Technically more compact, but not really more readable nor less DRY:
groups[m][n], gid = (groups[m-1][n], gid) if groups[m-1][n] else (gid+1, gid+1)
Less compact (for a single usage, at least), more readable:
def test_or_inc(val, accum):
return (val, accum) if val else (accum+1, accum+1)
groups[m][n], gid = test_or_inc(groups[m-1][n], gid)
Another option is to make gid something you can pass by reference... such as a property of an object, or an item in a list.
If you put the gid generation in a function you can do that. For example (using the global scope):
gid = 0
def newgid(): global gid; gid += 1; return gid
Now you can write:
groups[m][n] = groups[m - 1][n] or newgid()
Of course it would be better to put the gid and newgid in its own class or in the class where your other methods are.

Categories