Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using __class__ to create instances

Is it a good idea to use __class__ to create new instances within the class?

The following code is an example of doing this:

from collections import namedtuple

_Position = namedtuple('Position', ['x', 'y'])
class Position(_Position):
    def __add__(self, other):
        return __class__(self.x + other.x, self.y + other.y)

Using the actual class name sounds like duplicated code to me. If the name of the class changes I'd have to change it in all occurrences, even though modern IDE's can do that for you.

btw. What kind of variable is __class__? Shouldn't you only be able to access it with self.?

like image 801
Joschua Avatar asked Jan 01 '13 16:01

Joschua


People also ask

How do you make instances and classes?

To create instances of a class, you call the class using class name and pass in whatever arguments its __init__ method accepts.

What does __ class __ mean in Python?

__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .

Can you create multiple instances of a class?

One of the main characteristics of object oriented programming is the fact that you can create multiple instances of the same class. Each instance is created in a different place in the program memory and the values of instance attributes in one instance are independent from the values in other instances.

How do I create a new instance of a class in Python?

Use the class name to create a new instanceCall ClassName() to create a new instance of the class ClassName . To pass parameters to the class instance, the class must have an __init__() method. Pass the parameters in the constructor of the class.


1 Answers

To support the zero-argument form of super(), the compiler adds an implicit reference to the class if __class__ or super() are being used in a class method. See Creating the class object.

The example code you found (ab)uses this little factoid to create new instances of Position when adding.

Personally, I'd use type(self) instead, as that is the proper API method of determining the type or class of any object. type(self) will use self.__class__ where appropriate:

def __add__(self, other):
    return type(self)(self.x + other.x, self.y + other.y)

That is a good idea if you want to support subclassing. Any subclasses of Position will return the correct subclassed type when being added together. Using __class__ does not do that, as it will always be pointing to Position, even for subclasses:

>>> class Foo:
...     def method(self):
...         print(__class__)
...         print(type(self))
... 
>>> class Bar(Foo):
...     pass
... 
>>> Bar().method()
<class '__main__.Foo'>
<class '__main__.Bar'>

Of course, if that was your intention all along (to bypass subclasses), I'd still prefer using the explict class name over using __class__; explicit is better than implicit.

like image 133
Martijn Pieters Avatar answered Sep 22 '22 14:09

Martijn Pieters