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?
Related
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.
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 3 years ago.
I've the following class structure:
class StarCount:
one_stars = 0
two_stars = 0
three_stars = 0
four_stars = 0
five_stars = 0
class OrientationAnalysis:
straight = StarCount()
bisexual = StarCount()
gay = StarCount()
class GenderAnalysis:
men = OrientationAnalysis()
women = OrientationAnalysis()
I've written the following code:
genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100
print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is also 100
Why genderanalysis.women.straight.five_stars is also updated? I've checked the genderanalysis.women.gay.five_stars also but it's not updated?
When you declare some variables like this:
class StarCount:
one_stars = 0
two_stars = 0
three_stars = 0
four_stars = 0
five_stars = 0
These variables become class variables. Class variables are variables that are shared by all instances of a class. So when you updated genderanalysis.men.straight.five_stars, it actually updated StarCount.five_stars and as genderanalysis.women.straight.five_stars also points to the same variable, it seemed to have updated too.
I think what you are looking for are instance variables. You can declare them like this:
class StarCount:
def __init__(self):
self.one_stars = 0
self.two_stars = 0
self.three_stars = 0
self.four_stars = 0
self.five_stars = 0
Edit
Why genderanalysis.women.gay.five_stars is not updated?
What happens is that before you updated any variable of genderanalysis object, all of the variables were pointing to the variables of StarCount class. As you can see they have same id:
print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229389744'
print(id(genderanalysis.women.gay.five_stars)) # prints '94016229389744'
But when you changed genderanalysis.men.straight.five_stars, the reference/pointer got replaced with your provided value, in this case 100. You can see difference in their id's:
print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', see the difference?
So now genderanalysis.men.straight.five_stars does not point to StarCount.five_stars, rather it points to OrientationAnalysis.straight.five_stars. Once again, let's check their id's:
print(id(OrientationAnalysis.straight.five_stars)) # prints '94016229391328'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', same right?
Now onto your question, at this point genderanalysis.women.gay.five_stars is still untouched so it points to StarCount.five_stars and so it still prints 0. Change StarCount.five_stars and you can see the change reflecting in genderanalysis.women.gay.five_stars.
StarCount.five_stars = 101
print(genderanalysis.women.gay.five_stars) # prints `101`
Define the values in the init methods of the classes, so that they become attached to intance objects, not the class object itself.
class StarCount:
def __init__(self):
self.one_stars = 0
self.two_stars = 0
self.three_stars = 0
self.four_stars = 0
self.five_stars = 0
class OrientationAnalysis:
def __init__(self):
self.straight = StarCount()
self.bisexual = StarCount()
self.gay = StarCount()
class GenderAnalysis:
def __init__(self):
self.men = OrientationAnalysis()
self.women = OrientationAnalysis()
genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100
print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is now 0
your attributes should not be class attributes but instance attributes instead. this would be a start for you:
class StarCount:
def __init__(self, five_stars=0):
self.five_stars = five_stars
# ...
class OrientationAnalysis:
def __init__(self):
self.straight = StarCount()
# ...
class GenderAnalysis:
def __init__(self):
self.men = OrientationAnalysis()
self.women = OrientationAnalysis()
you’re almost there— you are referencing and modifying class variables rather than instance variables.
You need an __init__(self) method, and to create all the attributes on self
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.
code:
class aa:
def getDis():
return 0
class bb(aa):
def getDis():
return 10
class cc(aa):
def getDis():
return 15
class d:
def __init__(self,cust):
self.cust = cust
self.memberLevel = aa()
def cgl(self,amt):
if amt ==1:
self.memberLevel = bb()
elif amt ==2:
self.memberLevel = cc()
else:
self.memberLevel = aa()
Well i have these four classes. What i am trying to do is that in my top three classes i have inheritance. In my class d i am trying to call the respective method if the amount is 1 0r 2 . Instead it is giving me this output:
d1 = d('one')
d1.cgl(1)
print(d1.memberLevel)
output:
<__main__.bb object at 0x036D7BF0>
So help required that how can i use overriding technique.
It seems you were hoping to see the console output:10
Because d1.memberLevel is the bb class itself (not the value 10, and not the function that returns the value 10), the console output shows <__main__.bb object at 0x036D7BF0>. This is correct behavior when printing an object directly.
Perhaps your last line of console code should say:
print(d1.memberLevel.getDis())
Another option would be to assign the value within the "d" class:
self.memberLevel = bb().getDis()
And the member methods require "self", e.g.:
def getDis(self):
return 10
see my comments and please help me
class cercle:
Pi = 3,14159
def __init__(self):
self._rayon = 1
self._abcisse = 1
self._ordonnee = 1
if self._rayon < 0:
return -self._rayon #i want to take the opposite value if it is negative
def aire(self):
self.Pi * self._rayon ** 2 #How to do the power 2 ?
def permietre(self):
cercle.Pi * self._rayon * 2
aire(self) #How to call the aire method to go inside ?
i want to call the aire method but i can't because there is the problem with argument self
but i have
File "labspoo.py", line 26, in cercle
print(self.aire())
NameError: name 'self' is not defined
Mac:~ MatR$
class cercle:
Pi = 3.14159 # Changed from , to a . which is the decimal separator in Python.
def __init__(self):
self._rayon = 1
self._abcisse = 1
self._ordonnee = 1
if self._rayon < 0:
return -self._rayon #i want to take the opposite value if it is negative
def aire(self):
self.Pi * self._rayon ** 2 #How to do the power 2 ?
def permietre(self):
cercle.Pi * self._rayon * 2
x = cercle()
x.aire()
aire is a function of the class cercle, there for you need to instanciate cercle first and put it in a variable.
You can then use that variable (x in my case) to call on your aire function.
self is a mandatory parameter on all class functions within a class that you use to grab variables inside the class, for instance self._rayon.