Python object #property - python

I'm trying to create a point class which defines a property called "coordinate". However, it's not behaving like I'd expect and I can't figure out why.
class Point:
def __init__(self, coord=None):
self.x = coord[0]
self.y = coord[1]
#property
def coordinate(self):
return (self.x, self.y)
#coordinate.setter
def coordinate(self, value):
self.x = value[0]
self.y = value[1]
p = Point((0,0))
p.coordinate = (1,2)
>>> p.x
0
>>> p.y
0
>>> p.coordinate
(1, 2)
It seems that p.x and p.y are not getting set for some reason, even though the setter "should" set those values. Anybody know why this is?

The property method (and by extension, the #property decorator) requires a new-style class i.e. a class that subclasses object.
For instance,
class Point:
should be
class Point(object):
Also, the setter attribute (along with the others) was added in Python 2.6.

It will work if you derive Point from object:
class Point(object):
# ...

Related

Inheriting function data

I have a question about inheriting data from functions, defined inside another class. I have written an example script to clarify myself. In this script I define a class called Test. Here I define x and y in the __init__() function. Thereafter, I make a calculation and return x,y. I then create another class called Inherit_Test that inherits the x,y from Test. In this class I define z and make a calculation with the inherited values from Test. Afterwards, I call the class with Values. The problem arises when I want to access the data stored in Values. The type of this object is "Inherited_Values", while you would expect the type to be int and have the value 3*4*43. I hope I have explained myself well enough, thanks!
class Test():
def __init__(self, x , y ):
self.x = x
self.y = y
def Calculation(self):
self.x = 3*4 #self.x*self.x
self.y = 43 #self.y*self.y
return self.x, self.y
class Inherit_Test(Test):
def __init__(self,z ):
Test.__init__(self, x = Test.Calculation(self)[0],
y = Test.Calculation(self)[1])
self.z = z
def Inherit_Calculation(self):
self.z = self.x * self.y
return self.z
Value = Inherit_Test(0)
Value.Inherit_Calculation()
unfortunately, your question is not very clear defined and it is hard to assume what you exactly wanted to do. I'll try to help you with the following code :
class Test():
def __init__(self):
self.Calculation() # instantiation of the self.x and self.y; no init params needed
def Calculation(self):
self.x = 3*4 #self.x*self.x
self.y = 43 #self.y*self.y
#return self.x, self.y # do you need to return something here ?
class Inherit_Test(Test):
def __init__(self):
super().__init__() # instantiation of the parameters of your super class
#self.z = z # do you need this part ?
def Inherit_Calculation(self):
self.z = self.x * self.y
return self.z
Result:
Value = Inherit_Test()
print(type(Value.Inherit_Calculation()))
print(Value.x)
print(type(Value.x))
print(Value.y)
print(type(Value.y))
print(Value.z)
print(type(Value.z))
<class 'int'>
12
<class 'int'>
43
<class 'int'>
516
<class 'int'>

Is there an accepted pythonic way of splitting off a base class part from a subclass object?

I am looking for the best way to split off the base class content of a subclass object. That is, if I have an object b of class B, which subclasses class A, I would like a method for class B that returns an object a of class A with the relevant content taken from b (which is a subset of all the content in b). Currently I have roughly the following (the actual classes are more complicated of course, this is a simplified toy example)
class A:
def __init__(self):
self.x = 0
def update(self, dx):
self.x += dx
class B(A):
def __init__(self):
super().__init__()
self.y = None
def update(self, dx):
super().update(dx)
self.y = self.x*self.x
def split_off_base_part(self):
a = A()
a.__dict__.update({k: v for k, v in self.__dict__.items() if k in a.__dict__})
return a
but I am not too happy with it. Is there a more pythonic way of doing this? Possibly one that doesn't require calling A.__init__ or is this simply not possible in general?
You could re-define the init for A so that it can optionally take parameters, that is nice than trying to update the __dict__.
class A:
def __init__(self, _x = 0):
self.x = _x
def update(self, dx):
self.x += dx
class B(A):
def __init__(self):
super().__init__()
self.y = None
def update(self, dx):
super().update(dx)
self.y = self.x*self.x
def toA(self):
return A(self.x)
Or you could define that as a class-method (almost like a second constructor) on A, which takes a B and returns a stripped down A.

Should I use the class name or `cls` param to construct a an instance?

As title described, I an confused as the example:
class Point(object):
def __init__(self, x=0.0, y=0.0):
self.x, self.y = x, y
#classmethod
def get_point1(cls, cor): # cor is list with x=1 and y=2
return Point(cor[0], cor[1])
#classmethod
def get_point2(cls, cor):
return cls(cor[0], cor[1])
I am confused which one(get_point1 or get_point2) should I use, and what is the difference between them?
The #classmethod decorator makes the function a class method, as opposed to instance method. To make it more robust, it is preferable to use cls rather than the actual class name where it is defined.
If you use cls, the parameter which will be passed depends on the actual class being called (for example, if you subclass Point) while using Point explicity, may cause issues if you subclass it and use the class method.
Look at this code for example
class Point(object):
def __init__(self, x=0.0, y=0.0):
self.x, self.y = x, y
#classmethod
def get_point1(cls, cor): # cor is list like [1,2] with x=1 and y=2
return Point(cor[0], cor[1])
#classmethod
def get_point2(cls, cor):
return cls(cor[0], cor[1])
class SubPoint(Point):
pass
sub1 = SubPoint.get_point1([0, 1])
sub2 = SubPoint.get_point2([2, 2])
print sub1.__class__
print sub2.__class__
<class '__main__.Point'>
<class '__main__.SubPoint'>
Is there any other difference? - well, if you need to do some logic inside your class method, which depends on class attributes, then yes it does.

How to Nested Classes in Python when trying to write a __call__ overwrite

So hopefully below illustrates my point. I want to set the translate attributes once and then be able to pass any mods (like translate) into the modLevels function. The only way I know how to do this is through nested classes, but I can't figure out how to get access to the outer class points. Any ideas or maybe even let me know if I'm going about this all wrong. THANKS!
class PointSet:
def __init__(self, points):
self.points = points
class translate:
def __init__(self, xmove=0, ymove=0):
self.xmove = xmove
self.ymove = ymove
def __call__(self):
for p in Outer.points: # <-- this part isnt working
p.x += self.xmove; p.y += self.ymove
def modLevels(levels, *mods):
for lev in range(levels):
for mod in mods:
mod
set1 = PointSet(...list of point objects here...)
coolMod = translate(xmove=5)
change(5, coolMod)
Pass it as a parameter.
class PointSet:
def __init__(self, points):
self.points = points
class translate:
def __init__(self, xmove=0, ymove=0, parent):
self.parent = parent
self.xmove = xmove
self.ymove = ymove
def __call__(self):
for p in self.parent.points:
p.x += self.xmove; p.y += self.ymove
Self-contained example:
class A:
def __init__(self):
self.data = [1,2,3]
class B:
def __init__(self, parent):
self.data = [4,5,6]
self.parent = parent
def access(self):
print(self.parent.data)
a = A()
b = a.B(a)
b.access()
However, as explained in comments, you don't need a nested class at all.
class PointSet:
def __init__(self, points):
self.points = points
def translate(self, x, y):
for p in self.points:
p.x += x
p.y += y
Thank you all for your help. I found a way to access the outer class on ubuntu forums. Solved referencing outer class from an inner class.
I needed to do this to pass a few parameters to the translation constructor and then overwrite the call function to use those parameters. This is a similar concept to a C++ function object like what you would pass to an STL algorithm: more on function objects.

How to use property for a class that are not derived from object

I have a django Model class (PS: Model class is a class which represents a database table in django structure. They all derived from Model class) class. Assume that I set its attributes as follows:
class SomeModel(SomeClass):
def __init__(self):
self.x = 23
self.y = 100
def z(self):
return self.x + self.y
In my situation, I do not want to handle z as a method and call is as SomeModel().z() but as an attribute and call it as SomeModel().z. Also that attribute should not be updated or changed. In that case I define it as a #property
class SomeModel(SomeClass):
def __init__(self):
self.x = 23
self.y = 100
#property
def z(self):
return self.x + self.y
#z.setter
def z(self, val):
raise NotImplementedError
Now, I can use SomeModel().z just as an attribute of that class. But since it was not derived from object, #z.setter fails to work and I can set value to z with
some = SomeModel()
some.z
>> 123
some.z = 567
some.z
>> 567
Is there a way to use #property for classes that are not derived from object? Or is there another solution which will allow me to handle my class methods as attributes. My basic need is just handle them as attributes, but it would be better if I can override set and delete methods too.
UPDATE: I realized Model class is derived from object and I can use #property as expected. So Related examples are not valid and I change them some. But my question is still valid since I also have some classes which are not derived from object.
If you want to use new class style in a subclass of an old class, one way to do it would be simply subclass Object as well.
class OldNonObjectClass:
a, b = 2, 3
#property
def c(self):
return self.b + self.a
class SubClass(OldNonObjectClass, object):
x, y = 4, 5
#property
def z(self):
return self.x + self.y
a = OldNonObjectClass()
print(a.c)
#5
a.c = 2
print(a.c)
#2
b = SubClass()
print(b.z)
#5
b.z = 2
# AttributeError: can't set attribute
You can use multiple inheritance to make it inherit from object too: class Subclass(ParentClass, object):
I never tried it for properties, but it makes super() work so I guess it answers your question.
If you don't want to use it, you could also implement __getattr__.

Categories