I have my code setup this way:
class Test():
def __init__(self):
self.offset = [0,0]
#property
def offset(self):
return self._offset
#offset.setter
def offset(self,offset):
print("set")
self._offset = offset
test = Test()
test.offset[1] -= 1
but the setter is being called only once even though I am changing my variable twice, anyone is able to help ?
test.offset[1] -= 1
This line of your code is calling the getter not the setter. You get the list from the test object and then you alter its contents.
Same as if you wrote:
v = test.offset # get the list
v[1] -= 1 # alter the contents of the list
If I were to have these functions in a class, how would I call them from another function in the same class?
class Dead:
def initial(self):
self.amy = 1
self.bob = 2
self.cam = 3
def __init__(self):
self.initial()
def get_number(self, number):
How could I call self.amy, and in return be getting the number 1? In get_number I would like to add like self.amy to a number to return the sum, but like with all amy, bob, cam in one go with a for function maybe? I'm not sure how to word this question without completely spoiling the question, sorry.
You could change your get_number method to accept a member variable name instead and dynamically retrieve it. E.g.
class Dead:
def initial(self):
self.amy = 1
self.bob = 2
self.cam = 3
def __init__(self):
self.initial()
def get_number(self, name, number):
return getattr(self, name) + number
However, this is more than redundant. You can already access those variables from your object, adding a method to access them is adding an extra layer for no reason.
class Dead:
def initial(self):
self.amy = 1
self.bob = 2
self.cam = 3
def __init__(self):
self.initial()
dead = Dead()
dead.amy # 1
dead.bob # 2
dead.cam # 3
dead.amy += 1 # 2
So is adding an initial method to initialize your member variables. No reason not to do so inside your __init__ directly.
class Dead:
def __init__(self):
self.amy = 1
self.bob = 2
self.cam = 3
Adding useless methods is not making your code better, it really just pollute it.
I'm trying to have a static int inside a class in python. But it doesn't work.
Here's an example of what I've implemented :
class MyDict(dict):
STR_DEPTH = -1
def __init__(self, **kwargs):
super(MyDict, self).__init__(**kwargs)
self.__dict__.update(name = kwargs.get("name", ""))
def __str__(self):
self.STR_DEPTH += 1
res = self.name + '\n'
for k in self.keys():
res += '\t'*self.STR_DEPTH + k + " = " + str(self[k])
res += '\n'
self.STR_DEPTH -= 1
return res
def main():
d1 = MyDict(one=MyDict())
d1["two"] = 2
d1["one"]["one"] = 1
d1["one"]["two"] = MyDict(three=3)
d1["four"] = 4
print d1
if __name__ == "__main__":
main()
and i'm expecting :
four = 4
two = 2
one =
two =
three = 3
one = 1
but it doesn't work that way. If i'm not mistaking, int aren't references and it's not the same "STR_DEPTH" in every instances of my class.
I already know the list-of-length-1 trick and the empty-type trick, but do i really need to resort do clumsy unreadable trick ?
Isn't there a better way since i'm inside a class ?
Where you have:
self.STR_DEPTH += 1
replace that with:
MyDict.STR_DEPTH += 1
and the same where you decrement the value.
Assigning to self.STR_DEPTH will create a new instance variable which hides access to the class variable through self. You can use self.STR_DEPTH to access the class variable provided you don't have an instance variable of the same name, but if you want to rebind the class variable you have to refer to it directly.
Note that self.STR_DEPTH += 1 is really just shorthand for self.STR_DEPTH = self.STR_DEPTH + 1 so even if the right hand self.STR_DEPTH picks up the class variable the assignment still happens back to the instance variable.
Hello im on my journey to understand classes in python, so to make it more fun im trying to make basic text rpg game. Right now im trying to make function which take instance of class as argument and is changing specific attribute of it for example:
class short_sword:
def __init__(self):
self.modf = 1
self.name = "Short Sword"
self.min_dmg = 1 * self.modf
self.max_dmg = 3 * self.modf
self.group = 0
Now im trying to change self.modf value by using function on instance of that class:
def jewel(short_sword):
short_sword.modf = short_sword.modf + 1
After that im creating object and printing values min_dmg and max_dmg before and after usage of that function to check if its works:
item = short_sword(1)
print(str(item.min_dmg))
print(str(item.max_dmg))
jewel(item)
print(str(item.min_dmg))
print(str(item.max_dmg))
but its stays the same 1 for min_dmg and 3 for max_dmg nothing is getting changed, how can i access that variable by function to change it?
English is not my native language so i hope that somebody will understand me Sorry for trouble and thanks for help :P
When you update your modf you don't update min_dmg and max_dmg. You could use an accessor:
class short_sword:
def __init__(self):
self.modf = 1
self.name = "Short Sword"
self.min_dmg = 1 * self.modf
self.max_dmg = 3 * self.modf
self.group = 0
def change_modf(self, newValue):
self.modf = newValue
self.processDmg()
def processDmg(self):
self.min_dmg = 1 * self.modf
self.max_dmg = 3 * self.modf
And then
def jewel(short_sword):
short_sword.change_modf(short_sword.modf + 1)
Because otherwise your properties still have their initial value.
Side note: you use
item = short_sword(1)
But your short_sword class doesn't take any argument in its constructor... What is the 1 supposed to be useful for?
So for a line class I'm doing, I keep getting an error that says
AttributeError: Line instance has no attribute 'point0'
I'm declaring the line like this:
def __init__(self, point0, point1):
self.x = point0
self.y = point1
def __str__(self):
return '%d %d' % (int(round(self.point0)), int(round(self.point1)))
And I get the x and y from my point class which should already be float values so I don't need to check for an error in my init method however I do check to see if point0 and point1 are floats in my rotate method:
def rotate(self, a):
if not isinstance(a, float) or not isinstance(self.point0, float) or not isinstance(self.point1, float):
raise Error("Parameter \"a\" illegal.")
self.point0 = math.cos(a) * self.point0 - math.sin(a) * self.point1
self.point1 = math.sin(a) * self.point0 + math.cos(a) * self.point1
So why does python keep saying that it has no attribute point0? I also tried changing my init method to look like this:
def __init__(self, point0, point1):
self.point0 = point0
self.point1 = point1
But when I do that the error says point0 has no attribute float. So why do I keep getting this error? Here's the code I'm using to test:
p0 = Point(0.0, 1.0)
p1 = Point(2.0, 3.0)
line = Line(p0,p1)
print line
I'm curious... how much do you know about scope in Python?
In your class, you have a member variable named x and another named y. Your init function accepts an argument called point0 and another called point1. It saves point0 in the x member variable, and point1 in y. Then, in your rotate function, you attempt to access a variable called point0. Do you see the problem?
An important thing to understand when programming (and this is true in most programming languages, if not all of them) is that the name of an argument doesn't affect the name of that data elsewhere. I can pass a variable called foo into a function that takes an argument called bar. In that function, I have to refer to the data as bar because that's the name of the variable. Later, after I've called that function, the name of the variable is still foo, because only the variable inside the function is called bar. Does that make sense?
your class accept point0 and point1 parameters when you call it. If you want to get values of these parameters you should use self.x(for point0) and self.y(for point1)
or another way;
class Line:
def __init__(self, point0, point1):
self.point0 = point0
self.point1 = point1
I suggest you to read;
Python __init__ and self what do they do?
https://www.ibiblio.org/swaroopch/byteofpython/read/class-init.html
https://docs.python.org/2/tutorial/classes.html
A few overall points before displaying your corrected code. (Note that not much actually changed):
Don't bother checking argument types. Python programmers are assumed to be responsible enough to read the documentation and pass values of the correct value.
Your Line class was duplicating code that you had already defined in the Point class. The attributes of a line are Point instances, so you can use the methods you defined to implement the Line methods.
There's no reason to round the point coordinates to integers when displaying them; show the actual floating-point values that define the point. Your Line.__str__ method can take advantage of the fact that you've defined Point.__str__.
And now, your much shorter and corrected code, with some interspersed comments.
import math
class Point:
def __init__(self, x, y):
'''x and y should be floats'''
self.x = x
self.y = y
def rotate(self, a):
'''Rotate the point around the origin by a radians'''
self.x = math.cos(a) * self.x - math.sin(a) * self.y
self.y = math.sin(a) * self.x + math.cos(a) * self.y
# If you *were* going to check if a is a float, you
# need to do it *before* you use it.
def scale(self, f):
'''Scale the point by f units''' # you get the idea
self.x = f * self.x
self.y = f * self.y
def translate(self, delta_x, delta_y):
self.x = self.x + delta_x
self.y = self.y + delta_y
def __str__(self):
# If you're storing floats, it's probably useful
# to output them.
return '(%f, %f)' % (self.x, self.y)
# Operations on a line all involve applying the same operations
# to each of its end points.
class Line:
def __init__(self, point0, point1):
self.point0 = point0
self.point1 = point1
def rotate(self, a):
self.point0.rotate(a)
self.point1.rotate(a)
def scale(self, factor):
self.point0.scale(factor)
self.point1.scale(factor)
# If for whatever reason you didn't want to use Point.scale
# here, the code would be...
# self.point0.x = f * self.point0.x
# self.point0.y = f * self.point0.y
# self.point1.x = f * self.point0.x
# self.point1.y = f * self.point0.y
def translate(self, delta_x, delta_y):
self.point0.translate(delta_x, delta_y)
self.point1.translate(delta_x, delta_y)
def __str__(self):
# You've already defined out to turn a Point into
# a string, so you can take advantage of that here.
return "%s -- %s" % (self.point0, self.point1)
I'm going to add another answer here, both because I lack the reputation to comment on the other answer and because I feel this answer is unrelated to my previous answer (which addressed a different problem than what you're seeing now).
So. That said, look at this line of code:
return '%d %d' % (int(round(self.point0)), int(round(self.point1)))
round is a function that takes a numeric argument. However, self.point0 and self.point1 are not numbers. They are points. If you want the numbers from them, you'll have to refer to those explicitly (i.e. self.point0.x).