开发者

Idiomatic Python for generating a new object from within a class

开发者 https://www.devze.com 2023-02-10 16:36 出处:网络
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 sa

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, call开发者_开发技巧ing 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?


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.


You can use the builtin 'type'.

type(instance)

is that instance's class.

0

精彩评论

暂无评论...
验证码 换一张
取 消