Dealing with class inheritance in python - python

Can someone explain why I'm getting the error:
global name 'helloWorld' is not defined
when executing the following:
class A:
def helloWorld():
print 'hello world'
class B(A):
def displayHelloWorld(self):
helloWorld()
class Main:
def main:
b = B()
b.displayHelloWorld()
I'm used to java where class B would obviously have a copy of class A's method "helloWorld" and thus this code would run fine when executing main. This however appears to think class B doesn't have any method called "helloWorld"

Missing the self before the helloWorld(). The self keyword means that this an instance function or variable. When class B inherits class A, all the functions in class A can now be accessed with the self.classAfunction() as if they were implemented in class B.
class A():
def helloWorld(self): # <= missing a self here too
print 'hello world'
class B(A):
def displayHelloWorld(self):
self.helloWorld()
class Main():
def main(self):
b = B()
b.displayHelloWorld()

You need to indicate that the method is from that class (self.):
class B(A):
def displayHelloWorld(self):
self.helloWorld()
Python differs in this from Java. You have to specify this explicitly in Python whereas Java accepts implicitly as well.

I don't know what is the version of python used in this example but it seems that syntax looks like python3. (except print statement which looks like python2.x)
Lets suppose that this is python3
I would say that helloWorld is class method of class A and It should be called as class attribute. As soon as this function is in class namespace It can be accessed outside this class only using owner class.
A.helloWorld()
or
B.helloWorld()
or
self.__class__.helloWorld()
You can't call it as bound method in this case because self argument will be passed and as soon as your function doesn't expect it it will fail.
there is possibility that helloWorld is method of A and self parameter is just missed
in this case this method can be called as follow:
self.helloWorld()
or
A.helloWorld(self)

Related

Python staticmethod decorator with inheritance

My case:
class BaseClass:
#staticmethod
def dummy_decorator(fnc):
def wrapper():
print('Im so dummy')
return wrapper
class InheritedClass(BaseClass):
def __init__(self):
pass
def anymethod(self):
print('hello world')
When I look at dir(), I see my staticmethod
>>> c = InheritedClass()
>>> dir(c)
['__doc__', '__init__', '__module__', 'anymethod', 'dummy_decorator']
Also, I can use my dummy operator as simple staticmethod inside new class.
But when I try to use it as decorator -- I get error
class InheritedClass(BaseClass):
def __init__(self):
pass
#dummy_decorator
def anymethod(self):
print('hello world')
>>> NameError: name 'dummy_decorator' is not defined
Why it works so?
I know, that if I change #dummy_decorator to #BaseClass.dummy_decorator -- everything will work, but why I can't use decorator without ref to parent class?
The reason why is baecause it is a static method, it belongs to the class as you have figured out when you put #BaseClass.dummy_decorator and it worked.
It is an attribute of the class so you can't just refer to it by dummy_decorator unless you move it out of the class or save it into the global namespace
To understand this properly, you need to understand how class definitions work. In a nutshell, everything inside a class block is executed just like regular Python code. Every name that has been created inside that class block (e.g. def or variable assignments) are then wrapped up at the end of the class block and become attributes of the new class object. It goes something like:
# START CAPTURE
def __init__(self):
pass
foo = 'bar'
# END CAPTURE
InheritedClass = # OBJECT WITH ATTRIBUTES "CAPTURED" ABOVE AND ADDITIONAL MAGIC
So, any code within the class block is just regular Python code. It hasn't "inherited" anything yet. That's the "additional magic" applied to the resulting class object at the end of the class block. And since there's no global "dummy_decorator" name defined, you can't call it by that name. It exists as "BaseClass.dummy_decoator", same as it would outside any class block.

Assign Python class variable with a method of that class

I have a code like this:
def my_func():
pass
class MyClass():
class_variable = my_func()
pass
i = MyClass()
Since my_func is logically related to MyClass, and doesn't serve any purpose outside of it, I'd prefer to have something like that instead:
class MyClass():
class_variable = my_func()
def my_func():
pass
i = MyClass()
The above doesn't work, of course, because my_func isn't defined yet at the time it's called. Is there some other way to assign a class variable from inside the class?
I'd personally keep my_func() outside the class. Sure, it may only be used for the class definition, but if it is not useful once the class is defined, it should not be part of the class API.
If the my_func() function should be used together with the class even after the class has been created, then you can still make this work with MyClass.my_func() being a static method. In that case define the function first before setting the class variable:
class MyClass():
#staticmethod
def my_func():
pass
class_variable = my_func.__func__()
The #staticmethod is not strictly necessary as at the time class_variable is set, my_func is still a local name in the class definition body.
However, since you are using it as as static function anyway, you may as well mark it as such. The advantage however is that MyClass.my_func() now also works.
Because a #staticmethod isn't going to bind outside of a class or instance attribute context, you do need to unwrap it first by accessing the wrapped function with the __func__ attribute.
Demo:
>>> class MyClass():
... #staticmethod
... def my_func():
... return 'foobar'
... class_variable = my_func.__func__()
...
>>> MyClass.class_variable
'foobar'
>>> MyClass.my_func()
'foobar'

Calling a base class method from a derived class method in Python

I have a class A and I have inherited a class B from class A.
I have two methods methodX & methodY in ClassA. This methodY will be calling methodX in classA.
Now I have a methodZ in ClassB.
The following is the scenario:-
class A(object):
def methodX(self):
....
def methodY(self):
methodX()
class B(A)
def methodZ(self):
self.methodY() #says the global methodX is not defined
My question is that I have to call methodY which inturn calls methodX from methodZ. How is it possible? Should I define the methodX globally ? Or is there any other alternative..
Thanks in advance !
In methodY you should be calling self.methodX().
As it has been said before, using self.methodX() seems to be solving your problem.
Check this:
class A(object):
def methodX(self):
print "A.methodX"
def methodY(self):
print "A.methodY"
self.methodX()
class B(A):
def methodZ(self):
print "B.methodZ"
self.methodY()
b = B()
b.methodZ()
Generates this output:
$ python test.py
B.methodZ
A.methodY
A.methodX
$
Which I think it's what you were looking for...
Since a member function cannot be called without using the object of that class, this error is thrown. Using
self.methodX()
Calls the function methodX() using the object using the object used to call the methodY()

How to refer overriden class functions in python

I know C++ and Java and I am unfamiliar with Pythonic programming. So maybe it is bad style what I am trying to do.
Consider fallowing example:
class foo:
def a():
__class__.b() # gives: this is foo
bar.b() # gives: this is bar
foo.b() # gives: this is foo
# b() I'd like to get "this is bar" automatically
def b():
print("this is foo")
class bar( foo ):
def b( ):
print("this is bar")
bar.a()
Notice, that I am not using self parameters as I am not trying to make instances of classes, as there is no need for my task. I am just trying to refer to a function in a way that the function could be overridden.
What you want is for a to be a classmethod.
class Foo(object):
#classmethod
def a(cls):
Foo.b() # gives: this is foo
Bar.b() # gives: this is bar
cls.b() # gives: this is bar
#staticmethod
def b():
print("this is foo")
class Bar(Foo):
#staticmethod
def b():
print("this is bar")
Bar.a()
I've edited your style to match the Python coding style. Use 4 spaces as your indent. Don't put extra spaces in between parenthesis. Capitalize & CamelCase class names.
A staticmethod is a method on a class that doesn't take any arguments and doesn't act on attributes of the class. A classmethod is a method on a class that gets the class automatically as an attribute.
Your use of inheritance was fine.
Quote from the Execution Model:
The scope of names defined in a class block is limited to the class
block; it does not extend to the code blocks of methods – this
includes generator expressions since they are implemented using a
function scope.
This mean that there is no name b in the scope of function a. You should refer to it via class or instance object.

What is the Python equivalent of a Ruby class method?

In ruby you can do this:
class A
def self.a
'A.a'
end
end
puts A.a #-> A.a
How can this be done in python. I need a method of a class to be called without it being called on an instance of the class. When I try to do this I get this error:
unbound method METHOD must be called with CLASS instance as first argument (got nothing instead)
This is what I tried:
class A
def a():
return 'A.a'
print A.a()
What you're looking for is the staticmethod decorator, which can be used to make methods that don't require a first implicit argument. It can be used like this:
class A(object):
#staticmethod
def a():
return 'A.a'
On the other hand, if you wish to access the class (not the instance) from the method, you can use the classmethod decorator, which is used mostly the same way:
class A(object):
#classmethod
def a(cls):
return '%s.a' % cls.__name__
Which can still be called without instanciating the object (A.a()).
There are two ways to do this:
#staticmethod
def foo(): # No implicit parameter
print 'foo'
#classmethod
def foo(cls): # Class as implicit paramter
print cls
The difference is that a static method has no implicit parameters at all. A class method receives the class that it is called on in exactly the same way that a normal method receives the instance.
Which one you use depends on if you want the method to have access to the class or not.
Either one can be called without an instance.
You can also access the class object in a static method using __class__:
class A() :
#staticmethod
def a() :
return '{}.a'.format( __class__.__name__ )
At least this works in Python 3.1

Categories

Resources