Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic Python for generating a new object from within a class

Tags:

python

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?

like image 264
TR. Avatar asked Feb 14 '11 19:02

TR.


People also ask

How are objects created from a class in Python?

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.

Which method gets called when you create an object Python?

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.

When a new instance of a class is created which method gets called in Python?

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.

Which method is called when an object is created from a class and allows the class to initialize the attributes of the class?

__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.


1 Answers

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.

like image 70
gotgenes Avatar answered Sep 25 '22 06:09

gotgenes