I have two classes. a and b.
In one of class a's methods, I created an object of class b. One of class b attributes takes a function. So say I gave it a random function but does this function of class b have access to class a's attribute? even though I didn't pass it in directly as a parameter?
class b:
def __init__(self):
self.attribute_function = None
class a:
def __init__(self):
self.temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda self: self.counter < self.temp
return obj.attribute_function()
if __name__ == "__main__":
#pass
obj = a()
print obj.temp()
In the above example, I tried to provide a really basic example, but if you run it, it doesn't work...
Revised Code, class a should look like this:
class a:
def __init__(self):
self.temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda args: self.counter < self.temp
return obj.attribute_function(1) # i added this 1 to fill in arg
This works:
class b:
def __init__(self):
self.attribute_function = None
class a:
def __init__(self):
self._temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda self=self: self.counter < self._temp
return obj.attribute_function()
if __name__ == "__main__":
obj = a()
print obj.temp()
On problem you had is self.temp = 10 which shadowed your method temp().
Another problem: lambda self: self.counter < self._temp. Your lambda function was expecting an argument. But omitting self is not a good idea lambda : self.counter < self._temp, because if you call obj.attribute_function() somewhere where self is not available or has changed - it will not find self or use another self. self=self fixes that.
But generally such magic is an anti-pattern. Tell us what are your trying to achieve, and there should be a better way to do what you want. Otherwise this kind of code will ensure many headaches.
I think this is a better solution (called strategy pattern):
class B:
def __init__(self, a):
self.a = a
def temp(self):
return self.a.temp()
class A:
def __init__(self):
self._temp = 10
self.counter = 0
def temp(self):
return self.counter < self._temp
if __name__ == "__main__":
obj = B(A())
print obj.temp()
Your example does not work because you have a name collision at temp
You have assigned temp to be both a method:
def temp(self):
and an attribute:
self.temp = 10
Related
class Player:
def __init__(self):
self.godHole = GodHole
self.pits = []
for i in range(0, 6):
self.pits.append(Pit())
def return_stones(self):
return self.godHole.return_stones(self.godHole)
#or return self.godHole.return_stones()
# same warning for invoking seld.godHole.increment_stones()
class GodHole:
def __init__(self):
self.stones = 0
def return_stones(self):
return self.stones
def change_stones(self, s):
self.stones = s
def increment_stones(self):
self.stones += 1
When using the commented line I get self unfilled warning. when I used the first one I get the expected type ' ' but got 'Type[]' warning
What am I doing wrong? How can I fill self parameter? Can I even access instance attributes this way?
The attribute godHole of class Player, it is just a class, and no instantiation operation is performed, you directly use the instance method return_stones below, and pass in the class GodHole, which is wrong.
There are two ways to execute instance methods:
call directly using the class instance
when a class uses an instance method, the instance is passed in as a parameter
class Player:
def __init__(self):
self.godHole = GodHole()
self.pits = []
for i in range(0, 6):
self.pits.append(Pit())
def return_stones(self):
return self.godHole.return_stones()
or
class Player:
def __init__(self):
self.godHole = GodHole
self.pits = []
for i in range(0, 6):
self.pits.append(Pit())
# def return_stones(self):
# return self.godHole.return_stones(self.godHole())
def return_stones(self, obj: GodHole):
# obj is an instance object of class GodHole
return self.godHole.return_stones(obj)
I'm trying to set a variable and be able to change and store that variable using set and gets. The current output is:
0
0
I'm trying to get it to be:
0
2
Can some one help me understand how to change a value and then use it later in python? Kind of like a toggle?
class Spammer:
def __init__(self, spam = 0):
self._spam = spam
# getter method
def get_spam(self):
return self._spam
# setter method
def set_spam(self, x):
if x == 1:
return self._spam+1
if x== 0:
return self._spam
spammer=Spammer()
print (spammer.get_spam())
spammer.set_spam(1)
print(spammer.get_spam())
There is an #property decorator builtin so you could do the following:
class Spammer:
def __init__(self, spam = 0):
self._spam = spam
#property
def spam(self):
return self._spam
#spam.setter
def spam(self, new_spam):
self._spam = new_spam
Is there a way in Python to get a reference to an object on which a method was called?
And in case it is, is it possible even in a nested way?
my_class.py:
from modules import math_ops
class A():
def __init__(self):
self.math_ops = math_ops.B()
self.number = 1
modules/math_ops.py:
class B():
def add_1():
where_to_add = # Get instance of A() object
where_to_add.number += 1
To execute this:
>>> a = A()
>>> a.math_ops.add_1()
And get this:
>>> a.number
2
I'm asking because I am interested in writing a static method which works with the object on which it was called, but would like to avoid using the object as an argument as it would be much nicer to call a method like my_object.prop.static_method() instead of my_object.prop.static_method(my_object).
If you never plan on reassigning math_ops outside A, this is fairly simple to do.
from modules import math_ops
class A():
def __init__():
self.math_ops = math_ops.B(self)
self.number = 1
modules/math_ops.py:
class B():
def __init__(self, creator):
self.creator = creator
def add_1():
creator.number += 1
I will mention it again in case you skimmed the first line, the following will generate unexpected results since B is tracking the creator of the object rather than the caller.
a1 = A()
a2 = A()
a1.math_ops = a2.math_ops
a1.math_ops.add_1() # a2 is updated
If that looks like something you might wanna do, the answer is a tad more complicated. Here's my attempt:
from modules import math_ops
class A():
def __init__(self):
self._math_ops = math_ops.B(self)
self.number = 1
#property
def math_ops(self):
self._math_ops.set_caller(self)
return self._math_ops
#math_ops.setter
def math_ops(self, new_math_ops):
self._math_ops = new_math_ops
modules/math_ops.py:
class B():
def __init__(self, caller):
self.caller = caller
def set_caller(self, caller):
self.caller = caller
def add_1(self):
self.caller.number += 1
class A():
number = 1
class B():
def add_1():
where_to_add = A
where_to_add.number += 1
B.add_1()
print(A.number)
B.add_1()
print(A.number)
B.add_1()
print(A.number)
I have a question about python using OOP.
If I have two classes, and a method which takes variables from those classes, I pass the classes as parameters of the method as shown below. I am sure that this is not the right approach, and this is why I would like to know an alternative and more efficient way to do it. Specifically:
class Player(object):
x_player = 5
y_player = 5
class Food(object):
x_food = 10
y_food = 10
def method(Player, Food):
if Player.x_player > Food.x_food:
print('Food behind)
if Player.x_player < Food.x_food:
print('Food in front')
Is this correct? If I use the method def __init(self)__ then I cannot pass those variables in the function.
Thank you
If I use the method def init(self) then I cannot pass those variables in the function.
This understanding is wrong, as you can add parameters to __init__.
How about this? Or you still insist to use class method? If you choose class method, your solution already ok, just call with method(Player, Food) or even you did not need the parameters added in the function.
class Player(object):
def __init__(self, x, y):
self.x_player = x
self.y_player = y
class Food(object):
def __init__(self, x, y):
self.x_food = x
self.y_food = y
def method(player, food):
if player.x_player > food.x_food:
print('Food behind')
if player.x_player < food.x_food:
print('Food in front')
method(Player(5, 5), Food(10, 10))
if those are class variables, you can just refer to those variables as classname.var_name:
class A:
a = 10
if __name__ == '__main__':
print(A.a)
if the values are defined by instance, then you need to instantiate the class variables and then you can perform comparison on that
class A:
def __init__(self, a):
self.a = a
if __name__ == '__main__':
x = A(5)
y = A(10)
print(x.a > y.a)
>> False
Also this is python and in python you don't specify the data types of function arguments so you can send any object and be carefree of which class' instance it is. You code should handle the exceptions if a wrong class' object is sent.
class A:
def __init__(self, a):
self.a = a
class B:
def __init__(self, a):
self.a = a
def fun(obj):
print(obj.a)
if __name__ == '__main__':
x = A(5)
y = B(10)
fun(x)
fun(y)
>> 5
>> 10
class A:
def __init__(self, a):
self.a = a
class B:
def __init__(self, a):
self.a = a
def fun(obj):
if not isinstance(obj, B):
print(obj.a)
if __name__ == '__main__':
x = A(5)
y = B(10)
fun(x)
fun(y)
>> 5
Trying to get a work around for getting access to a class method in another class while being inside a class. Code below will probably explain my goal.
class Access(object):
def __init__(self):
pass
def select(self, value):
Store.keep(value)
class Store(object):
def __init__(self):
self.store_value = 0
def keep(self, value):
self.store_value = value
x = Access()
y = Store()
x.select(10)
y.store_value
##Want the output of 10
I don't see any way to do what you want without Access having a reference to a Store object.
The closest thing you can do is
class Access(object):
def __init__(self):
pass
def select(self, value):
Store.keep(value)
class Store(object):
#classmethod
def keep(cls, value):
cls.store_value = value
x = Access()
y = Store()
x.select(10)
print y.store_value #will print 10
#but
z = Store()
print z.store_value #will print 10 too
Where store_value is shared by all instances of Store.
You could pass an instance to select also and use Store.keep(inst, value):
class Access(object):
def __init__(self):
pass
def select(self, inst, value):
Store.keep(inst, value)
class Store(object):
def __init__(self):
self.store_value = 0
def keep(self, value):
self.store_value = value
x = Access()
y = Store()
x.select(y, 10)
print(y.store_value)
10