Rename every method skipping the object name - python

Not sure if this is a valid question or just nonsense, but I have not found an answer online.
I know that it is possible to rename a function in Python this way:
SuperMethod = myObject.SuperMethod
I would like to know if it is possible to rename every method of an object, that's it, being able to call every method of a particular object without telling explicitly its name (similarly than in VBA by using with clause)
I know this will have all kind of naming issues.

You can update the globals() dict with the object's callables after filtering out the internal methods that start and end with '__':
class A:
def __init__(self, i):
self.i = i
def x(self):
print(self.i + 1)
def y(self):
print(self.i + 2)
myObject = A(1)
globals().update({k: getattr(myObject, k) for k, v in A.__dict__.items() if not k.startswith('__') and not k.endswith('__') and callable(v)})
x()
y()
This outputs:
2
3

Related

C-like Static Variable inside a Python class method

After 20 years of C++ experience I am struggling to learn something of Python.
Now I'd like to have a method (a function inside a class) that has a "static" variable of its own, and not a static class variable.
Probably a pseudo code example can illustrate better what I want.
class dummy:
#staticmethod
def foo():
foo.counter += 1
print "You have called me {} times.".format(foo.counter)
foo.counter = 0
NOTE 1: I used #staticmethod just for simplicity, but this is irrelevant.
NOTE 2: This crashes with AttributeError: 'staticmethod' object has no attribute 'counter' but as I said above, this is a pseudo code to clarify my objective.
I have already learned that this works outside a class:
def foo():
foo.counter += 1
print "You have called me {} times.".format(foo.counter)
foo.counter = 0
But the same trick doesn't seem to work for member-functions.
Last minute information, I am restricted to using Python 2.7 (not my choice).
Is there any legal and reliable way to have a persistent variable (or constant) with scope restricted to the member-function scope?
Some relevant links
"What is the Python equivalent of static variables inside a function?":
https://stackoverflow.com/a/279586/466339
"There are no function-level static variables in Python":
https://code-maven.com/slides/python-programming/static-variable
Thanks in advance.
One way to achieve this is to tuck your variable away in a closure, so it will effectively be static for your purposes. Unfortunately, Python 2 does not support the nonlocal keyword, so we have to wrap our variable's value in an object (unless you only mean to reference and not mutate the variable (i.e. assign to the variable) in the method:
In [7]: class _Nonlocal:
...: def __init__(self, value):
...: self.counter = value
...:
...: def foo_maker():
...: nonlocal = _Nonlocal(0)
...: def foo(self):
...: nonlocal.counter += 1
...: print "You have called me {} times.".format(nonlocal.counter)
...: return foo
...:
In [8]: class Dummy(object): #you should always inherit from object explicitely in python 2
...: foo = foo_maker()
...:
In [9]: dummy = Dummy()
In [10]: dummy.foo()
You have called me 1 times.
In [11]: dummy.foo()
You have called me 2 times.
Of course, this is a lot of rigamarole simply to avoid using an instance variable. Perhaps the best solution is to make your method a custom object, and you can implement the descriptor protocol to make it callable as a method, and it will be usable as an instance method if you'd like:
In [35]: import types
...:
...: class Foo(object):
...: def __init__(this):
...: this.counter = 0
...: def __call__(this, self):
...: this.counter += 1
...: print "You have called me {} times.".format(this.counter)
...: print "here is some instance state, self.bar: {}".format(self.bar)
...: def __get__(this, obj, objtype=None):
...: "Simulate func_descr_get() in Objects/funcobject.c"
...: if obj is None:
...: return this
...: return types.MethodType(this, obj)
...:
In [36]: class Dummy(object): #you should always inherit from object explicitely in python 2
...: foo = Foo()
...: def __init__(self):
...: self.bar = 42
...:
In [37]: dummy = Dummy()
In [38]: dummy.foo()
You have called me 1 times.
here is some instance state, self.bar: 42
In [39]: dummy.bar = 99
In [40]: dummy.foo()
You have called me 2 times.
here is some instance state, self.bar: 99
All of this would be highly irregular and confusing to someone else who is used to python conventions, although I hope you see, the Python data-model offers a lot of power to customize things.
note, i've used this as the name of the first argument to avoid confusion with self that will actually come from the object that Foo get's bound to as a method.
Again, I should reiterate, I would never do this. I would just use an instance variable, or perhaps a generator if your function needs to maintain state, and could be used as an iterator.
No, there is not. You've already found the Python version: a class variable that you, the supreme overlord of class dummy development, will access only within function foo.
If it would help to know the rationale for this, you can start that path here. I expect that you've already been through much of this; however, this answer gives Python specifics for more Pythonic ways to implement what you need.
As #Prune already mentioned there is no real way of doing so.
However, if you want the static variable inside a method to be available only to the object it belongs to (as it is in C++ as far as I remember), you should define it in the constructor or as a class variable with a non-static method:
from __future__ import print_function
class dummy:
def __init__(self, counter=0):
self._foo_counter = 0
def foo(self):
self._foo_counter += 1
print("You have called me {} times.".format(self._foo_counter))
or:
class dummy:
def foo(self):
self._foo_counter += 1
print("You have called me {} times.".format(self._foo_counter))
_foo_counter = 0
This way, running:
x = dummy()
for _ in range(4):
x.foo()
y = dummy()
for _ in range(4):
y.foo()
Results in:
You have called me 1 times.
You have called me 2 times.
You have called me 3 times.
You have called me 4 times.
You have called me 1 times.
You have called me 2 times.
You have called me 3 times.
You have called me 4 times.
Note that the two versions do not behave in exactly the same way.
When you define _foo_counter in the class directly, you will have access to the _foo_counter variable both for the object (self._foo_counter) and for the class itself (dummy._foo_counter).
The dummy._foo_counter will be static for every use of the class and will persist across multiple instances of the class, so across multiple objects.
This is also the only variable that you can access if you use the #staticmethod decorator on dummy.foo():
class dummy:
#staticmethod
def foo():
dummy._foo_counter += 1
print("You have called me {} times.".format(dummy._foo_counter))
_foo_counter = 0
Here, self or _foo_counter will not be accessible, and your only option is to use the class-wide variable dummy._foo_counter (which, as already mentioned, you could use with methods not decorated with #staticmethod as well).
So that running again:
x = dummy()
for _ in range(4):
x.foo()
y = dummy()
for _ in range(4):
y.foo()
results in:
You have called me 1 times.
You have called me 2 times.
You have called me 3 times.
You have called me 4 times.
You have called me 5 times.
You have called me 6 times.
You have called me 7 times.
You have called me 8 times.
Using a mutable type as the default value for a keyword argument for your function is maybe the simplest approach:
class Dummy:
#staticmethod
def foo(_counter=[0]): # here using a list, but you could use a dictionary, or a deque
_counter[0] += 1
print "You have called me {} times.".format(_counter[0])
The rationale is that this variable is initialized only once; its latest value remains in the closure formed.
I already posted this in an old post, but nobody noticed it
As I have a different idiomatic objective with static variables, I would like to expose the following:
In a function, I want to initialize a variable only once with a calculated value which may be a bit costly.
As I love nice-writing, and being an old C-style programmer. I tried to define a macro-like writing:
def Foo () :
StaticVar( Foo, ‘Var’, CalculateStatic())
StaticVar( Foo, ‘Step’, CalculateStep())
Foo.Var += Foo.Step
print(‘Value of Var : ‘, Foo.Var)
Then, I wrote ‘StaticVar’ like this:
def StaticVar(Cls, Var, StaticVal) :
if not hasattr(Cls, Var) :
setattr(Cls, Var, StaticVal)
I can even write nicer code in Python:
def StaticVars(Cls, **Vars) :
for Var, StaticVal in Vars.items() :
if not hasattr(Cls, Var) :
setattr(Cls, Var, StaticVal)
def Foo () :
StaticVars( Foo, Var = CalculateStatic(),Step= CalculateStep()))
Foo.Var += Foo. Step
print(‘Value of Var : ‘, Foo.Var)
Sure, this is a nice way to write the code, but my objective (only one call of initialization functions) is not met (just add a print in the initialization function to see that the it is called often) ! The fact is that, in a function call, the parameter value is evaluated even before the function is called.
def CalculateStatic() :
print("Costly Initialization")
return 0
def CalculateStep() :
return 2
def Test() :
Foo()
Foo()
Foo()
>>> Test()
Costly Initialization
Value of Var : 2
Costly Initialization
Value of Var : 4
Costly Initialization
Value of Var : 6
To meet my objective, I’d rather write something like this:
def Foo () :
if not hasattr(Foo, ‘Var’) :
setattr ( Foo, ‘Var’, CalculateStatic())
setattr ( Foo, ‘Step’, CalculateStep())
Foo.Var += Foo. Step
print(‘Value of Var : ‘, Foo.Var)
>>> Test()
Costly Initialization
Value of Var : 2
Value of Var : 4
Value of Var : 6
And it could be “nicely written” like this (I used the underscore notation refering to “private == static”):
def StaticVars(Cls, **Vars) :
for Var, StaticVal in Vars.items() :
setattr(Cls, Var, StaticVal)
def Foo () :
_ = Foo
try :
__ = _.Var
except AttributeError : # The above code could only generate AttributeError Exception
# the following code is executed only once
StaticDefVars(_, Var= CalculateStatic(), Step = CalculateStep())
_.Var += _. Step
print(‘Value of Var : ‘, Foo.Var)
Attention must be paid to not put 'calculation code' in the 'try' clause which could generate extra 'AttributeError' exception.
Sure, if Python had had 'Marcro preprocessing', it would be even nicer
"'

Assign method locals to class attributes

When debugging, I sometimes find it useful to access the values of local variables within a class method without necessarily invoking pdb.set_trace().
class Calculator:
# ...
def add_and_format(x, y):
sum = x + y
return '{:.2f}'.format(sum)
If I want to access sum following a call to add_and_format, I could edit the code to be self.sum = x + y and inspect it that way. In the case of many local variables, however, it would be simpler if I could use a #debug decorator around the method or some debug_function() class method to persist all locals variables as attributes. I guess I have in mind something basically equivalent to
def my_method(self, *args, **kwargs):
# ... method code
for k, v in locals().items():
setattr(self, k, v)
return result
I've seen this answer, which is a good partial solution but I'm unsure how to get it to work for this use case.

does #property update changed elements in an attribute or calculates it again?

I was wondering if using the #property in python to update an attribute overwrites it or simply updates it? As the speed is very different in the 2 cases.
And in case it gets overwritten, what alternative can I use? Example:
class sudoku:
def __init__(self,puzzle):
self.grid={(i,j):puzzle[i][j] for i in range(9) for j in range(9)}
self.elements
self.forbidden=set()
#property
def elements(self):
self.rows=[[self.grid[(i,j)] for j in range(9)] for i in range(9)]
self.columns=[[self.grid[(i,j)] for i in range(9)] for j in range(9)]
self.squares={(i,j): [self.grid[(3*i+k,3*j+l)] for k in range(3) for l in range(3)] for i in range(3) for j in range(3) }
self.stack=[self.grid]
self.empty={k for k in self.grid.keys() if self.grid[k]==0}
Basically, I work with the grid method, and whenever I need to update the other attributes I call elements. I prefer to call it manually tho. The question, however, is that if I change self.grid[(i,j)], does python calculate each attribute from scratch because self.grid was changed or does it only change the i-th row, j-th column etc?
Thank you
edit: added example code
As is, your question is totally unclear - but anyway, since you don't seem to understand what a property is and how it works...
class Obj(object):
def __init__(self, x, y):
self.x = x
#property
def x(self):
return self._x / 2
#x.setter
def x(self, value):
self._x = value * 2
Here we have a class with a get/set ("binding") property x, backed by a protected attribute _x.
The "#property" syntax here is mainly syntactic sugar, you could actually write this code as
class Obj(object):
def __init__(self, x, y):
self.x = x
self.y = y
def get_x(self):
return self._x / 2
def set_x(self, value):
self._x = value * 2
x = property(fget=get_x, fset=set_x)
The only difference with the previous version being that the get_x and set_x functions remain available as methods. Then if we have an obj instance:
obj = Obj(2, 4)
Then
x = obj.x
is just a shortcut for
x = obj.get_x()
and
obj.x = 42
is just a shortcut for
obj.set_x(42)
How this "shortcut" works is fully documented here, with a whole chapter dedicated to the property type.
As you can see there's nothing magical here, and once you get (no pun intended) the descriptor protocol and how the property class uses it, you can answer the question by yourself.
Note that properties will ALWAYS add some overhead (vs plain attributes or direct method call) since you have more indirections levels and method calls invoked, so it's best to only use them when it really makes sense.
EDIT: now you posted your code, I confirm that you don't understand Python's "properties" - not only the technical side of it but even the basic concept of a "computed attribute".
The point of computed attributes in general (the builtin property type being just one generic implementation of) is to have the interface of a plain attribute (something you can get the value if with value = obj.attrname and eventually set the value of with obj.attrname = somevalue) but actually invoking a getter (and eventually a setter) behind the hood.
Your elements "property" while technically implemented as a read-only property, is really a method that initializes half a dozen attributes of your class, doesn't return anything (well it implicitely returns None) and which return value is actually never used (of course). This is definitly not what computed attributes are for. This should NOT be a property, it should be a plain function (with some explicit name such as "setup_elements" or whatever makes sense here).
# nb1 : classes names should be CamelCased
# nb2 : in Python 2x, you want to inherit from 'object'
class Sudoku(object):
def __init__(self,puzzle):
self.grid={(i,j):puzzle[i][j] for i in range(9) for j in range(9)}
self.setup_elements()
self.forbidden=set()
def setup_elements(self):
self.rows=[[self.grid[(i,j)] for j in range(9)] for i in range(9)]
self.columns=[[self.grid[(i,j)] for i in range(9)] for j in range(9)]
self.squares={(i,j): [self.grid[(3*i+k,3*j+l)] for k in range(3) for l in range(3)] for i in range(3) for j in range(3) }
self.stack=[self.grid]
self.empty={k for k, v in self.grid.items() if v==0}
Now to answer your question:
if I change self.grid[(i,j)], does python calculate each attribute from scratch because self.grid was changed
self.grid is a plain attribute, so just rebinding self.grid[(i, j)] doesn't make "python" calculate anything else, of course. None of your object's other attributes will be impacted. Actually Python (the interpreter) has no mind-reading ability and will only do exactly what you asked for, nothing less, nothing more, period.
or does it only change the i-th row, j-th column
This :
obj = Sudoku(some_puzzle)
obj.grid[(1, 1)] = "WTF did you expect ?"
will NOT (I repeat: "NOT") do anything else than assigning the literal string "WTF did you expect ?" to obj.grid[(1, 1)]. None of the other attributes will be updated in any way.
Now if your question was: "if I change something to self.grid and call self.setup_elements() after, will Python recompute all attributes or only update self.rows[xxx] and self.columns[yyy]", then the answer is plain simple: Python will do exactly what you asked for: it will execute self.setup_elements(), line after line, statement after statement. Plain and simple. No magic here, and the only thing you'll get from making it a property instead of a plain method is that you won't have to type the () after to invoke the method.
So if what you expected from making this elements() method a property was to have some impossible magic happening behind the scene to detect that you actually only wanted to recompute impacted elements, then bad news, this is not going to happen, and you will have to explicitely tell the interpreter how to do so. Computed attributes might be part of the solution here, but not by any magic - you will have to write all the code needed to intercept assignments to any of those attributes and recompute what needs to be recomputed.
Beware, since all those attributes are mutable containers, just wrapping each of them into properties won't be enough - consider this:
class Foo(object):
def __init__(self):
self._bar = {"a":1, "b": 2}
#property
def bar(self):
print("getting self._bar")
return self._bar
#bar.setter
def bar(self, value):
print("setting self._bar to {}".format(value))
self._bar = value
>>> f = Foo()
>>> f.bar
getting self._bar
{'a': 1, 'b': 2}
>>> f.bar['z'] = "WTF ?"
getting self._bar
>>> f.bar
getting self._bar
{'a': 1, 'b': 2, 'z': 'WTF ?'}
>>> bar = f.bar
getting self._bar
>>> bar
{'a': 1, 'b': 2, 'z': 'WTF ?'}
>>> bar["a"] = 99
>>> f.bar
getting self._bar
{'a': 99, 'b': 2, 'z': 'WTF ?'}
As you can see, we could mutate self._bar without the bar.setter function ever being invoked - because f.bar["x"] = "y" is actually NOT assigning to f.bar (which would need f.bar = "something else") but _getting_ thef._bardict thru theFoo.bargetter, then invokingsetitem()` on this dict.
So if you want to intercept something like f.bar["x"] = "y", you will also have to write some dict-like object that will intercept all mutators access on the dict itself ( __setitem__, but also __delitem__ etc) and notify f of those changes, and change your property so that it returns an instance of this dict-like objects instead.

Python equivalent of C++ member pointer

What would be the equivalent of a C++ member pointer in Python? Basically, I would like to be able to replicate similar behavior in Python:
// Pointer to a member of MyClass
int (MyClass::*ptMember)(int) = &MyClass::member;
// Call member on some instance, e.g. inside a function to
// which the member pointer was passed
instance.*ptMember(3)
Follow up question, what if the member is a property instead of a method? Is it possible to store/pass a "pointer" to a property without specifying the instance?
One way would obviously be to pass a string and use eval. But is there a cleaner way?
EDIT: There are now several really good answers, each having something useful to offer depending on the context. I ended up using what is described in my answer, but I think that other answers will be very helpful for whoever comes here based on the topic of the question. So, I am not accepting any single one for now.
Assuming a Python class:
class MyClass:
def __init__(self):
self.x = 42
def fn(self):
return self.x
The equivalent of a C++ pointer-to-memberfunction is then this:
fn = MyClass.fn
You can take a method from a class (MyClass.fn above) and it becomes a plain function! The only difference between function and method is that the first parameter is customarily called self! So you can call this using an instance like in C++:
o = MyClass()
print(fn(o)) # prints 42
However, an often more interesting thing is the fact that you can also take the "address" of a bound member function, which doesn't work in C++:
o = MyClass()
bfn = o.fn
print(bfn()) # prints 42, too
Concerning the follow-up with the properties, there are plenty answers here already that address this issue, provided it still is one.
The closest fit would probably be operator.attrgetter:
from operator import attrgetter
foo_member = attrgetter('foo')
bar_member = attrgetter('bar')
baz_member = attrgetter('baz')
class Example(object):
def __init__(self):
self.foo = 1
#property
def bar(self):
return 2
def baz(self):
return 3
example_object = Example()
print foo_member(example_object) # prints 1
print bar_member(example_object) # prints 2
print baz_member(example_object)() # prints 3
attrgetter goes through the exact same mechanism normal dotted access goes through, so it works for anything at all you'd access with a dot. Instance fields, methods, module members, dynamically computed attributes, whatever. It doesn't matter what the type of the object is, either; for example, attrgetter('count') can retrieve the count attribute of a list, tuple, string, or anything else with a count attribute.
For certain types of attribute, there may be more specific member-pointer-like things. For example, for instance methods, you can retrieve the unbound method:
unbound_baz_method = Example.baz
print unbound_baz_method(example_object) # prints 3
This is either the specific function that implements the method, or a very thin wrapper around the function, depending on your Python version. It's type-specific; list.count won't work for tuples, and tuple.count won't work for lists.
For properties, you can retrieve the property object's fget, fset, and fdel, which are the functions that implement getting, retrieving, and deleting the attribute the property manages:
example_bar_member = Example.bar.fget
print example_bar_member(example_object) # prints 2
We didn't implement a setter or deleter for this property, so the fset and fdel are None. These are also type-specific; for example, if example_bar_member handled lists correctly, example_bar_member([]) would raise an AttributeError rather than returning 2, since lists don't have a bar attribute.
I was not satisfied with the string approach and did some testing. This seems to work pretty well and avoids passing strings around:
import types
# Our test class
class Class:
def __init__(self, val):
self._val = val
def method(self):
return self._val
#property
def prop(self):
return self._val
# Get the member pointer equivalents
m = Class.method
p = Class.prop
# Create an instance
c1 = Class(1)
# Bind the method and property getter to the instance
m1 = types.MethodType(m, c1)
p1 = types.MethodType(p.fget, c1)
# Use
m1() # Returns 1
p1() # Returns 1
# Alternatively, the instance can be passed to the function as self
m(c1) # Returns 1
p.fget(c1) # Returns 1
I'm not a C++ programmer, so maybe I'm missing some detail of method pointers here, but it sounds like you just want a reference to a function that's defined inside a class. (These were of type instancemethod in Python 2, but are just type function in Python 3.)
The syntax will be slightly different --- instead of calling it like a method with object.reference(args), you'll call it like a function: reference(object, args). object will be the argument to the self parameter --- pretty much what the compiler would have done for you.
Despite the more C-like syntax, I think it still does what you wanted... at least when applied to a callable member like in your example. It won't help with a non-callable instance field, though: they don't exist until after __init__ runs.
Here's a demonstration:
#!/usr/bin/env python3
import math
class Vector(object):
def __init__(self, x, y):
self.x = x
self.y = y
return
def __str__(self):
return '(' + str(self.x) + ', ' + str(self.y) + ')'
def __repr__(self):
return self.__class__.__name__ + str(self)
def magnitude(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
def print_dict_getter_demo():
print('Demo of member references on a Python dict:')
dict_getter = dict.get
d = {'a': 1, 'b': 2, 'c': 3, 'z': 26}
print('Dictionary d : ' + str(d))
print("d.get('a') : " + str(d.get('a')))
print("Ref to get 'a' : " + str(dict_getter(d, 'a')))
print("Ref to get 'BOGUS': " + str(dict_getter(d, 'BOGUS')))
print('Ref to get default: ' + str(dict_getter(d, 'BOGUS', 'not None')))
return
def print_vector_magnitude_demo():
print('Demo of member references on a user-defined Vector:')
vector_magnitude = Vector.magnitude
v = Vector(3, 4)
print('Vector v : ' + str(v))
print('v.magnitude() : ' + str(v.magnitude()))
print('Ref to magnitude: ' + str(vector_magnitude(v)))
return
def print_vector_sorting_demo():
print('Demo of sorting Vectors using a member reference:')
vector_magnitude = Vector.magnitude
v0 = Vector(0, 0)
v1 = Vector(1, 1)
v5 = Vector(-3, -4)
v20 = Vector(-12, 16)
vector_list = [v20, v0, v5, v1]
print('Unsorted: ' + str(vector_list))
sorted_vector_list = sorted(vector_list, key=vector_magnitude)
print('Sorted: ' + str(sorted_vector_list))
return
def main():
print_dict_getter_demo()
print()
print_vector_magnitude_demo()
print()
print_vector_sorting_demo()
return
if '__main__' == __name__:
main()
When run with Python 3, this produces:
Demo of member references on a Python dict:
Dictionary d : {'a': 1, 'c': 3, 'b': 2, 'z': 26}
d.get('a') : 1
Ref to get 'a' : 1
Ref to get 'BOGUS': None
Ref to get default: not None
Demo of member references on a user-defined Vector:
Vector v : (3, 4)
v.magnitude() : 5.0
Ref to magnitude: 5.0
Demo of sorting Vectors using a member reference:
Unsorted: [Vector(-12, 16), Vector(0, 0), Vector(-3, -4), Vector(1, 1)]
Sorted: [Vector(0, 0), Vector(1, 1), Vector(-3, -4), Vector(-12, 16)]
As you can see, it works with both builtins and user-defined classes.
Edit:
The huge demo above was based on an assumption: that you had a reference to the class, and that your goal was to "hold on to" to one of the class's methods for use on whatever instances of that class showed up sometime later.
If you already have a reference to the instance, it's much simpler:
d = {'a': 1, 'b': 2, 'c': 3, 'z': 26}
d_getter = d.get
d_getter('z') # returns 26
This is basically the same thing as above, only after the transformation from a function into a method has "locked in" the argument to self, so you don't need to supply it.
The way I would approach this in python is to use __getattribute__. If you have the name of an attribute, which would be the analog of the c++ pointer-to-member, you could call a.__getattribute__(x) to get the attribute whose name is stored in x. It's strings and dicts instead of offsets & pointers, but that's python.

Python assignment to self in constructor does not make object the same

I am making a constructor in Python. When called with an existing object as its input, it should set the "new" object to that same object. Here is a 10 line demonstration:
class A:
def __init__(self, value):
if isinstance(value, A):
self = value
else:
self.attribute = value
a = A(1)
b = A(a)#a and b should be references to the same object
print("b is a", b is a)#this should be true: the identities should be the same
print("b == a", b == a)#this should be true: the values should be the same
I want the object A(a) constructed from the existing object a to be a. Why is it not? To be clear, I want A(a) to reference the same object as a, NOT a copy.
self, like any other argument, is among the local variables of a function or method. Assignment to the bare name of a local variable never affects anything outside of that function or method, it just locally rebinds that name.
As a comment rightly suggests, it's unclear why you wouldn't just do
b = a
Assuming you have a sound reason, what you need to override is not __init__, but rather __new__ (then take some precaution in __init__ to avoid double initialization). It's not an obvious course so I'll wait for you to explain what exactly you're trying to accomplish.
Added: having clarified the need I agree with the OP that a factory function (ideally, I suggest, as a class method) is better -- and clearer than __new__, which would work (it is a class method after all) but in a less-sharply-clear way.
So, I would code as follows:
class A(object):
#classmethod
def make(cls, value):
if isinstance(value, cls): return value
return cls(value)
def __init__(self, value):
self.attribute = value
Now,
a = A.make(1)
b = A.make(a)
accomplishes the OP's desires, polymorphically over the type of argument passed to A.make.
The only way to make it work exactly as you have it is to implement __new__, the constructor, rather than __init__, the initialiser (the behaviour can get rather complex if both are implemented). It would also be wise to implement __eq__ for equality comparison, although this will fall back to identity comparison. For example:
>>> class A(object):
def __new__(cls, value):
if isinstance(value, cls):
return value
inst = super(A, cls).__new__(cls)
inst.attribute = value
return inst
def __eq__(self, other):
return self.attribute == other.attribute
>>> a = A(1)
>>> b = A(a)
>>> a is b
True
>>> a == b
True
>>> a == A(1)
True # also equal to other instance with same attribute value
You should have a look at the data model documentation, which explains the various "magic methods" available and what they do. See e.g. __new__.
__init__ is an initializer, not a constructor. You would have to mess around with __new__ to do what you want, and it's probably not a good idea to go there.
Try
a = b = A(1)
instead.
If you call a constructor, it's going to create a new object. The simplest thing is to do what hacatu suggested and simply assign b to a's value. If not, perhaps you could have an if statement checking if the value passed in is equal to the object you want referenced and if it is, simply return that item before ever calling the constructor. I haven't tested so I'm not sure if it'd work.

Categories

Resources