I have a class where I want to validate the data whenever it's property is changed. I wish to store the valid options as a class variable that the setter can refer to, but I seem to have found that within the #var.setter option I'm unable to reference any class variables at all.
Why is that?
Code example:
class Standard():
def __init__(self):
self.variable1 = 1
self.variable2 = 2
#property
def variable1(self):
# This works
print(self.variable2)
return self.__variable1
#variable1.setter
def variable1(self, var):
# This doesn't work
print(self.variable2)
self.__variable1 = var
x = Standard()
print(x.variable1)
x.variable1 = 4
print(x.variable1)
This outputs:
AttributeError: 'Standard' object has no attribute 'variable2'
When it clearly does.
You are first setting variable1 in __init__:
def __init__(self):
self.variable1 = 1
self.variable2 = 2
Since self.variable1 is handled by #variable1.setter, variable2 can't yet exist at that time. You could swap the two lines:
def __init__(self):
self.variable2 = 2
self.variable1 = 1
Now variable2 is properly set before variable1.setter runs.
Alternatively, give variable2 a class attribute to act as a default:
class Standard():
# ...
variable2 = 'class default'
#variable1.setter
def variable1(self, var):
print(self.variable2)
self.__variable1 = var
or use getattr() on self:
#variable1.setter
def variable1(self, var):
print(getattr(self, 'variable2', 'not available yet'))
self.__variable1 = var
or set __variable1 directly, bypassing the setter:
class Standard():
def __init__(self):
self.__variable1 = 1 # don't use the setter
self.variable2 = 2
Related
I want to reference a class attribute from class variable but it gives me error 'self is not defined'
class Test:
def __init__(self, val):
self.val = val
data = self.val
def main(self):
print(self.data)
When you say data = self.val outside __init__, you are defining a class variable, not an instance variable. This line affects all objects of type Test. However, self is not recognized in this scope.
If you want val to update all instances of this class,
class Test:
data = None
def __init__(self, val):
self.val = val
Test.data = self.val
In this case,
test1 = Test(1)
print(test1.data) # prints 1
print(Test.data) # prints 1
test2 = Test(2)
print(test1.data) # prints 2
print(test2.data) # prints 2
print(Test.data) # prints 2
I have a class like this
class Test:
def __init__(self, var):
self.var = var
def test(self):
x = self.var + 2
return x
And then I make a class like this
class Test:
def __init__(self, var):
self.var = var
def test(self):
self.x = self.var + 2
return self.x
I understand that I can use self to separate attribute values across various instances of this class. My question is, if I create many utility variables (like x) inside a method, should I always create them using self?
Can anyone explain how the above two classes behave differently (if they do)?
Let's see the difference between the two classes :
class Test:
def __init__(self, var):
self.var = var
def test(self):
x = self.var + 2
return x
Let's create a Test object:
t = Test(1)
And see what we can do
t.var # 1
t.x # Raises AttributeError : no such attribute in the class
t.test() #3
t.x # Still erroring
And with your second class
class Test:
def __init__(self, var):
self.var = var
def test(self):
self.x = self.var + 2
return self.x
Let's create a Test object:
t = Test(1)
And see what we can do
t.var # 1
t.x # Raises AttributeError : no such attribute in the class
t.test() #3
t.x # 3
So what ? Well we can see that any variables defined with self.VARNAME persist in the instance, while simple local variables, without self., dosen't.
However, if x needs to be accessible with t.x, i'd probably go for a property, like so
class Test:
def __init__(self, var):
self.var = var
#property
def x(self):
x = self.var + 2
return x
t = Test()
t.x # 3
I want local variable of a class to be changed by other class. My script is similar to the following :
import datetime
b = []
class P:
def __init__(self):
self.count = 1
self.create()
def create(self):
global b
a = C(self.count)
for i in range(10):
a.print_name()
print b
class C:
def __init__(self, *data):
self.test = data[0]
#staticmethod
def print_name():
global b
b.append(datetime.datetime.now())
o = P()
How to avoid use of a global variable . On web i found use of "super " can resolve the issue . Please help in this regard .
Make C constructor to accept P instance. And call the method of P to append item to instance attribute of P object.
class P:
def __init__(self):
self.count = 1
self.items = []
self.create()
def append(self, item):
self.items.append(item)
def create(self):
a = C(self, self.count) # <-- Pass P instance (self)
for i in range(10):
a.print_name()
print self.items
class C:
def __init__(self, p_instance, *data):
self.p_instance = p_instance # <-- Save P instance to use later
self.test = data[0]
def print_name(self):
self.p_instance.append(datetime.datetime.now()) # <-- Call p instance method
You are probably looking for a class attribute. If you add b as an attribute to the C class, it can be accessed as C.b and C().b, i.e. from a reference to the class or any instance.
class C(object): # classes in py2 should inherit from object!
b = [] # b inside C definition
#classmethod
def print_name(cls):
cls.b.append(datetime.datetime.now())
class P(object):
def __init__(self):
self.count = 1
self.create()
def create(self):
a = C(self.count)
for i in range(10):
a.print_name()
print C.b # or a.b
Of course, you can also place b on P. In this case, do
def print_name():
P.b.append(datetime.datetime.now())
Have written a simple code like this:
class Operations:
#global a,b
a=1
b=2
def __init__(self):
print(self,"object has been created")
def add(self):
#a = 2
#b = 3
return a+b
obj1=Operations()
sum=obj1.add()
print(sum).
when i run this code, am getting this error NameError: name 'a' is not defined.
can you please explain why variables a and b are not accessible in the method 'add' which is defined in the same class?
Note:when am declaring variables as a global, am able to access the variables inside the 'add' method.
You need to use the self keyword.
What does self do?
a = 1
class Operations:
a = 2
def fun1(self):
return a
def fun2(self):
return self.a
obj = Operations()
print(obj.fun1())
print(obj.fun2())
Output:
1
2
Solution for you case:
class Operations:
a=1
b=2
def __init__(self):
print(self,"object has been created")
def add(self):
return self.a + self.b
obj1=Operations()
print(obj1.add())
Output:
<__main__.Operations object at 0x100663588> object has been created
3
Use the class reference
Value= self.a + self.b
Is this the answer that you need? if you're writing a class, use self.value instead global value:
class Operations:
def __init__(self):
self.a = 1
self.b = 2
print(self, "object has been created")
def add(self):
return self.a + self.b
obj1 = Operations()
print(obj1.add())
class A():
def __init__(self):
self.__var = 5
def get_var(self):
return self.__var
def set_var(self, value):
self.__var = value
var = property(get_var, set_var)
a = A()
a.var = 10
print a.var == a._A__var
Can anyone explain why result is False?
The property decorator only works on new-style classes. In Python 2.x, you have to extend the object class:
class A(object):
def __init__(self):
self.__var = 5
def get_var(self):
return self.__var
def set_var(self, value):
self.__var = value
var = property(get_var, set_var)
Without the behavior of the new-style class, the assignment a.var = 10 just binds a new value (10) to a new member attribute a.var.