Controlling assignation

  • Thread starter =?ISO-8859-1?Q?Xavier_D=E9coret?=
  • Start date
?

=?ISO-8859-1?Q?Xavier_D=E9coret?=

I would like to know if there is for python's classes an equivalent of
the operator= that can be overidden.

Let's say I haveand I want this to change some internal value of a instead of making a
point to a new object (an int 5)

In other word, I would like to be able to use a=5 instead of a.set(5)

Is that possible?
 
P

Peter Hansen

Xavier said:
I would like to know if there is for python's classes an equivalent of
the operator= that can be overidden.

Let's say I have
and I want this to change some internal value of a instead of making a
point to a new object (an int 5)

In other word, I would like to be able to use a=5 instead of a.set(5)

Is that possible?

Not with simple names, such as "a". You can do it if you assign to an
attribute of an object, such as a.b, by intercepting the assignment call
via __setattr__ or a property.

In Python, anyone reading your code would expect that "a=5" represents a
rebinding of the name "a" to a new object, possibly destroying the old
object, and if you did manage to subvert that you'd just be making your
code unreadable, in the way that overuse of #define to change syntax in
C can make C code (even more) unreadable. Please reconsider why you
want to do that and find a more conventional approach, such as a.set(5).

-Peter
 
H

harold fellermann

I would like to know if there is for python's classes an equivalent of
the operator= that can be overidden.

Let's say I have
and I want this to change some internal value of a instead of making a
point to a new object (an int 5)

In other word, I would like to be able to use a=5 instead of a.set(5)

Is that possible?

the short answer is: no.

the long answer:

if you writean instance of class A is created and bound to the local identifier
'a'. If you later writethe object 5 is reassigned to the same identifier, deleting whatever
value was stored there before. The identifier itself does not impose
any restrictions on the type of instances that can be bound to it.
Binding an instance of class A in the first part, does not make the
identifier of the kind 'can-only-bind-A-instances'. In other words:
identifiers don't have types. Thus, there is no mechanism that allows
to change the binding behavior of identifiers.

As a general advise, don't try to write C++ in python. I think, for
most cases, there are far better solutions than changing the assign
operator anyway... explicit is better than implicit:

If class A has only one dedicate value and no internal state, make it a
construcotr call:
Otherwise, it is worth mentioning the name of the member to set.
IMHO this increases the readability of your source code:

Cheers,

- harold -
 
S

Steven D'Aprano

I would like to know if there is for python's classes an equivalent of
the operator= that can be overidden.

Let's say I have
and I want this to change some internal value of a instead of making a
point to a new object (an int 5)

In other word, I would like to be able to use a=5 instead of a.set(5)

Is that possible?

I don't know, because I don't understand what you mean.

What is A()? A class or a function? What is a.set()? What does it do?

I'm going to make a wild guess as to what you want to do. You want
something like Pascal records or C structs, right?

py> a = MyCustomShapeClass()
py> print a # calls a.__repr__ for a nice printable representation
[top = 0, bottom = 1, left = 5, right = 20, kind = "rect"]
py> a.kind = "oval"
py> a.bottom = 100
py> print a
[top = 0, bottom = 100, left = 5, right = 20, kind = "oval"]

Is that the sort of thing you are looking for?
 
E

egbert

In other word, I would like to be able to use a=5 instead of a.set(5)

If a(5) is acceptable to you in stead of a=5
you can make your instance callable with the __call__ method:


class A(object):
def __init__(self):
self.var=0
def __call__(self,val=None):
self.var=val

a = A()
a(5)
print a.var # gives 5

egbert
 
?

=?ISO-8859-1?Q?Xavier_D=E9coret?=

Xavier Décoret a écrit :
I would like to know if there is for python's classes an equivalent of
the operator= that can be overidden.

Let's say I have
and I want this to change some internal value of a instead of making a
point to a new object (an int 5)

In other word, I would like to be able to use a=5 instead of a.set(5)

Is that possible?

Thanks anybody for the answers. It confirms what I understood of Python.
What I wanted to do is something like this:

def change(x,v):
x = v

class A(object):
def __init__(self,v):
self.x = v

a = A(3)
print a.x # displays 3
change(a.x,4)
print a.x # still displays 3


It may seem weird, but I ensure there is a reason for doing this. In C++
(the language I am mot familiar with), I could define f to take a
pointer to member function of a class, a pointer and a value and achieve
what I want. In python, I cannot that way becauswe when change(a.x,4) is
executed, a.x is "replaced" by ist value (returned by __getattribute__).

Finally, here is how I hold the situation:


class Handle:
def __init__(self,v):
self.__v = v
def __call__(self):
x = self.__v
while callable(x): x=x()
return x
def set(self,v):
self.__v = v

class HandledProperty(object):
def __init__(self,name=""):
self.name = name
def __get__(self,o,t):
return o.__dict__[self]
def __set__(self,o,v):
o.__dict__[self] = Handle(v)

class A(object):
x = HandledProperty("x")
def __init__(self,v):
self.x = v

def change(x,v):
x.set(v)


a = A(3)
print a.x() # displays 3 (notice the () in the call)
change(a.x,4)
print a.x() # still displays 4
 
D

Dennis Lee Bieber

I would like to know if there is for python's classes an equivalent of
the operator= that can be overidden.
First problem: = is NOT an "operator", as such.
Let's say I have

Assuming A() is creating an instance of some class, the above
basically says: Create a class instance somewhere in memory (note: it
has no identifier at this time, just that the runtime knows where it is
created); Stick the identifier "a" onto that instance.
and I want to write

As before: Create an instance of an integer "5" somewhere in
memory (actually, the first 100 or so integers are pre-created); realize
there is an identifier "a" already in the system, find that identifier,
remove it from whatever it was attached to, and stick it to the new "5".

IOW: the identifier on the left doesn't take part in the
activities until /after/ the right hand side has been computed. The
identifier is then attached (like a 3M Post-It note) to the object that
resulted from the computation of the right hand side.

--
 
P

Peter Hansen

Xavier said:
What I wanted to do is something like this:

def change(x,v):
x = v

class A(object):
def __init__(self,v):
self.x = v

a = A(3)
print a.x # displays 3
change(a.x,4)
print a.x # still displays 3

How about this?

def change(x, v):
x.x = v

Then call it with

change(a, 4)

And print a.x will return 4 as you wish.
It may seem weird, but I ensure there is a reason for doing this. In C++
(the language I am mot familiar with), I could define f to take a
pointer to member function of a class, a pointer and a value and achieve
what I want.

In Python the closest match to this might be to pass the reference to
the object, plus the *name* of the attribute, as a string.

def change(obj, attr, v):
setattr(obj, attr, v)

This, of course, is now a useless function since that's what "setattr"
already does...

So:

a = A(3)
print a.x # displays 3
setattr(a, 'x', 4)
print a.x # displays 4

-Peter
 
T

Terry Reedy

if you write
an instance of class A is created and bound to the local identifier 'a'.

I think it perhaps better to think of the label 'a' being bound to the
object rather than vice versa. For one, a label can only be bound (stuck
to, like a stick note) to one object at a time while one object can have
many labels (and other references) stuck to it.
If you later write
the object 5 is reassigned to the same identifier,

Or one could say that the label 'a' is removed from the A() object and
reassigned to the 5 object. Since the 5 object may have numerous other
connections, and since those connections are unaffected by the new
connection to 'a', whereas the previous assignment of 'a' is broken, I
think it better to say that 'a' is being reassigned, not 5.
deleting whatever value was stored there before.

In memory-oriented languages, such as C, names refer to chunks of memory
where values are stored and deleted. Assigning a new value to a variable
puts a new value in that chunk of memory, necessarily overwriting the old.

In object-oriented Python, objects have values and possibly multiple
associations with names and slots. If, but only if, 'a' was the last
association of its last assigned-to object, then that object is eligible
for deletion.
In other words: identifiers don't have types.

This and the following I agree with.

Terry J. Reedy
 
H

harold fellermann

I think it perhaps better to think of the label 'a' being bound to the
object rather than vice versa. For one, a label can only be bound
(stuck
to, like a stick note) to one object at a time while one object can
have
many labels (and other references) stuck to it.


Or one could say that the label 'a' is removed from the A() object and
reassigned to the 5 object. Since the 5 object may have numerous other
connections, and since those connections are unaffected by the new
connection to 'a', whereas the previous assignment of 'a' is broken, I
think it better to say that 'a' is being reassigned, not 5.

yeah. I have never seen it this way, but you are right! Binding the
identifier/label to the object is a much better perspective. thanks for
the lesson :)

- harold -
 
B

Bruno Desthuilliers

Xavier Décoret a écrit :
(snip)
What I wanted to do is something like this:

def change(x,v):
x = v

class A(object):
def __init__(self,v):
self.x = v

a = A(3)
print a.x # displays 3
change(a.x,4)
print a.x # still displays 3


It may seem weird,

It does
but I ensure there is a reason for doing this.

I really wonder what it can be ???
In C++
(the language I am mot familiar with), I could define f to take a
pointer to member function of a class, a pointer and a value and achieve
what I want. In python, I cannot that way becauswe when change(a.x,4) is
executed, a.x is "replaced" by ist value (returned by __getattribute__).

Finally, here is how I hold the situation:


class Handle:
def __init__(self,v):
self.__v = v
def __call__(self):
x = self.__v
while callable(x): x=x()
return x
def set(self,v):
self.__v = v

class HandledProperty(object):
def __init__(self,name=""):
self.name = name
def __get__(self,o,t):
return o.__dict__[self]
def __set__(self,o,v):
o.__dict__[self] = Handle(v)

class A(object):
x = HandledProperty("x")
def __init__(self,v):
self.x = v

def change(x,v):
x.set(v)


a = A(3)
print a.x() # displays 3 (notice the () in the call)
change(a.x,4)
print a.x() # still displays 4

You could achieve the same effect with:

class A( object):
def __init__(self, value):
self.value = value

a = A(3)
a.value = 4
a.value
=> 4

And it's *much* more simple/readable/efficient.

Ever googled for "evolution of a programmer" ?-)
 
?

=?ISO-8859-1?Q?Xavier_D=E9coret?=

Bruno Desthuilliers a écrit :
Xavier Décoret a écrit :
(snip)



It does



I really wonder what it can be ???

It's the ability to develop the equivalent of GeoNext (and much more) in
Python with a very nice syntax.
You could achieve the same effect with:

class A( object):
def __init__(self, value):
self.value = value

a = A(3)
a.value = 4
a.value
=> 4

Of course, and even simpler ;-)
print "4"

More seriously, try to do this with your simpler approach.

a = A(4)
b = A(lambda : a.x+5)
a.x = 2

print b.x # I want this to be 7, not 9

And it's *much* more simple/readable/efficient.

Ever googled for "evolution of a programmer" ?-)
Not to brag, but I think I know what programming is. Google for my
name. C'est bien un commentaire de francais ca ;-)
 
T

Terry Reedy

More seriously, try to do this with your simpler approach.
a = A(4)
b = A(lambda : a.x+5)
a.x = 2
print b.x # I want this to be 7, not 9

As written, it will be neither, since b.x is a function. But if you call
it, its value *is* 7, not 9, as you specified wanting. So I don't
understand your point.
.... def __init__(self,val): self.x = val
....7

Terry J. Reedy
 
B

Bruno Desthuilliers

Xavier Décoret a écrit :
Bruno Desthuilliers a écrit :
(snip)

It's the ability to develop the equivalent of GeoNext (and much more) in
Python with a very nice syntax.

This is nice, but this does not explain the why of your code snippet.
Of course, and even simpler ;-)
print "4"

of course !-)
More seriously, try to do this with your simpler approach.

a = A(4)
b = A(lambda : a.x+5)
a.x = 2

print b.x # I want this to be 7, not 9

I may miss the point, but what about:

class A(object):
def __init__(self, x):
self.x = x

def _getx(self):
if callable(self._x):
return self._x()
else:
return self._x

def _setx(self, x):
self._x = x

x = property(_getx, _setx)

a = A(4)
b = A(lambda : a.x+5)
a.x = 2
print "b.x is", b.x

<have-fun with="lambdas">
#... and now for the fine part:
del a
b.x

But what, your solution behaves just the same.
Not to brag, but I think I know what programming is.

I don't have any reason to doubt it. But do you know what not
programming is ?-)
C'est bien un commentaire de francais ca ;-)

<gaston>Meuhnon</gaston>
 
B

Bengt Richter

<...OTT [OT Title] posted text snipped.../>
assignation != assignment ;-)

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,999
Latest member
MakersCBDGummiesReview

Latest Threads

Top