I have a method on one of my objects that returns a new instance of that same class. I'm trying to figure out the most idiomatic way to write this method such that it generates a new object of the same type without duplicating code.
Since this method uses data from the instance, my first pass is:
class Foo(object):
def get_new(self):
data = # Do interesting things
return Foo(data)
However, if I subclass Foo and don't override get_new, calling get_new on SubFoo would return a Foo! So, I could write a classmethod:
class Foo(object):
@classmethod
def get_new(cls, obj):
data = # Munge about in objects internals
return cls(data)
However, the data I'm accessing is specific to the object, so it seems to break encapsulation for this not to be a "normal" (undecorated) method. Additionally, you then have to call it like SubFoo.get_new(sub_foo_inst)
, which seems redundant. I'd like the object to just "know" which type to return -- the same type as itself!
I suppose it's also possible to add a factory method to the class, and override the return type everywhere, without duplicating the logic, but that seems to put a lot of work on the subclasses.
So, my question is, what's the best way to write a method that gives flexibility in type of class without having to annotate the type all over the place?
A class is a user-defined blueprint or prototype from which objects are created. Classes provide a means of bundling data and functionality together. Creating a new class creates a new type of object, allowing new instances of that type to be made.
Introduction to the Python __init__() method. When you create a new object of a class, Python automatically calls the __init__() method to initialize the object's attributes. Unlike regular methods, the __init__() method has two underscores (__) on each side. Therefore, the __init__() is often called dunder init.
Constructors in Python Of one particular interest is the __init__() function. This special function gets called whenever a new object of that class is instantiated.
__init__ method This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.
If you want to make it more flexible for subclassing, you can simply use the self.__class__
special attribute:
class Foo(object):
def __init__(self, data):
self.data = data
def get_new(self):
data = # Do interesting things
return self.__class__(data)
Note that using the @classmethod
approach will prevent you from accessing data within any one instance, removing it as a viable solution in instances where #Do interesting things
relies on data stored within an instance.
For Python 2, I do not recommend using type(self)
, as this will return an inappropriate value for classic classes (i.e., those not subclassed from the base object
):
>>> class Foo:
... pass
...
>>> f = Foo()
>>> type(f)
<type 'instance'>
>>> f.__class__ # Note that the __class__ attribute still works
<class '__main__.Foo'>
For Python 3, this is not as much of an issue, as all classes are derived from object
, however, I believe self.__class__
is considered the more Pythonic idiom.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With