How do I return a new instance of the python class itself dynamically inside it?

Asked

Viewed 1,117 times

4

I’m giving a study in Python and for this I am building a class in Python that I had already done in PHP.

For example, in a given method in PHP I needed to return the same instance of the class, dynamically, but without using the $this (which refers to the current instance of the object), because I want to apply the immutability in this case.

Example:

class Time {

        public function diff(Time $time) {
              $seconds = abs($time->getSeconds() - $this->getSeconds());

              return new static(0, 0, $seconds);
        }
}

That is, that a given method returns the instance of the class itself, but not the same instance, but a new one.

In python I have this currently:

class Time(object):

    __seconds = 0

    def __init__(self, **kw):

        self.set_time(**kw)

    def set_time(self, **kw):

        seconds = (kw.get('hours', 0) * 3600) \
        + (kw.get('minutes', 0) * 60) \
        + kw.get('seconds', 0)

        self.__seconds = seconds

        return self

   def diff(self, other):
      seconds = abs(self.get_seconds() - other.get_seconds())

      #como posso fazer para retornar uma nova instância com 'seconds' aqui?

2 answers

3

I ended up figuring out how to solve this problem.

Just use the special attribute __class__ of the current class, which can create a new instance.

Example:

 class Time(object):

     def diff(self, other):

        seconds = abs(self.get_seconds() - other.get_seconds());

        return self.__class__(seconds=seconds)

So if I inherit, in some object, the class Time, it will not be necessary to recreate the method diff, because the same already get the name of the class dynamically through __class__

class NewTime(Time):
    pass

a = NewTime(seconds=5)

b = NewTime(seconds=2)

c = a.diff(b)

print (c.__class__) #<class '__main__.NewTime'>
  • yes - self.__class__ or type(self) - the two do the same thing. In Python 3, you can also use the magic variable __class__ within a method (without the self ) : __class__ Only will always point to the class itself in which the method is defined - even if self is an instance of a sub-class of the same. That __class__ magic (why it appears out of nowhere) is part of the mechanism used in Python 3 so that super work without parameters.

  • Just one question @jsbueno: If I use __future__, can do this in Python 2 without the self?

  • No -this feature was not ported retroactively to Python2. But so far, why are you using Python2 in 2016 anyway? (Until 2015 I would understand).

  • @jsbueno seriously? now we can go to the Python 3? Is that in my Ubuntu, by default is installed the 2.7

  • It’s been years on Ubuntu - many years - that you can have Python2 and 3 parallels - just instill with apt-get install python3. Ai, for each project, you install the separadametne requirements using virtualenv and Pip (do not use system packages) <- this practice is also recommended for proejtos in Python2.

  • The question is more or less subjective, love until 2014, many of Python’s most important libraries and frameorks did not work in Python3 yet -or did not work properly. Today, silverily no important project that is basis for development (other than app for end user) is stuck only on Python2

Show 1 more comment

0

If I understand the problem, just return a new instance of the class itself. I changed some things in your class to run and show the result:

class Time(object):
    def __init__(self, **kw):
        self.__seconds = 0 
        self.set_time(**kw)

    def set_time(self, **kw):
        seconds = (kw.get('hours', 0) * 3600) \
        + (kw.get('minutes', 0) * 60) \
        + kw.get('seconds', 0)
        self.__seconds = seconds
        return self

    def diff(self, other):
        seconds = abs(self.get_seconds() - other.get_seconds())
        return Time(**{'seconds':seconds})

    def get_seconds(self):
        return self.__seconds

x = {'hours':1, 'minutes':2, 'seconds':1}
t = Time(**x)
print t.get_seconds()

x2 = {'hours':1, 'minutes':0, 'seconds':0}
t2 = Time(**x2)
print t2.get_seconds()

t3 = t.diff(t2)
print t3.get_seconds()

Exit:

3721
3600
121
  • 1

    Okay, but suppose I just inherited the class Time. I’d have to change the method diff every time I had an inheritance?

  • No.. the diff method is from the Time class and will always return a new instance of itself. If you want the method to return something else, it needs to be reimplemented in the class that is bequeathed

  • 1

    Wrong, there’s another way to do this in Python

  • So I don’t understand the problem or I don’t know this other way. I’ll follow this topic to see if anyone knows. Sorry I couldn’t help.

  • The way you did it beforehand, but actually I’m saying that the problem is generated when you inherit this class. It will keep coming back Time, then I would have to rewrite the method. The way I did in the new answer, resolves

  • The way Wallace himself does it works - the new instance created is subclass. You can either user self.__class__() as type(self)()

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.