I am confused on what the folowing means:
class class_name(object):
What does the class takes in between the parenthesis? is it inheritance?
It's the superclass. There can be more than one, though getting that right and making it useful can be a bit tricky. There can also be none, but unless you're on Python 3, that's a bad idea.
Basically it is inheritance. You might find this thread and some of the related links useful: Python class inherits object.
Yes. It's inheritance. This is what it looks like:
class DerivedClass(BaseClass)
In your declaration, you're basically inheriting the object type. It's a built-in. However, in Python 3 you don't need to do this, as every class is implicitly a subclass of object.
By the way, more about this here.
class class_name(object):
This is called inheritance
Python also supports multiple inheritance , that means you can inherit from multiple classes
for example:
class class_name(BaseClassName1,BaseClassName2,BaseClassName3):
Related
Why does the following class declaration inherit from object?
class MyClass(object):
...
Is there any reason for a class declaration to inherit from object?
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:
"classic" style classes: they don't have object as a base class:
>>> class ClassicSpam: # no base class
... pass
>>> ClassicSpam.__bases__
()
"new" style classes: they have, directly or indirectly (e.g inherit from a built-in type), object as a base class:
>>> class NewSpam(object): # directly inherit from object
... pass
>>> NewSpam.__bases__
(<type 'object'>,)
>>> class IntSpam(int): # indirectly inherit from object...
... pass
>>> IntSpam.__bases__
(<type 'int'>,)
>>> IntSpam.__bases__[0].__bases__ # ... because int inherits from object
(<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.
__slots__: Saves memory consumptions of a class and also results in faster attribute access. Of course, it does impose limitations.
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.
Related to MRO, super calls. Also see, super() considered super.
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:
class ClassicSpam:
pass
is completely equivalent (apart from their name :-) to this:
class NewSpam(object):
pass
and to this:
class Spam():
pass
All have object in their __bases__.
>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[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 3
class MyClass(object): = New-style class
class MyClass: = New-style class (implicitly inherits from object)
Python 2
class MyClass(object): = New-style class
class MyClass: = OLD-STYLE CLASS
Explanation:
When defining base classes in Python 3.x, you’re allowed to drop the object from the definition. However, this can open the door for a seriously hard to track problem…
Python introduced new-style classes back in Python 2.2, and by now old-style classes are really quite old. Discussion of old-style classes is buried in the 2.x docs, and non-existent in the 3.x docs.
The problem is, the syntax for old-style classes in Python 2.x is the same as the alternative syntax for new-style classes in Python 3.x. Python 2.x is still very widely used (e.g. GAE, Web2Py), and any code (or coder) unwittingly bringing 3.x-style class definitions into 2.x code is going to end up with some seriously outdated base objects. And because old-style classes aren’t on anyone’s radar, they likely won’t know what hit them.
So just spell it out the long way and save some 2.x developer the tears.
Yes, this is a 'new style' object. It was a feature introduced in python2.2.
New style objects have a different object model to classic objects, and some things won't work properly with old style objects, for instance, super(), #property and descriptors. See this article for a good description of what a new style class is.
SO link for a description of the differences: What is the difference between old style and new style classes in Python?
History from Learn Python the Hard Way:
Python's original rendition of a class was broken in many serious
ways. By the time this fault was recognized it was already too late,
and they had to support it. In order to fix the problem, they needed
some "new class" style so that the "old classes" would keep working
but you can use the new more correct version.
They decided that they would use a word "object", lowercased, to be
the "class" that you inherit from to make a class. It is confusing,
but a class inherits from the class named "object" to make a class but
it's not an object really its a class, but don't forget to inherit
from object.
Also just to let you know what the difference between new-style classes and old-style classes is, it's that new-style classes always inherit from object class or from another class that inherited from object:
class NewStyle(object):
pass
Another example is:
class AnotherExampleOfNewStyle(NewStyle):
pass
While an old-style base class looks like this:
class OldStyle():
pass
And an old-style child class looks like this:
class OldStyleSubclass(OldStyle):
pass
You can see that an Old Style base class doesn't inherit from any other class, however, Old Style classes can, of course, inherit from one another. Inheriting from object guarantees that certain functionality is available in every Python class. New style classes were introduced in Python 2.2
Yes, it's historical. Without it, it creates an old-style class.
If you use type() on an old-style object, you just get "instance". On a new-style object you get its class.
The syntax of the class creation statement:
class <ClassName>(superclass):
#code follows
In the absence of any other superclasses that you specifically want to inherit from, the superclass should always be object, which is the root of all classes in Python.
object is technically the root of "new-style" classes in Python. But the new-style classes today are as good as being the only style of classes.
But, if you don't explicitly use the word object when creating classes, then as others mentioned, Python 3.x implicitly inherits from the object superclass. But I guess explicit is always better than implicit (hell)
Reference
I wrote a metaclass that automatically registers its classes in a dict at runtime. In order for it to work properly, it must be able to ignore abstract classes.
The code works really well in Python 2, but I've run into a wall trying to make it compatible with Python 3.
Here's what the code looks like currently:
def AutoRegister(registry, base_type=ABCMeta):
class _metaclass(base_type):
def __init__(self, what, bases=None, attrs=None):
super(_metaclass, self).__init__(what, bases, attrs)
# Do not register abstract classes.
# Note that we do not use `inspect.isabstract` here, as
# that only detects classes with unimplemented abstract
# methods - which is a valid approach, but not what we
# want here.
# :see: http://stackoverflow.com/a/14410942/
metaclass = attrs.get('__metaclass__')
if not (metaclass and issubclass(metaclass, ABCMeta)):
registry.register(self)
return _metaclass
Usage in Python 2 looks like this:
# Abstract classes; these are not registered.
class BaseWidget(object): __metaclass__ = AutoRegister(widget_registry)
class BaseGizmo(BaseWidget): __metaclass__ = ABCMeta
# Concrete classes; these get registered.
class AlphaWidget(BaseWidget): pass
class BravoGizmo(BaseGizmo): pass
What I can't figure out, though, is how to make this work in Python 3.
How can a metaclass determine if it is initializing an abstract class in Python 3?
PEP3119 describes how the ABCMeta metaclass "marks" abstract methods and creates an __abstractmethods__ frozenset that contains all methods of a class that are still abstract. So, to check if a class cls is abstract, check if cls.__abstractmethods__ is empty or not.
I also found this relevant post on abstract classes useful.
I couldn't shake the feeling as I was posting this question that I was dealing with an XY Problem. As it turns out, that's exactly what was going on.
The real issue here is that the AutoRegister metaclass, as implemented, relies on a flawed understanding of what an abstract class is. Python or not, one of the most important criteria of an abstract class is that it is not instanciable.
In the example posted in the question, BaseWidget and BaseGizmo are instanciable, so they are not abstract.
Aren't we just bifurcating rabbits here?
Well, why was I having so much trouble getting AutoRegister to work in Python 3? Because I was trying to build something whose behavior contradicts the way classes work in Python.
The fact that inspect.isabstract wasn't returning the result I wanted should have been a major red flag: AutoRegister is a warranty-voider.
So what's the real solution then?
First, we have to recognize that BaseWidget and BaseGizmo have no reason to exist. They do not provide enough functionality to be instantiable, nor do they declare abstract methods that describe the functionality that they are missing.
One could argue that they could be used to "categorize" their sub-classes, but a) that's clearly not what's going on in this case, and b) quack.
Instead, we could embrace Python's definition of "abstract":
Modify BaseWidget and BaseGizmo so that they define one or more abstract methods.
If we can't come up with any abstract methods, then can we remove them entirely?
If we can't remove them but also can't make them properly abstract, it might be worthwhile to take a step back and see if there are other ways we might solve this problem.
Modify the definition of AutoRegister so that it uses inspect.isabstract to decide if a class is abstract: see final implementation.
That's cool and all, but what if I can't change the base classes?
Or, if you have to maintain backwards compatibility with existing code (as was the case for me), a decorator is probably easier:
#widget_registry.register
class AlphaWidget(object):
pass
#widget_registry.register
class BravoGizmo(object):
pass
Below is some code from Learn Python The Hard Way
Exercise 40: Modules, Classes, And Objects
I can't seem to figure out why is there a parameter for class MyStuff(object).
What's the reason to put object in the parentheses?
class MyStuff(object):
def __init__(self):
self.tangerine = "And now a thousand years between"
def apple(self):
print "I AM CLASSY APPLES!"
I have looked through some of the articles here on StackOverflow but failed to understand what's new object and old class object.
Could someone please explain the meaning of object in the class definition?
What happens if I leave that the parentheses empty when I declare my class?
Also there is a (self) argument for the 2 functions in the code.
In the book it says "self" is an empty object python created while instantiating an object with class.
But why stating the argument before the actual use of it??
I have been learning programming for 2 weeks only so I apologize if the question is too superficial, thank you for your time~
As per your comment, I see you are using Python 2. In Python 2.2 they introduced "New-style" classes, but kept "Classic" classes for backwards-compatibility reasons. In Python 3.0 or newer, classic classes are gone - every class is a new-style class (regardless of syntax).
For python 2.2-2.7, syntactically a new-style class is declared by subclassing from object explicitly (unless it has a different parent class):
class MyStuffNew(object):
a=1
while omitting the object reference creates a classic class:
class MyStuffClassic():
a=1
Functionally, they work almost the same, but there are a few differences between them in the builtin language definitions. For example, New-style classes introduced a builtin class method __mro()__ (method resolution order) which is used by the interpreter to work out which method (in the class inheritance heirarchy) you meant to call. This inbuilt method is missing in old-style classes (and the method resolution order is different, which can lead to some unexpected behaviour). For more information about New-style vs Classic classes, please read this Python Wiki page.
As mentioned above, in Python3 or above, the syntax used doesn't matter; all classes are new-style. However, many coders will use the class MyClass(object): syntax to maintain code compatibility with Python2.7. - Please see this answer.
In any version of the Python language, class MyChildClass(ParentClass): defines an inheritance relationship - MyChildClass is a child of ParentClass and will inherit all of its methods and fields.
The self is the way Python knows this is a member method and not a static function of your class. You can only access member fields and methods from within your class by using self.field and self.myMethod(var1,var2), etc.
When you actually call these functions from other places in your code, you don't pass a value to self - it is the variable that you are using. For example:
stuff = MyStuff()
stuff.apple()
# outputs "I AM CLASSY APPLES!"
print stuff.tangerine
# outputs "And now a thousand years between"
stuff.tangerine = "Something else."
print stuff.tangerine
# outputs "Something else."
stuff2 = MyStuff()
print stuff2.tangerine
# outputs "And now a thousand years between"
If you don't include self in the method definition, calling mystuff.apple() will result in a runtime error because implicitly it's the same thing as calling MyStuff.apple(mystuff) - passing the instance of your MyStuff class into the apple function.
I'm looking for a clear explanation of why my base classes must extend object if I want to use super
# Without extending object, this code will fail with
# TypeError: must be type, not classobj
class A(object):
def __init__(self):
print "Called A.__init__"
class AChild(A):
def __init__(self):
super(AChild, self).__init__()
print "Called AChild.__init__"
AChild()
This works as expected, but if you remove object it throws the exception mentioned. I'm using Python 2.7.8. Feel free to link me to any related questions, but I didn't find a good answer with a quick search
It's because by extending object you are using new style classes which are required to support the use of super, which was added alongside the introduction of new style classes to Python.
According to the information in this answer, old style classes had a simple depth-first method resolution order so there was no need for this function, and thats probably why it wasn
t included then. However upon adding multiple inheritance, super is now the recommended way to call a superclass because of the more complicated MRO.
is there any possible to override class, or undeclare class or redeclare a Class in python?
Yes, just declare it again:
class Foo(object): x = 1
class Foo(object): x = 2
The above code will not raise any error, and the name Foo will refer to the second class declared. Note however, that the class declared by the first declaration will still exist if anything refers to it, e.g. an instance, or a derived class.
This means that existing instances will not change class when you declare a new class with the same name, and existing subclasses will not magically inherit from the new class.
Probably the simplest method to deal with subclasses is to also re-declare them, so they inherit from the "renewed" base class. An alternative would be to mess with their __bases__ property, although I can't tell you if that would have unexpected results (there will almost certainly be some corner cases where this would not work).
As to existing instances, it is possible to re-assign their __class__ property with a new class. This does present two issues - first you have to find them (see this question: Printing all instances of a class), and second of all, items stored in instance __dict__ or __slots__ properties will still be there in those instances. If that is not something that should happen with your new class definition, you will have to write appropriate code to handle that as part of the transformation.
IN summary, it's unlikely to be worth it except in quite simple cases. If you need complete uptime for a running system, you might be better using a replication-based approach to achieve code changes.
Update: If this is the kind of thing you know you're going to do, another solution would be to use the strategy pattern.
Undeclare a class using del className as usual.