简体   繁体   中英

python class inheritance for parameters

I am trying to create a schedule class in python that takes the start time, end time, and location of a meeting. So far I have:

class Schedule(Time):
def __init__(self, start_time, end_time, location):
    self.start_time = start_time
    self.end_time = end_time
    self.location = location
    print (self.start_time)
    print (self.end_time)
    print (self.location)

I have a Time class completed which looks like this:

class Time():
    def __init__(self, init_hr = 12, init_min = 0, init_ampm = "AM"):
        self.hr = init_hr
        self.min = init_min
        self.ampm = init_ampm

Now I want to be able to make the parameters start_time and end_time (from the initialization of schedule) to be Time instances, however I'm confused on how I would go about doing that. Any suggestions?

You probably don't want Schedule to be a subclass of Time; the relationship between the two is most likely "has a" rather than "is a". Just make it a subclass of object and you should be fine.

You don't really need to change anything in your code.

However, you can:

  • Document it to make it clear the expected type of the parameters (I recommend sphinx for that).
  • Write assertions to make sure the type passed matches your expectations ( assert isinstance(variable, type) ). You can even use some more advance libraries for that like pycontracts .
  • Write unittests also to make sure that the whole API works as expected, that is, only the expected types are accepted ( unittest library works great, but you may want to take a look at alternative runners like nose or pytest ).

Regarding Schedule being a subclass of Time , I agree with the other answers.

Some dynamically-typed languages would want you to do this everywhere (statically-typed languages will generally enforce it themselves), but in Python the generally recommended practice is duck typing , which suggests that you just expect it to be a Time, but if it's something else, don't worry (if it implements the same interface as Time, well and good, if it doesn't, let it fail when you try accessing attributes that don't exist on the object). The general idea there is that you are expected to be intelligent enough to know what you're doing.

If a I were writing this code, I would leave it as you have it, with a few notes:

  • As others have mentioned, change class Schedule(Time) to class Schedule(object) .
  • In Time.__init__ , don't call your parameters init_hr , etc., just call them hr , etc. Python ain't Java, where you've got to use different names or always refer to the class version as this.* . In Python, you always use self.* . Python also has keyword arguments - so you could have Time(hr=4, ...) ; Time(init_hr=4, ...) would be ugly.
  • If you're in Python 2, change print (...) to print ... . If you're in Python 3, change it to print(...) .

Would you say that "a schedule is a time" ? I wouldn't. This implies that they don't inherit in this way. I'd say that a schedule is a collection of times, which means that your schedule class will have an attribute which is a listing of times.

Since in Python, type cannot be checked at compile time you need to write something like this on __init__ of Schedule

if not isinstance(start_time, Time):
     raise ValueError("Start time need to be of type time")

or

assert isinstance(start_time, Time)

Similarly for end_time also

Generally best practice in Python is to treat it as if it is a Time object and simply test whether it has the properties that you want rather than using isinstance . That way someone (including you) could create your own Time -like object in the future with the appropriate attributes ( hr , min , ampm ) and use it as a drop-in replacement. This would even work–if you aren't doing substantive logic with the Time objects or interact with that logic using operators–with their own custom objects that don't use the same fields. That would have a few good advantages, depending on exactly how your schedule objects work.

This style of coding is known as " Easier to ask for forgiveness than permission " and is relatively common in python, thanks to widespread use of duck typing .

A somewhat better pattern than using isinstance that still lets you check whether it conforms to a standard (if you want to do that) might be to use hasattr instead. For example:

hasattr(start_time, 'ampm')

I'll also agree with the others that a Schedule doesn't seem to have a is a relationship with Time but rather a has a relationship, else you could end up with someone creating a schedule with a Schedule as the start time and a Schedule as the end time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM