Question about setter and calling MyClass() - python-3.x

I have a class like this:
class A:
b = ""
#property
some_property(self):
raise Error()
#some_property.setter
def some_property(self, some_property_var)
self.b = some_property_var
and i want to do A(some_property='A'), but i can't because
TypeError: A() takes no arguments
. Is there any way to make it work?

I think this is a better example of how to demonstrate what you are trying to do;
#set a property in a class in python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
#property
def name(self):
return self._name
#name.setter
def name(self, name):
self._name = name
#property
def age(self):
return self._age
#age.setter
def age(self, age):
self._age = age
p = Person("John", 36)
So in your case;
class A:
def __init__(self, b):
self.b = b
#property
def b(self):
return self._b
#b.setter
def b(self, b):
self._b = b
a = A(1)
print(a.b)
Based on your comments;
#create a class that takes keyword arguments
class A:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
a = A(a=1, b=2)

Related

Python: detect changes in a subclass

Let's consider the following example:
class SubClass:
def __init__(self):
self._param = None
#property
def param(self):
print('read param')
return self._param
#param.setter
def param(self, value):
print('set param')
self._param = value
class MainClass:
def __init__(self):
self._var = SubClass()
#property
def var(self):
print('read var')
return self._var
#var.setter
def var(self, value):
print('set var')
self._var = value
If I do:
cls = MainClass()
cls.var.param = 3
I obtain:
'read var'
'set param'
How can I make MainClass aware that var.param has changed?
Useful additional info: consider that in my actual code param is not a scalar but an array with hundreds of elements, so I would like to avoid to create a copy and then just compare them. Moreover, param and var are not the only properties.
One approach is to pass a method from MainClass as an argument when instantiating SubClass, and have SubClass call it whenever it changes a variable:
class SubClass:
def __init__(self, changed):
self._param = None
self.changed = changed
#property
def param(self):
print('read param')
return self._param
#param.setter
def param(self, value):
print('set param')
self._param = value
self.changed('param')
class MainClass:
def __init__(self):
self._var = SubClass(self.changed)
def changed(self, name):
print("Subclass changed: ", name, getattr(self._var, name))
#property
def var(self):
print('read var')
return self._var
#var.setter
def var(self, value):
print('set var')
self._var = value
m = MainClass()
m.var.param = 'test'

Why does one property work and the other not?

It happens that I have two property implementations. but one works and the other does not. That is, that in one it does not even enter the setters.
I gave myself the task of wandering online, and this happens to me is very rare, both are supposed to work.
Do you know why this happens?
Thank you
class QuickTasks():
def __init__(self, name=None, value=None):
self.name = name
self.value = value
#property
def name(self):
return self._name
#name.setter
def name(self, value):
if isinstance(value, str):
self._name = value
else:
raise TypeError("name must be str")
#property
def value(self):
return self._value
#value.setter
def value(self, value):
if isinstance(value, int):
self._value = value
else:
raise TypeError("value must be int")
obj = QuickTasks(name=4, value='j')
print(obj.name)
obj.name = 5
print(obj.name)
################################################################
class TreeNode(object):
def __init__(self, value = None):
self.value = value
self._left_node = None
self._right_node = None
#property
def value(self):
return self._value
#value.setter
def value(self, value):
if isinstance(value, int):
self._value = 8
else:
raise TypeError("value must be int")
def main():
tree_node = TreeNode(3)
#tree_node.value = 3
print (tree_node.value)
if __name__ == '__main__':
print("")
main()
When you hit the line:
obj = QuickTasks(name=4, value='j')
and it assigns to self.name in the QuickTasks initializer, it raises a TypeError, which you don't catch. That bypasses the rest of your code entirely, skipping all uses of the value property (and of TreeNode entirely).

how to set property for parent class inside child class in python?

I have two class one is Vehicle and one is BMW, I know I can create a color as property unver Vehicle. However how I set the property inside class BMW
but i am still able to access color as bmw.info,color? Can I do something like following?
class Vehicle:
def __init__(self, name):
self.name = name
self._color = None
#property
def color(self):
return self._color
#color.setter
def color(self, color):
self._color = color
class BMW:
def __init__(self, name):
self.info = Vehicle(name)
#can I do something like
class Vehicle:
def __init__(self, name):
self.name = name
class BMW:
def __init__(self, name):
self.info = Vehicle(name)
setattr(self.info, "color", None)
#info.property
def color(self):
return self._color
#info.color.setter
def color(self, color):
self._color = color
bmw = BMW('sister')
print(bmw.info.color)
bmw.info.color = 'red'
print(bmw.info.color)

python lost data-descriptor as a instance attribute?

class data_attr_set_pass(object):
def __init__(self, inner=None, name=""):
self.inner = inner
self.name = name
def __get__(self, instance, owner):
return self.inner
def __set__(self, instance, value):
pass
def __repr__(self):
return str(self.name) + ":" + str(self.inner)
class data_attr(object):
def __init__(self, inner=None, name=""):
self.inner = inner
self.name = name
def __get__(self, instance, owner):
return self.inner
def __set__(self, instance, value):
self.inner = value
def __repr__(self):
return str(self.name) + ":" + str(self.inner)
class non_data_attr(object):
def __init__(self, inner=None, name=""):
self.inner = inner
self.name = name
def __get__(self, instance, owner):
return self.inner
def __repr__(self):
return str(self.name) + ":" + str(self.inner)
class Myclass(object):
x = data_attr_set_pass(11, "class attr")
def __init__(self):
self.x = data_attr(890, "instance attr")
print(Myclass.x)
m = Myclass()
print(Myclass.x)
print(m.x)
print(Myclass.__dict__)
print(m.__dict__)
output:
11
11
11
{'__module__': '__main__', 'x': class attr:11, '__init__': <function Myclass.__init__ at 0x7f0dcc2d1378>, '__dict__': <attribute '__dict__' of 'Myclass' objects>, '__weakref__': <attribute '__weakref__' of 'Myclass' objects>, '__doc__': None}
{}
I had some tests for usage of python data-descriptor. And one test had very strange behaviour. I know that descriptor should be class attr, it's just a test:).
I put pass in __set__ of class data_attr_set_pass. So as far as I know, self.x = data_attr(890, "instance attr") in __init__ will put data_attr(890, "instance attr") into self.__dict__. But it can be found nowhere.
why does it happend and where can I find the data-descriptor?
==================================================================
It's really my misunderstanding, I just run first test in code below in which I put 2 into self.__dict__["x"] directly, the second one can prove it.
class Myclass(object):
x = data_attr_set_pass(11, "class attr")
def __init__(self):
self.__dict__["x"] = 2
print(Myclass.x)
m = Myclass()
print(Myclass.x)
print(m.x)
print(Myclass.__dict__)
print(m.__dict__)
print('================')
class Myclass(object):
x = data_attr_set_pass(1324, "class attr")
def __init__(self):
self.x = 2232
print(Myclass.x)
m = Myclass()
print(Myclass.x)
print(m.x)
print(Myclass.__dict__)
print(m.__dict__)
You say
I put pass in __set__ of class data_attr_set_pass. So as far as I know, self.x = data_attr(890, "instance attr") in __init__ will put data_attr(890, "instance attr") into self.__dict__.
But why would it do that? You didn't write data_attr_set_pass.__set__ to insert the value into the instance __dict__. You wrote your __set__ to do nothing but pass.
Assigning something to self.x does exactly what you wrote your __set__ to do: nothing.

Override abstract setter of property in Python 3

What is the simplest / most pythonic way to override only the setter of an abstract property in Python 3? Variant 3 seems to mean the least effort for the derived class implementor. Is it correct? Does it have disadvantages?
import abc
class A1(metaclass=abc.ABCMeta):
def __init__(self, x, **kwargs):
super().__init__(**kwargs)
self._x = x
#property
def x(self):
return self._x
#x.setter
#abc.abstractmethod
def x(self, value):
self._x = value
class B1(A1):
#property
def x(self):
return super().x
#x.setter
def x(self, value):
print("B1 setter")
super(B1, self.__class__).x.fset(self, value)
b1 = B1(x=1)
b1.x = 3
print(b1.x)
class A2(metaclass=abc.ABCMeta):
def __init__(self, x, **kwargs):
super().__init__(**kwargs)
self._x = x
#abc.abstractmethod
def _get_x(self):
return self._x
#abc.abstractmethod
def _set_x(self, value):
self._x = value
x = property(_get_x, _set_x)
class B2(A2):
def _get_x(self):
return super()._get_x()
def _set_x(self, value):
print("B2 setter")
super()._set_x(value)
x = property(_get_x, _set_x)
b2 = B2(x=1)
b2.x = 3
print(b2.x)
class A3(metaclass=abc.ABCMeta):
def __init__(self, x, **kwargs):
super().__init__(**kwargs)
self._x = x
def _get_x(self):
return self._x
#abc.abstractmethod
def _set_x(self, value):
self._x = value
x = property(
lambda self: self._get_x(),
lambda self, value: self._set_x(value))
class B3(A3):
def _set_x(self, value):
print("B3 setter")
super()._set_x(value)
b3 = B3(x=1)
b3.x = 3
print(b3.x)
So, yes, you listed a lot of ways in there - and although the one that requires more code is your variant 3, the most straighforard, least surprising way to do it is your variant 1 -
It just works, and is perfectly readable, no surprises - and there seems to be no simpler way than calling fget explicitly there.

Resources