I have this class with an unbound method and a static class inside:
class ClassA():
class Foo():
pass
def getFoo():
return ???.Foo
Now, if I inherit a ClassB from ClassA how do I get ClassB.getFoo() to return ClassB.Foo without explicitly implementing ClassB.getFoo()? Returning super().Foo doesn't work, writing ClassA.Foo doesn't work either obviously.
Your getFoo should be a classmethod:
class ClassA():
class Foo():
pass
#classmethod
def getFoo(cls):
return cls.Foo
Class methods are passed their class as their first argument, similar to how instance methods are passed the instance as the first argument. When you subclass ClassA, the proper class is passed.
Just to add my own thoughts on this: In addition to #Ned Batchelder's answer, you can use static methods to achieve a similar goal.
class ClassA():
class Foo():
def fooTest(self):
print("Hello from {}!".format(self.__name__))
#staticmethod
def getFoo():
return ClassA.Foo
class ClassB(ClassA):
pass
And test with:
>>> Foo = ClassB.getFoo()
>>> foo = Foo()
>>> foo.fooTest()
Hello from Foo!
This to me demonstrates the beauty of the python language - there are usually multiple ways of solving the same problem...
Related
I just noticed some unintended behaviour then tested it in an interpretor (Python 3.5.3):
>>> class SomeClass:
... def __init__(self):
... print("nothing important")
...
>>> a = SomeClass()
nothing important
>>> class SomeOtherClass(SomeClass):
... pass
...
>>> b = SomeOtherClass()
nothing important
>>>
I thought you needed to directly call the parents __init__(). What is the simplest way to write or instantiate the child class such that it does not run the __init__() from the parent class?
You can by defining an __init__ method in the child class:
class SomeOtherClass(SomeClass):
def __init__(self):
pass
I want some methods from the parent, just not that the init runs
Then your design is wrong. If you only care about code reuse but not proper subtyping (as defined by Liskov), proper designs are either composition/delegation or (probably the best in your case) multiple inheritance with mixin classes:
class CommonMixin():
def method1(self):
pass
def method2(self):
pass
class SomeClass(CommonMixin, SomeBaseClass):
def __init__(self):
print("nothing important")
class SomeOtherClass(CommonMixin, SomeOtherBaseClass):
pass
Suppose I have the following:
class myClass:
def foo(self):
# do something
How can I call myClass from inside the class without declaring an new myClass Object? i.e. I'd like something like
class myClass:
def foo(self):
# do something
if __name__ == '__main__':
# call foo
or without main:
class myClass:
def foo(self):
# do something
# call foo
Right now I keep getting either the error that self is not defined, or the error that foo expects 1 argument but 0 was provided.
You cannot. The function is part of the class, so to access it you must access the class first.
class myClass:
def foo(self):
# do something
myClass().foo()
If you just don't want to type myClass().foo() but only foo then you could just return the myClass() in a new function called foo():
def foo():
return myClass().foo()
You can use self in a class when calling from inside the class itself:
class myClass:
def __init__(self):
pass
def foo(self):
pass
def method2(self):
self.foo()
This does not create a new instance of myClass like calling myClass().foo() would, and you do not need to pass the same arguments that you may have passed in myClass.
Since foo() has a self parameter, that means it is an instance method, and therefore it is only callable from an instance of myClass.
If you want foo to be callable without an instance, use the #staticmethod decorator, and remove self from the parameter list.
I need to deliver something like this in my program
class the_class_name(Parent):
the_attribute = self.parent_class_method()
#the parent class method will return a value
#but I cannot use self here since there's no self
How can I carry this out? Is there any other alternative that can do the job for me?
I have tried using __init__ like this:
def __init__(self):
Parent.__init__(self)
self.attribute = self.the_method()
But then I have problem creating the object, it won't receive any parameters that the Parent class normally receives anymore
Sounds like you are looking for __init__:
class TheClassName(Parent):
def __init__(self):
# Set attribute to the result of the parent method
self.attribute = super(TheClassName, self).the_method()
EDIT
If your parent class has parameters in it's own __init__ function, include them in the child class:
class Parent(object):
def __init__(self, foo, bar):
...
#classmethod
def the_method(cls):
...
class TheClassName(Parent):
def __init__(self, foo, bar):
super(TheClassName, self).__init__(foo, bar)
self.attribute = super(TheClassName, self).the_method()
I don't quite understand why you don't just call the parent method on your child object when you need the value though.
There is no self at that point of the creation of the subclass, nor is there an instance of the Parent class. That means the only Parent class methods you could call would have to be either static or class methods.
To demonstrate:
class Parent(object):
#staticmethod
def static_method():
return 42
#classmethod
def class_method(cls):
return 43
class TheClassName(Parent):
the_attribute = Parent.static_method()
another_attribute = Parent.class_method()
print(TheClassName.the_attribute) # -> 42
print(TheClassName.another_attribute) # -> 43
You must use class methods, declared with the #classmethod decorator, or a #staticmethod. The #classmethod decorator is preferable so that inheritance is handled correctly, i.e. the method is invoked on the derived class (a bit of a technicality, if you are still learning this).
class Alpha(object):
#classmethod
def method1(cls):
return 'method1 has been called on {}'.format(cls)
class Beta(Alpha):
def __init__(self):
self.myattr = Beta.method1()
print(Beta().myattr)
method1 has been called on class <'__main__.Beta'>
Use
super(ClassName, self).methodname(arg)
inside a method
def child_method(self, arg):
super(ClassName, self).methodname(arg)
You cannot use self outside a method.
I'd like to automatically run some code upon class creation that can call other class methods. I have not found a way of doing so from within the class declaration itself and end up creating a #classmethod called __clsinit__ and call it from the defining scope immediately after the class declaration. Is there a method I can define such that it will get automatically called after the class object is created?
You can do this with a metaclass or a class decorator.
A class decorator (since 2.6) is probably easier to understand:
def call_clsinit(cls):
cls._clsinit()
return cls
#call_clsinit
class MyClass:
#classmethod
def _clsinit(cls):
print "MyClass._clsinit()"
Metaclasses are more powerful; they can call code and modify the ingredients of the class before it is created as well as afterwards (also, they can be inherited):
def call_clsinit(*args, **kwargs):
cls = type(*args, **kwargs)
cls._clsinit()
return cls;
class MyClass(object):
__metaclass__ = call_clsinit
#classmethod
def _clsinit(cls):
print "MyClass._clsinit()"
I understand the following Python code:
>>> class A(object):
... def __str__(self):
... return "An instance of the class A"
...
>>>
>>> a = A()
>>> print a
An instance of the class A
Now, I would like to change the output of
>>> print A
<class '__main__.A'>
Which function do I need to overload to be able to do that? The solution has to work even if the class is never instantiated. Is the situation different in Python 2.x and 3?
Define __str__() on the metaclass:
class A(object):
class __metaclass__(type):
def __str__(self):
return "plonk"
Now, print A will print plonk.
Edit: As noted by jsbueno in the comments, in Python 3.x you would need to do the following:
class Meta(type):
def __str__(self):
return "plonk"
class A(metaclass=Meta):
pass
Even in Python 2.x it might be a better idea to define the metaclass outside the class body -- I chose the nested form above to save some typing.
Define the __repr__ method on your meta class:
class MetaClass(type):
def __repr__(self):
return "Customized string"
class TestClass(object):
__metaclass__ = MetaClass
print TestClass # Customized string