Python how to deal with A (a) when type (a) still has A

I need to create a class that mimics this behavior (in math, let's say list, dict, "idempotent"):

>>> list(list([3,4])) [3, 4] >>> dict({'a':1,'b':2}) {'a':1,'b':2} 

So, if A is my class, I want to write

 >>> a = A(1) >>> b = A(a) >>> b == a True 

I assume that my class A should look like this:

 class A(object): def __init__(self,x): if isinstance(x, A) : self = x else : self.x = x self.y = 'hello' 

I try this

 >>> A(1).x 1 >>> A(A(1)).x Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'A' object has no attribute 'x' 

This does not work!

I don’t want to copy x attributes to myself, I just want me to be BE x or “point” x

Some idea? Thanks

+4
source share
1 answer

What you are looking for is the __new__() method, which is executed, executed before , the class is built, and not the __init__() , which takes place after. With __new__() you can connect and replace the created object.

 def __new__(cls, x): if isinstance(x, A): return x else: return object.__new__(cls, x) 

You cannot do this in __init__() since the object has already been created. Changing self just changes the value of a local variable; it does not affect the object.

It's also worth noting that type checking is almost always what you need to do in Python. Instead, check if the class has the information / attributes that you need. That way, someone can create a class that acts like yours and works with your code.

As a final word of warning, this is a rather confusing behavior - people don’t expect your class to act like that, and that’s not a great idea at all. Your example list() and dict() not accurate in what you are doing here, since list(some_list) does not give some_list , it gives a new list, which is a copy of some_list - the same is true for dict() :

 >>> x = [1, 2, 3] >>> list(x) is x False 

When you call the constructor, it is natural to expect a new object, not a reference to an existing one. I would recommend making A(some_a) copy some_a and rebuild your calling code so as not to rely on A(some_a) is some_a ).

+11
source

Source: https://habr.com/ru/post/1446477/


All Articles