I didn't understand why. And It will raise an error 'int' object has no attribute 'v', but I want to access the self.v. When I print only self it will print some numbers. I couldn't understand what was going on. Here is my code.
class Candidate:
def __init__(self,val,pscore,nscore):
self.v = val
self.p = pscore
self.n = nscore
def __str__(self):
return f"{self.v} ({self.p},{self.n})"
def check_plus_pos(self, guessval):
count = 0
b = self.v
a = str(b)
guessval = str(guessval)
for i in range(0,len(a)):
if a[i] == guessval[i]:
count += 1
return count
def check_neg_pos(self, guessval):
count = 0
b = self.v
a = str(b)
guessval = str(guessval)
for i in range(0,len(a)):
for j in range(0,len(guessval)):
if a[i] == guessval[j] and a[i] != guessval[i]:
count += 1
return count
def consistent(self, guess):
if Candidate.check_plus_pos(self,guess.v) == guess.p and Candidate.check_neg_pos(self,guess.v) == guess.n:
return True
else:
return False
The problem occurs at b == self.v I wanted to assign the self.v value to a variable.
To be honest it's pretty hard to understand what that code/class is supposed to do, imho it needs some serious refactoring.
My guess is you should:
instantiate your class somewhere
use the method as an instance method, so invoke it with self and not the class name
do NOT pass self explicitly at all
do NOT use abbreviations which are not commonly known
do NOT use single letter variables a means literally nothing
use docstrings for non-trivial functions (or as a rule of thumb to most of functions/methods)
use type hints, which will help you catch this kind of errors automatically (if you configure your IDE that is)
get rid of the assignment to b at all, it's not reused and doesn't seem do anything. This will do the same a = str(self.v)
... # all the class related code above
def check_neg_pos(self, guessval):
count = 0
a = str(self.v)
guessval = str(guessval)
for i in range(0,len(a)):
for j in range(0,len(guessval)):
if a[i] == guessval[j] and a[i] != guessval[i]:
count += 1
return count
def is_consistent(self, guess: Candidate)->bool:
return bool(self.check_plus_pos(guess.v) == guess.p and self.check_neg_pos(guess.v) == guess.n)
# Example usage
candidate_1 = Candidate(1,2,3)
candidate_2 = Candidate(4,5,6)
candidates_consistent = candidate_1.is_consistent(guess=candidate_2)
print(candidates_consistent)
Define a class for a type called CounterType. An object of this type is used to count
things, so it records a count that is a nonnegative whole number.
a. Private data member: count.
b. Include a mutator function that sets the counter to a count given as an argument.
c. Include member functions to increase the count by one and to decrease the count
by one.
d. Include a member function that returns the current count value and one that outputs
the count.
e. Include default constructor that set the count to 0.
f. Include one argument constructor that set count to given argument.
Be sure that no member function allows the value of the counter to become negative.
Embed your class definition in a test program.
An output example would be:
a = CounterType(10)
a.display()
a.increase()
a.display()
a.setCounter(100)
a.display
Will display the following:
Counter: 10
Counter: 11
Counter: 100
I have written the code but I just want to make sure that it is following what the question asked and if there could be an easier way to write this code.
class CounterType:
def __init__(self, counter=0):
self.counter = counter
def increase(self):
self.counter += 1
def decrease(self):
if self.counter == 0:
print("Error, counter cannot be negative")
else:
self.counter -= 1
def setCounter(self, x):
if x < 0:
print("Error, counter cannot be negative")
else:
self.counter = x
def setCount0(self):
self.counter = 0
def display(self):
print("Counter:", self.counter)
def getCounter(self):
return self.counter
This is a homework assignment so it would help if you could just give some tips
You forgot "Be sure that no member function allows the value of the counter to become negative."
The naïve way to do this is to add an if condition in every function. A smarter way would be to add that check the setCounter function and use this function from all other functions.
class CounterType:
def __init__(self, counter=0): # (e, f) counter = 0: default argument value so x = CounterType() works and has a counter of 0
self.counter = 0 # (a)
self.setCounter(counter)
def increase(self): # (c)
self.setCounter(self.counter + 1)
def decrease(self): # (c)
self.setCounter(self.counter - 1)
def setCounter(self, x): # (b)
if x < 0:
print("Error, counter cannot be negative")
else:
self.counter = x
def setCount0(self): # This is not needed
self.counter = 0
def display(self): # (d)
print("Counter:", self.counter)
def getCounter(self): # (d)
return self.counter
add_digits2(1)(3)(5)(6)(0) should add up all the numbers and stop when it reaches 0.
The output should be 15
The below code works but uses a global variable.
total = 0
def add_digits2(num):
global total
if num == 0:
print(total)
else:
total += num
return add_digits2
The result is correct but needs to do the same thing without using the global variable.
One thing you could do is use partial:
from functools import partial
def add_digits2(num, total=0):
if num == 0:
print(total)
return
else:
total += num
return partial(add_digits2, total=total)
add_digits2(2)(4)(0)
You can just pass in *args as a parameter and return the sum
def add_digits2(*args):
return sum(args)
add_digits2(1, 3, 5 ,6)
You could also use a class, using the __call__ method to obtain this behavior:
class Add_digits:
def __init__(self):
self.total = 0
def __call__(self, val):
if val != 0:
self.total += val
return self
else:
print(self.total)
self.total = 0
add_digits = Add_digits()
add_digits(4)(4)(0)
# 8
add_digits(4)(6)(0)
# 10
though I still don't get why you would want to do this...
Really hard to say what they are after when asking questions like that but the total could be stored in a function attribute. Something like this
>>> def f():
... f.a = 3
>>> f()
>>> f.a
3
I am recursively generating few objects, which need a contiguous, unique id. How can I guarantee (easiest) the synchronization in python 2.7.
iid = 1
def next_id():
iid += 1
return iid
def process():
# .. do something
id = next_id()
from itertools import count
iid = count()
print next(iid) # 0
print next(iid) # 1
print next(iid) # 2
etc., and
new_iid = count(10)
print next(new_iid) # 10
print next(new_iid) # 11
print next(new_iid) # 12
for starting at other values than 0.
count() is essentially a generator which infinitely yields values.
Use a mutex:
import threading
iid = 1
iid_lock = threading.Lock()
def next_id():
global iid
with iid_lock:
result = iid
iid += 1
return result
You might like to hide the internals in a class:
class IdGenerator(object):
def __init__(self):
self.cur_id = 1
self.lock = threading.Lock()
def next_id(self):
with self.lock:
result = self.cur_id
self.cur_id += 1
return result
EDIT: Based on the comments, it seems like you're not using threads. This means you don't need the locking mechanism at all. What you initially wrote would be sufficient, though you need the global keyword to make the global variable mutable:
iid = 1
def next_id():
global iid
res = iid
iid += 1
return res
You were thinking to something of this kind:
class Counter():
def __init__(self):
self.theCount = -1
def __call__(self):
self.theCount += 1
return self.theCount
class BorgCounter():
Borg = {'theCount':-1}
def __init__(self):
self.__dict__ = BorgCounter.Borg
def __call__(self):
self.theCount += 1
return self.theCount
myCount = Counter()
mycount2 = Counter()
assert(myCount()==0)
assert(mycount2()==0)
assert(mycount2()==1)
assert(myCount()==1)
assert(myCount()==2)
myCount = BorgCounter()
mycount2 = BorgCounter()
assert(myCount()==0)
assert(mycount2()==1)
assert(mycount2()==2)
assert(myCount()==3)
assert(myCount()==4)
I'm writing a class for a simple game of 4 in a row, but I'm running into a problem calling a method in the same class. Here's the whole class for the sake of completeness:
class Grid:
grid = None
# creates a new empty 10 x 10 grid
def reset():
Grid.grid = [[0] * 10 for i in range(10)]
# places an X or O
def place(player,x,y):
Grid.grid[x][y] = player
# returns the element in the grid
def getAt(x,y):
return Grid.grid[x][y]
# checks for wins in a certain direction
def checkLine(player,v,count,x,y):
x = x+v[0]
y = y+v[1]
if x < 0 or x > 9:
return
if y < 0 or y > 9:
return
if Grid.grid[x][y] == p:
count = count+1
if count == 4:
return True
checkLine(player,v,count,x,y)
return False
# returns the number of the player that won
def check():
i = 'i'
for x in range(0,10):
for y in range(0,10):
if Grid.grid[x][y] > 0:
p = Grid.grid[x][y]
f = checkLine(p,0,array(i,[1,0]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[0,1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[1,1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,0]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[0,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[1,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,1]),x,y)
if f:
return p
return 0
reset = staticmethod(reset)
place = staticmethod(place)
getAt = staticmethod(getAt)
check = staticmethod(check)
checkLine = staticmethod(checkLine)
I'm trying to call checkLine() from check(), but I get the error "NameError: global name 'checkLine' is not defined". When I call Grid.checkLine() instead, I get "TypeError: 'module' object is not callable"
How do I call checkLine()?
EDIT:
#beer_monk
class Grid(object):
grid = None
# creates a new empty 10 x 10 grid
def reset(self):
Grid.grid = [[0] * 10 for i in range(10)]
# places an X or O
def place(self,player,x,y):
Grid.grid[x][y] = player
# returns the element in the grid
def getAt(self,x,y):
return Grid.grid[x][y]
# checks for wins in a certain direction
def checkLine(self,player,v,count,x,y):
x = x+v[0]
y = y+v[1]
if x < 0 or x > 9:
return
if y < 0 or y > 9:
return
if Grid.grid[x][y] == p:
count = count+1
if count == 4:
return True
checkLine(self,player,v,count,x,y)
return False
# returns the number of the player that won
def check(self):
i = 'i'
for x in range(0,10):
for y in range(0,10):
if Grid.grid[x][y] > 0:
p = Grid.grid[x][y]
for vx in range(-1,2):
for vy in range(-1,2):
f = self.checkLine(p,0,array(i,[vx,vy]),x,y)
if f:
return p
return 0
reset = staticmethod(reset)
place = staticmethod(place)
getAt = staticmethod(getAt)
check = staticmethod(check)
checkLine = staticmethod(checkLine)
Get rid of the class. Use plain functions and module level variable for grid.
The class is not helping you in any way.
PS. If you really want to call checkline from within the class, you'd call Grid.checkline. For example:
class Foo:
#staticmethod
def test():
print('Hi')
#staticmethod
def test2():
Foo.test()
Foo.test2()
prints
Hi
Syntax:
class_Name.function_Name(self)
Example:
Turn.checkHoriz(self)
A reworked example (hopefully showing a better use of classes!)
import itertools
try:
rng = xrange # Python 2.x
except NameError:
rng = range # Python 3.x
class Turn(object):
def __init__(self, players):
self.players = itertools.cycle(players)
self.next()
def __call__(self):
return self.now
def next(self):
self.now = self.players.next()
class Grid(object):
EMPTY = ' '
WIDTH = 10
HEIGHT = 10
WINLENGTH = 4
def __init__(self, debug=False):
self.debug = debug
self.grid = [Grid.EMPTY*Grid.WIDTH for i in rng(Grid.HEIGHT)]
self.player = Turn(['X','O'])
def set(self, x, y):
if self.grid[y][x]==Grid.EMPTY:
t = self.grid[y]
self.grid[y] = t[:x] + self.player() + t[x+1:]
self.player.next()
else:
raise ValueError('({0},{1}) is already taken'.format(x,y))
def get(self, x, y):
return self.grid[y][x]
def __str__(self):
corner = '+'
hor = '='
ver = '|'
res = [corner + hor*Grid.WIDTH + corner]
for row in self.grid[::-1]:
res.append(ver + row + ver)
res.append(corner + hor*Grid.WIDTH + corner)
return '\n'.join(res)
def _check(self, s):
if self.debug: print("Check '{0}'".format(s))
# Exercise left to you!
# See if a winning string exists in s
# If so, return winning player char; else False
return False
def _checkVert(self):
if self.debug: print("Check verticals")
for x in rng(Grid.WIDTH):
winner = self._check([self.get(x,y) for y in rng(Grid.HEIGHT)])
if winner:
return winner
return False
def _checkHoriz(self):
if self.debug: print("Check horizontals")
for y in rng(Grid.HEIGHT):
winner = self._check([self.get(x,y) for x in rng(Grid.WIDTH)])
if winner:
return winner
return False
def _checkUpdiag(self):
if self.debug: print("Check up-diagonals")
for y in rng(Grid.HEIGHT-Grid.WINLENGTH+1):
winner = self._check([self.get(d,y+d) for d in rng(min(Grid.HEIGHT-y, Grid.WIDTH))])
if winner:
return winner
for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
if winner:
return winner
return False
def _checkDowndiag(self):
if self.debug: print("Check down-diagonals")
for y in rng(Grid.WINLENGTH-1, Grid.HEIGHT):
winner = self._check([self.get(d,y-d) for d in rng(min(y+1, Grid.WIDTH))])
if winner:
return winner
for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
if winner:
return winner
return False
def isWin(self):
"Return winning player or False"
return self._checkVert() or self._checkHoriz() or self._checkUpdiag() or self._checkDowndiag()
def test():
g = Grid()
for o in rng(Grid.WIDTH-1):
g.set(0,o)
g.set(Grid.WIDTH-1-o,0)
g.set(Grid.WIDTH-1,Grid.HEIGHT-1-o)
g.set(o,Grid.HEIGHT-1)
print(g)
return g
g = test()
print g.isWin()
Unlike java or c++, in python all class methods must accept the class instance as the first variable. In pretty much every single python code ive seen, the object is referred to as self. For example:
def reset(self):
self.grid = [[0] * 10 for i in range(10)]
See http://docs.python.org/tutorial/classes.html
Note that in other languages, the translation is made automatically
There are multiple problems in your class definition. You have not defined array which you are using in your code. Also in the checkLine call you are sending a int, and in its definition you are trying to subscript it. Leaving those aside, I hope you realize that you are using staticmethods for all your class methods here. In that case, whenever you are caling your methods within your class, you still need to call them via your class's class object. So, within your class, when you are calling checkLine, call it is as Grid.checkLine That should resolve your NameError problem.
Also, it looks like there is some problem with your module imports. You might have imported a Module by name Grid and you have having a class called Grid here too. That Python is thinking that you are calling your imported modules Grid method,which is not callable. (I think,there is not a full-picture available here to see why the TypeError is resulting)
The best way to resolve the problem, use Classes as they are best used, namely create objects and call methods on those objects. Also use proper namespaces. And for all these you may start with some good introductory material, like Python tutorial.
Instead of operating on an object, you are actually modifying the class itself. Python lets you do that, but it's not really what classes are for. So you run into a couple problems
-You will never be able to make multiple Grids this way
the Grid can't refer back to itself and e.g. call checkLine
After your grid definition, try instantiating your grid and calling methods on it like this
aGrid = Grid()
...
aGrid.checkLine()
To do that you, you first need to modify all of the method definitions to take "self" as your first variable and in check, call self.checkLine()
def check(self):
...
self.checkLine()
...
Also, your repeated checking cries out for a FOR loop. You don't need to write out the cases.
Java programmer as well here, here is how I got it to call an internal method:
class Foo:
variable = 0
def test(self):
self.variable = 'Hi'
print(self.variable)
def test2(self):
Foo.test(self)
tmp = Foo()
tmp.test2()