2021年9月3日 星期五

[ Python 常見問題 ] Why do Python classes inherit object?

 Source From Here

Question
Is there any reason for a class declaration to inherit from object? I just found some code that does this and I can't find a good reason why.
  1. class MyClass(object):  
  2.     # class code follows...  
Answer:
In Python 3, apart from compatibility between Python 2 and 3, no reason. In Python 2, many reasons.

Python 2.x story:
In Python 2.x (from 2.2 onwards) there's two styles of classes depending on the presence or absence of object as a base-class:

1. "classic" style classes: they don't have object as a base class:
  1. >>> class ClassicSpam:      # no base class  
  2. ...     pass  
  3. >>> ClassicSpam.__bases__  
  4. ()  
2. "new" style classes: they have, directly or indirectly (e.g inherit from a built-in type), object as a base class:
  1. >>> class NewSpam(object):           # directly inherit from object  
  2. ...    pass  
  3. >>> NewSpam.__bases__  
  4. (<type 'object'>,)  
  5. >>> class IntSpam(int):              # indirectly inherit from object...  
  6. ...    pass  
  7. >>> IntSpam.__bases__  
  8. (<type 'int'>,)   
  9. >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object    
  10. (<type 'object'>,)  
Without a doubt, when writing a class you'll always want to go for new-style classes. The perks of doing so are numerous, to list some of them:

Support for descriptors. Specifically, the following constructs are made possible with descriptors:
classmethod: A method that receives the class as an implicit argument instead of the instance.
staticmethod: A method that does not receive the implicit argument self as a first argument.
properties with property: Create functions for managing the getting, setting and deleting of an attribute.
more...

* The __new__ static method: lets you customize how new class instances are created.
Method resolution order (MRO): in what order the base classes of a class will be searched when trying to resolve which method to call.
* More

If you don't inherit from object, forget these. A more exhaustive description of the previous bullet points along with other perks of "new" style classes can be found here.

One of the downsides of new-style classes is that the class itself is more memory demanding. Unless you're creating many class objects, though, I doubt this would be an issue and it's a negative sinking in a sea of positives.

Python 3.x story:
In Python 3, things are simplified. Only new-style classes exist (referred to plainly as classes) so, the only difference in adding object is requiring you to type in 8 more characters. This:
  1. class ClassicSpam:  
  2.     pass  
is completely equivalent (apart from their name :-) to this:
  1. class NewSpam(object):  
  2.      pass  
and to this:
  1. class Spam():  
  2.     pass  
All have object in their __bases__.
  1. >>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]  
  2. [True, True, True]  
So, what should you do?
In Python 2: always inherit from object explicitly. Get the perks.

In Python 3: inherit from object if you are writing code that tries to be Python agnostic, that is, it needs to work both in Python 2 and in Python 3. Otherwise don't, it really makes no difference since Python inserts it for you behind the scenes.

沒有留言:

張貼留言

[ Python 常見問題 ] When using unittest.mock.patch, why is autospec not True by default?

  Source From  Here Question When you patch a function using  mock , you have the option to specify  autospec  as True: If you set  autospec...