Understanding Python classes - python

I am trying to learn about python classes, but I don't understand something. Why does this simple example not return "6"? It returns <function TEST.f at 0x00000000029ED378> instead. I have also tried TEST.f() but then he tells me that the argument self is missing. Shouldn't self only exist inside the class and python fills it in automatically?
#! coding=utf-8
class TEST:
def __init__(self):
self.x = 6
def f(self):
return(self.x)
print(TEST.f)

You need to create an instance of the class.
test = TEST()
print test.x()
But you also need to call the method and the variable different things.
class TEST:
def __init__(self):
self._x = 6
def x(self):
return(self._x)
Otherwise you're redefining the value of x.

There are two ways to make your code work:
As aychedee said, create a TEST instance, and invoke method f from
the instance:
>>> TEST().f()
6
Another way is to create a TEST instance t, and pass it the
method f:
>>> t = TEST()
>>> TEST.f(t)
6
Remember the self argument of your method f? Basically, this is to explicitly pass the TEST instance t to method f.

You need to create an instance just as shown.
test = Test()
test.f()

Related

Methods in python are associated with the class. what does a function associated directly with the instance imply?

I know that in python, methods are associated the class and not the instance but they accept the instance as their first argument so as to access it. but, one can still define a function and tie it to an instance directly. What does this imply? and can this function somehow access the instance?
class TestClass:
def __init__(self, a):
self.a = a
def method1(self):
return self.a
my_obj = TestClass(12)
print(my_obj.method1()) // 12
Python also allows this:
class TestClass:
def __init__(self, a):
self.a = a
my_obj = TestClass(12)
def method1_defined_outside(self):
return self.a
TestClass.method1 = method1_defined_outside
print(my_obj.method1()) // 12
The two snippets above mean the same thing.
but python also allows this:
class TestCase:
def __init__(self, a):
self.a = a
my_obj = TestCase(12)
def method1_defined_outside(self):
return self.a
my_obj.method1 = method1_defined_outside
print(my_obj.method1()) // this throws an error stating the method1 is missing one postional argument(s), so clearly self does not automatically equate to the object
difference between the second and the third snippet is that the method defined outside is tied to the instance in latter, and to the class in the former.
When you access a method through an instance, but the method lives on the class, accessing the method actually creates a method wrapper. This wrapper knows what instance the method was called on, and passes it through to the actual function as the first argument (named, by convention, self). The mechanism behind this is the descriptor protocol and it's how properties work, too.
When you put the method directly on the instance, none of that applies and it's just a function that you access by way of the instance. It doesn't get self.
Now, you can create a method wrapper by manually invoking the descriptor, and set the resulting bound method on the instance.
my_obj.method1 = method1_defined_outside.__get__(my_obj)
Now my_obj.method1() passes my_obj as self.
The situations in which you'd want to set a method on an instance like this are fairly rare, though.
One way you could force sending the instance as self is by using the functools.partial wrapper as:
from functools import partial
class A:
def __init__(self):
self.x = 10
a1 = A()
def do_external(self):
print("EXTERNAL", self.x)
a1.doext = partial(do_external, a1)
a1.doext()
which will yield in the console:
EXTERNAL 10

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()

Python constructors and __init__

Why are constructors indeed called "Constructors"? What is their purpose and how are they different from methods in a class?
Also, can there be more that one __init__ in a class? I tried the following, can someone please explain the result?
>>> class test:
def __init__(self):
print "init 1"
def __init__(self):
print "init 2"
>>> s=test()
init 2
Finally, is __init__ an operator overloader?
There is no function overloading in Python, meaning that you can't have multiple functions with the same name but different arguments.
In your code example, you're not overloading __init__(). What happens is that the second definition rebinds the name __init__ to the new method, rendering the first method inaccessible.
As to your general question about constructors, Wikipedia is a good starting point. For Python-specific stuff, I highly recommend the Python docs.
Why are constructors indeed called "Constructors" ?
The constructor (named __new__) creates and returns a new instance of the class. So the C.__new__ class method is the constructor for the class C.
The C.__init__ instance method is called on a specific instance, after it is created, to initialise it before being passed back to the caller. So that method is the initialiser for new instances of C.
How are they different from methods in a class?
As stated in the official documentation __init__ is called after the instance is created. Other methods do not receive this treatment.
What is their purpose?
The purpose of the constructor C.__new__ is to define custom behaviour during construction of a new C instance.
The purpose of the initialiser C.__init__ is to define custom initialisation of each instance of C after it is created.
For example Python allows you to do:
class Test(object):
pass
t = Test()
t.x = 10 # here you're building your object t
print t.x
But if you want every instance of Test to have an attribute x equal to 10, you can put that code inside __init__:
class Test(object):
def __init__(self):
self.x = 10
t = Test()
print t.x
Every instance method (a method called on a specific instance of a class) receives the instance as its first argument. That argument is conventionally named self.
Class methods, such as the constructor __new__, instead receive the class as their first argument.
Now, if you want custom values for the x attribute all you have to do is pass that value as argument to __init__:
class Test(object):
def __init__(self, x):
self.x = x
t = Test(10)
print t.x
z = Test(20)
print t.x
I hope this will help you clear some doubts, and since you've already received good answers to the other questions I will stop here :)
Classes are simply blueprints to create objects from. The constructor is some code that are run every time you create an object. Therefor it does'nt make sense to have two constructors. What happens is that the second over write the first.
What you typically use them for is create variables for that object like this:
>>> class testing:
... def __init__(self, init_value):
... self.some_value = init_value
So what you could do then is to create an object from this class like this:
>>> testobject = testing(5)
The testobject will then have an object called some_value that in this sample will be 5.
>>> testobject.some_value
5
But you don't need to set a value for each object like i did in my sample. You can also do like this:
>>> class testing:
... def __init__(self):
... self.some_value = 5
then the value of some_value will be 5 and you don't have to set it when you create the object.
>>> testobject = testing()
>>> testobject.some_value
5
the >>> and ... in my sample is not what you write. It's how it would look in pyshell...
coonstructors are called automatically when you create a new object, thereby "constructing" the object. The reason you can have more than one init is because names are just references in python, and you are allowed to change what each variable references whenever you want (hence dynamic typing)
def func(): #now func refers to an empty funcion
pass
...
func=5 #now func refers to the number 5
def func():
print "something" #now func refers to a different function
in your class definition, it just keeps the later one
There is no notion of method overloading in Python. But you can achieve a similar effect by specifying optional and keyword arguments

What is the proper term for the methods defined inside of a Python class before the class is instantiated?

Using this example from http://docs.python.org/tutorial/classes.html#class-objects:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
According to those docs, f is an attribute reference that returns a function object.
Is there any shorter way of saying what f is? Can I call it a method of a class (note how I didn't say "class method" which is incorrect)? Or a function defined within a class? Or an instance method?
In other words, what's the formal short-hand term for f in terms of its relation to MyClass?
If you're referring specifically to the f returned by MyClass.f, then f is an unbound method of MyClass. Or at least that's what the REPL calls it:
>>> MyClass.f
<unbound method MyClass.f>
In general though, I don't think anyone would fault you for simply calling it a "method", plain and simple. Or, in terms of its relation to MyClass, a method of MyClass.
I'd say it's an instance method(or member function), because this method is only accessible when you bind it with an instance, instance.f() or MyClass.f(instance).
x = MyClass()
def __init__(self):
self.data = []
print x.i
print x.f()
print MyClass.__doc__
# Instance x = MyClass()
# More __init__(self) is important
# Sorry my english. I'm from Brazl

Python - how can I override the functionality of a class before it's imported by a different module?

I have a class that's being imported in module_x for instantiation, but first I want to override one of the class's methods to include a specific feature dynamically (inside some middleware that runs before module_x is loaded.
Neither AndiDog's nor Andrew's answer answer your question completely. But they have given the most important tools to be able to solve your problem (+1 to both). I will be using one of their suggestions in my answer:
You will need 3 files:
File 1: myClass.py
class C:
def func(self):
#do something
File 2: importer.py
from myClass import *
def changeFunc():
A = C()
A.func = lambda : "I like pi"
return A
if __name__ == "importer":
A = changeFunc()
File 3: module_x.py
from importer import *
print A.func()
The output of module_x would print "I like pi"
Hope this helps
You should know that each class type (like C in class C: ...) is an object, so you can simply overwrite the class methods. As long as instances don't overwrite their own methods (won't happen too often because that's not really useful for single inntances), each instance uses the methods as inherited from its class type. This way, you can even replace a method after an instance has been created.
For example:
class C:
def m(self):
print "original"
c1 = C()
c1.m() # prints "original"
def replacement(self):
print "replaced!"
C.m = replacement
c1.m() # prints "replaced!"
C().m() # prints "replaced!"
Since every python class is actually a dictionary (not only objects!)
You can easily override class methods by associate them with new function.
class A:
def f(self):
return 5
a = A()
a.f() #5
A.f = lambda self: 10
a.f() #10
You should use it with care. In most cases decorators & proper OO-design will work for you and if you forced to override class method, maybe, you make something wrong.

Categories

Resources