Is It Safe to Replace a Self Object by Another Object of the Same Type in a Method

Is it safe to replace a self object by another object of the same type in a method?

It is unlikely that replacing the 'self' variable will accomplish whatever you're trying to do, that couldn't just be accomplished by storing the result of func(self) in a different variable. 'self' is effectively a local variable only defined for the duration of the method call, used to pass in the instance of the class which is being operated upon. Replacing self will not actually replace references to the original instance of the class held by other objects, nor will it create a lasting reference to the new instance which was assigned to it.

python - Can you replace an object completely by internal method?

self is just another variable. Method objects cause the current instance to be assigned to that name (just like other values are assigned to other function parameters), but like other names, assigning to them will only change what object the name refers to. Other names that reference the same object, like x, do not change along.

That's because names in Python code are just like tags, and self = <something else> is like taking the tag of the old instance and putting it on another object. Any other tags still attached to the old object are not moved! Because x still references the old instance, it is not going to see that you put the self tag on another object.

Either your update() method needs to return the new object (so that the caller can update their reference to point to the new object), or change the list in-place (at which point all references to the object will see the same change.

Returning the object means the caller is responsible for doing something with the return value:

class test(list):
def update(self):
return test(['a','b','c','d'])

x = test([1,2,3])
x = x.update() # re-bind `x` to point to the new object.
print(x)

Or you can assign to indices of the list itself; this changes what the contents of the list point to. You can use self just like any other reference, so x[0] = 5 would change index 0, so would self[0] = 5. And if you assign to a slice you can change multiple indices at once. The identity slice, [:], lets you change all indices at once, and you can assign more or fewer values to grow or shrink a list. Assigning to self[:] changes all indices, and lets you change all indices to point to any number of different values.

So:

class test(list):
def update(self):
self[:] = ['a', 'b', 'c', 'd']

x = test([1,2,3])
x.update()
print(x) # The x reference to the same list will see the change too

The above replaces all indices with the values in the other list. All references to the instance will see the change; both as self and x, and any other such references.

Demo of what this means:

>>> class test(list):
... def update(self):
... self[:] = ['a', 'b', 'c', 'd']
...
>>> x = test([1, 2, 3])
>>> y = x # another reference to the same object
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x.update() # update the list in-place
>>> x # visible here
['a', 'b', 'c', 'd']
>>> y # and here!
['a', 'b', 'c', 'd']

is it possible to overwrite self to point to another object inside self.method in python?

Assigning to self inside a method simply rebinds the local variable self to the new object. Generally, an assignment to a bare name never changes any objects, it just rebinds the name on the left-hand side to point to the object on the right-hand side.

So what you would need to do is modify the object self points to to match the object self.o points to. This is only possible if both A and Wrapper are new-style classes and none of them defines __slots__:

self.__class__ = self.o.__class__
self.__dict__ = self.o.__dict__

This will work in CPython, but I'm not sure about the other Python implementation. And even in CPython, it's a terrible idea to do this.

(Note that the is condition in the last line of your code will still be False, but I think this does what you intend.)

Can I replace an existing method of an object in Python?

Using some tips from:

Is it possible to change an instance's method implementation without changing all other instances of the same class?

you can do the following, by using the types module to assign a method to the object created without affecting the class. You need to do this because a function does not automatically receive the self object as the first variable, but a method does.

import types

joe = Person()
bob = Person()

joe.SayHi()
>>> Hello!

def greedy_has_good_mood(self):
return self.Cash > 100

joe.HasGoodMood = types.MethodType(greedy_has_good_mood, joe)

joe.SayHi()
>>> Hmpf.
bob.SayHi()

>>> Hello!

how to assign self to another instance of itself

A solution:

import copy
class TestClass:
def __init__(self, value):
if isinstance(value, TestClass):
self.__dict__ = copy.deepcopy(value.__dict__)
else:
self.data = value

This makes your example working. You want to do a 'copy constructor',
in Python objects have a __dict__ attribute containing all
members so you can just copy the dictionary from the original object
and assign it to the new object __dict__.

Replace Instance of an object in python

I think a class method probably makes the most sense, something like

class Dictionary:
def __init__(self, collection_size):
self.dictionary = [Term() for _ in range(collection_size)]
self.collection_size = collection_size

@classmethod
def load_from_pickle(cls, src):
with open(src, 'rb') as handle:
cls = pickle.load(handle)
return cls

loaded_dictionary = Dictionary.load_from_pickle('path/to/pickle')

You probably want some "guardrails" on the load method to make sure you're unpickling an object that works.

At some point, you may also want some kind of Dictionary.merge, but that seems independent of initializing from a pickled object.

How do I use one object from one function in another function in the same class

The point of local variables is that they only exist within the function, so you can't do this by definition.

Often, the answer is to pass the variable's value around. For example, browse_file could return img to its caller, and that caller could keep it around and then pass it into grey_scale later.

Another option is to use a class to hold state. These functions seems to be methods of a class already (based on the self parameter), so there's a good chance this is the right design here. Just replace every img in both functions with self.img, and now this isn't a local variable, it's a member of the instance. Every method called on the same instance will have access to the same value. But if you create multiple instances of the same class, each instance will have its own img.



Related Topics



Leave a reply



Submit