This question is similar, but it pertains to static methods: In Python, how do I reference a class generically in a static way, like PHP's "self" keyword?
How do you refer to a class generically in an instance method?
e.g.
#!/usr/bin/python
class a:
b = 'c'
def __init__(self):
print(a.b) # <--- not generic because you explicitly refer to 'a'
#classmethod
def instance_method(cls):
print(cls.b) # <--- generic, but not an instance method
For old-style classes (if your code is Python 2.x code, and your class in not inheriting from object), use the __class__ property.
def __init__(self):
print(self.__class__.b) # Python 2.x and old-style class
For new-style classes (if your code is Python 3 code), use type:
def __init__(self):
print(self.__class__.b) # __class__ works for a new-style class, too
print(type(self).b)
Internally, type uses the __class__ property.
Related
I am given a designated factory of A-type objects. I would like to make a new version of A-type objects that also have the methods in a Mixin class. For reasons that are too long to explain here, I can't use class A(Mixin), I have to use the A_factory. Below I try to give a bare bones example.
I thought naively that it would be sufficient to inherit from Mixin to endow A-type objects with the mixin methods, but the attempts below don't work:
class A: pass
class A_factory:
def __new__(self):
return A()
class Mixin:
def method(self):
print('aha!')
class A_v2(Mixin): # attempt 1
def __new__(cls):
return A_factory()
class A_v3(Mixin): # attempt 2
def __new__(cls):
self = A_factory()
super().__init__(self)
return self
In fact A_v2().method() and A_v3().method() raises AttributeError: 'A' object has no attribute 'method'.
What is the correct way of using A_factory within class A_vn(Mixin) so that A-type objects created by the factory inherit the mixin methods?
There's no obvious reason why you should need __new__ for what you're showing here. There's a nice discussion here on the subject: Why is __init__() always called after __new__()?
If you try the below it should work:
class Mixin:
def method(self):
print('aha!')
class A(Mixin):
def __init__(self):
super().__init__()
test = A()
test.method()
If you need to use a factory method, it should be a function rather than a class. There's a very good discussion of how to use factory methods here: https://realpython.com/factory-method-python/
EDITED: Let's say I have some classes that inherit from the SuperFoo abstract class:
from abc import ABCMeta, abstractmethod
class SuperFoo(object):
__metaclass__ = ABCMeta
#abstractmethod
def do_something():
pass
class Foo(SuperFoo):
def __init__(self):
pass
def do_something():
pass
class Bar(SuperFoo):
def __init__(self):
pass
def do_something():
pass
And a documented function that takes in a subclass of SuperFoo as a parameter:
def build(super_foo):
"""
Instantiate a SuperFoo class and do some other stuff.
#param super_foo: The subclass whose constructor will be called
#type super_foo: ??? <--- What to use here?
#return: An instance of a SuperFoo subclass
#rtype: SuperFoo
"""
# Do some stuff
instance = class_name() # Instantiate class
return instance
foo = build(Foo)
bar = build(Bar)
What #type should I use in the function's docstring? It cannot be SuperFoo because that would correspond to an instance of SuperFoo and not to the type itself.
The simple technical answer has already been posted by motyzk - in your example, what you pass to build are classes so the the (ill-named) class_name param is of type type - with the restriction that (based on your code snippet) this class shouldn't expect any parameter, which doesn't correspond to any unambigous well-defined existing builtin "type".
Now as mentionned in comments, in Python
everything is an object (and as such an instance of a class),
instanciating a class is done by calling the class object just like you'd call any function,
all callables DO return an object, even if implicitely (None is an object too)
so your build function would technically work just the same with just any callable that doesn't expect a param. As an example, this:
def bar():
return
whatever = build(bar)
is technically correct.
Now you mention in the function's docstring (emphasis is mine):
Instantiate a class and do some other stuff
Since your function would just be totally useless as shown in the snippet you posted, I assume that in your real code the important part is in the (not shown) "do some other stuff", and that this "do some other stuff" part relies on some specific property of the class being passed.
In this case, you should document those specificities, either informally (textually, in the docstring itself) or formally using the abc module. This won't solve your question actually - your function expects a class, not instance, so theoritically #type should be type(YourABC), but then what you get is abc.ABCMeta. At this point, you either have to write a custom metaclass (inherithing from abc.ABCMeta) and specify it as the proper #type - but this won't say anything useful as far as documentation is concerned - or just textually describe it as "a MyABC subclass" (which is the correct description but not usable for code instrumentation).
The type is "type", as can be seen, running this:
class Foo(object):
def __init__(self):
pass
def f(t):
print(type(t)) # <class 'type'>
f(Foo)
i have seen many posts that describe how to call base class function is called inside a derived class function using the super keyword.I want to call a base class overloaded function globally using a derived class object.
class a:
def __init__(self):
self.x=45
def fun(self):
print "fun in base class"
class b(a):
def __init__(self):
self.y=98
def fun(self):
print "fun in derived class"
objb=b()
objb.fun()#here i want to call the base class fun()
Input:
objb = b()
super(b, objb).fun()
Output:
fun in base class
Edit:
As mentionned in comment below, in Python 2.7+ you need to declare class a(object) for this to work. This comes from a historical evolution of classes in Python, with this solution being functional for "new-style" classes only, i.e. for classes inheriting from object. In Python 3.x however, all classes are "new-style" by default, meaning you don't have to perform this small addition.
If you really want to call the 'base' function that works on old-style classes (classes that don't extend object) you can do it like:
objb = b()
a.fun(objb) # fun in base class
Or if you don't know the base/parent class, you can 'extract' it from the instance itself:
objb = b()
objb.__class__.__bases__[0].fun(objb) # fun in base class
But save yourself some trouble and just extend your base classes from object so you can use the super() notation instead of doing bases acrobatics.
I want to ask what the with_metaclass() call means in the definition of a class.
E.g.:
class Foo(with_metaclass(Cls1, Cls2)):
Is it a special case where a class inherits from a metaclass?
Is the new class a metaclass, too?
with_metaclass() is a utility class factory function provided by the six library to make it easier to develop code for both Python 2 and 3.
It uses a little sleight of hand (see below) with a temporary metaclass, to attach a metaclass to a regular class in a way that's cross-compatible with both Python 2 and Python 3.
Quoting from the documentation:
Create a new class with base class base and metaclass metaclass. This is designed to be used in class declarations like this:
from six import with_metaclass
class Meta(type):
pass
class Base(object):
pass
class MyClass(with_metaclass(Meta, Base)):
pass
This is needed because the syntax to attach a metaclass changed between Python 2 and 3:
Python 2:
class MyClass(object):
__metaclass__ = Meta
Python 3:
class MyClass(metaclass=Meta):
pass
The with_metaclass() function makes use of the fact that metaclasses are a) inherited by subclasses, and b) a metaclass can be used to generate new classes and c) when you subclass from a base class with a metaclass, creating the actual subclass object is delegated to the metaclass. It effectively creates a new, temporary base class with a temporary metaclass metaclass that, when used to create the subclass swaps out the temporary base class and metaclass combo with the metaclass of your choice:
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(type):
def __new__(cls, name, this_bases, d):
return meta(name, bases, d)
#classmethod
def __prepare__(cls, name, this_bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})
Breaking the above down:
type.__new__(metaclass, 'temporary_class', (), {}) uses the metaclass metaclass to create a new class object named temporary_class that is entirely empty otherwise. type.__new__(metaclass, ...) is used instead of metaclass(...) to avoid using the special metaclass.__new__() implementation that is needed for the slight of hand in a next step to work.
In Python 3 only, when temporary_class is used as a base class, Python first calls metaclass.__prepare__() (passing in the derived class name, (temporary_class,) as the this_bases argument. The intended metaclass meta is then used to call meta.__prepare__(), ignoring this_bases and passing in the bases argument.
next, after using the return value of metaclass.__prepare__() as the base namespace for the class attributes (or just using a plain dictionary when on Python 2), Python calls metaclass.__new__() to create the actual class. This is again passed (temporary_class,) as the this_bases tuple, but the code above ignores this and uses bases instead, calling on meta(name, bases, d) to create the new derived class.
As a result, using with_metaclass() gives you a new class object with no additional base classes:
>>> class FooMeta(type): pass
...
>>> with_metaclass(FooMeta) # returns a temporary_class object
<class '__main__.temporary_class'>
>>> type(with_metaclass(FooMeta)) # which has a custom metaclass
<class '__main__.metaclass'>
>>> class Foo(with_metaclass(FooMeta)): pass
...
>>> Foo.__mro__ # no extra base classes
(<class '__main__.Foo'>, <type 'object'>)
>>> type(Foo) # correct metaclass
<class '__main__.FooMeta'>
UPDATE: the six.with_metaclass() function has since been patched with a decorator variant, i.e. #six.add_metaclass(). This update fixes some mro issues related to the base objects. The new decorator would be applied as follows:
import six
#six.add_metaclass(Meta)
class MyClass(Base):
pass
Here are the patch notes and here is a similar, detailed example and explanation for using a decorator alternative.
This question already has answers here:
Why do Python classes inherit object?
(6 answers)
Closed 1 year ago.
I have found that both of the following work:
class Foo():
def a(self):
print "hello"
class Foo(object):
def a(self):
print "hello"
Should all Python classes extend object? Are there any potential problems with not extending object?
In Python 2, not inheriting from object will create an old-style class, which, amongst other effects, causes type to give different results:
>>> class Foo: pass
...
>>> type(Foo())
<type 'instance'>
vs.
>>> class Bar(object): pass
...
>>> type(Bar())
<class '__main__.Bar'>
Also the rules for multiple inheritance are different in ways that I won't even try to summarize here. All good documentation that I've seen about MI describes new-style classes.
Finally, old-style classes have disappeared in Python 3, and inheritance from object has become implicit. So, always prefer new style classes unless you need backward compat with old software.
In Python 3, classes extend object implicitly, whether you say so yourself or not.
In Python 2, there's old-style and new-style classes. To signal a class is new-style, you have to inherit explicitly from object. If not, the old-style implementation is used.
You generally want a new-style class. Inherit from object explicitly. Note that this also applies to Python 3 code that aims to be compatible with Python 2.
In python 3 you can create a class in three different ways & internally they are all equal (see examples). It doesn't matter how you create a class, all classes in python 3 inherits from special class called object. The class object is fundamental class in python and provides lot of functionality like double-underscore methods, descriptors, super() method, property() method etc.
Example 1.
class MyClass:
pass
Example 2.
class MyClass():
pass
Example 3.
class MyClass(object):
pass
Yes, all Python classes should extend (or rather subclass, this is Python here) object. While normally no serious problems will occur, in some cases (as with multiple inheritance trees) this will be important. This also ensures better compatibility with Python 3.
As other answers have covered, Python 3 inheritance from object is implicit. But they do not state what you should do and what is convention.
The Python 3 documentation examples all use the following style which is convention, so I suggest you follow this for any future code in Python 3.
class Foo:
pass
Source: https://docs.python.org/3/tutorial/classes.html#class-objects
Example quote:
Class objects support two kinds of operations: attribute references
and instantiation.
Attribute references use the standard syntax used for all attribute
references in Python: obj.name. Valid attribute names are all the
names that were in the class’s namespace when the class object was
created. So, if the class definition looked like this:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
Another quote:
Generally speaking, instance variables are for data unique to each
instance and class variables are for attributes and methods shared by
all instances of the class:
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
in python3 there isn't a differance, but in python2 not extending object gives you an old-style classes; you'd like to use a new-style class over an old-style class.