Overwritten Methods don't contain self? - python

Here is an example I just played through on my machine:
$ python
Python 2.7.4 (default, Apr 19 2013, 18:28:01)
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
# just a test class
>>> class A(object):
... def hi(self):
... print("hi")
...
>>> a = A()
>>> a.hi()
hi
>>> def hello(self):
... print("hello")
...
>>>
>>> hello(None)
hello
>>>
>>>
>>>
>>> a.hi = hello
# now I would expect for hi to work the same way as before
# and it just prints hello instead of hi.
>>> a.hi()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hello() takes exactly 1 argument (0 given)
>>>
>>> def hello():
... print("hello")
...
# but instead this one works, which doesn't contain any
# reference to self
>>> a.hi = hello
>>> a.hi()
hello
>>>
>>>
>>>
>>>
>>> a.hello = hello
>>> a.hello()
hello
What is happening here? Why doesn't the function get the parameter self, when it is used as a method? What would I need to do, to get a reference to self inside it?

A method in a class referenced via an instance is bound to that instance, in your case:
In [3]: a.hi
Out[3]: <bound method A.hi of <__main__.A object at 0x218ab10>>
Compare to:
In [4]: A.hi
Out[4]: <unbound method A.hi>
So, to achieve the effect you probably want, do
In [5]: def hello(self):
...: print "hello"
...:
In [6]: A.hi = hello
In [7]: a.hi()
hello
Beware - this will apply to all instances of A. But if you want to override a method on one instance only, do you really need to pass self?

It is the way functions are accessed when they are class attributes.
A function added as a class attribute gets accessed as a descriptor. You see that if you do
class A(object):
pass
def f(*a): pass
A.f = f
print f
print A.f
print A().f
Here, you get the output
<function f at 0x00F03D70>
<unbound method A.f>
<bound method A.f of <__main__.A object at 0x00F089D0>>
The same output you'd get with
print f
print f.__get__(None, A)
print f.__get__(A(), A)
because that's the way how descriptors work.
All this - the transformation from a function to a method via the descriptor protocol - does not happen on instance attributes.
If you do
a = A()
a.f = f
then a.f is as well read back as a function, not as a method. Thus, you should consider this at the time you do the assignment and rather do
a.f = lambda: f(a)
in order to pass a to the function.

Related

Can a class and a function have a common name in Python?

It looks like there is a function as well as a class associated with the name cv2.VideoCapture.
Is it possible for a class and a function that share a common name?
My guess is that at this moment cv2.VideoCapture represents a class and a function as well.
>>>import cv2
>>>print(cv2.VideoCapture)
<built-in function VideoCapture>
>>>camera = cv2.VideoCapture(0)
>>>print(type(camera))
<class 'cv2.VideoCapture'>
All depends on what you call "name"...
>>> class Foo(object):
... pass
...
>>> _Foo = Foo
>>> def Foo():
... return _Foo()
...
>>> f = Foo()
>>> print(Foo)
<function Foo at 0x7f74a5fec8c0>
>>> print(type(f))
<class '__main__.Foo'>
>>>
As you can see, you here have a function exposed as Foo and having it's __name__ == "Foo", and a class exposed as _Foo but having __name__ == "Foo" too.
To answer your question: you cannot have the same name (=> variable) bound to more than one object at a given time in a given namespace. But you can have has many objects has you want having the same value for a .__name__ attribute.
I have not checked the OpenCV source code in order to check out what or why is going on in this specific case, but in theory this can be possible if your function returns an instance of a class with the same name.
consider the file cv2.py with the following content
def VideoCapture(_):
class VideoCapture(object):
pass
return VideoCapture()
usage:
>>> import cv2
>>> cv2.VideoCapture
<function VideoCapture at 0x7f70d36069b0>
>>>
>>> camera = cv2.VideoCapture(0)
>>> type(camera)
<class 'cv2.VideoCapture'>

What is difference between A.fun and A().fun?

class A(object):
def fun(self):
pass
ins_a = A.fun
ins_b = A().fun
I came across this piece of code and I am unable to understand the difference between the 2 objects.
Just try the above code in the interactive interpreter:
>>> class A(object):
... def fun(self):
... pass
...
>>> ins_a = A.fun
>>> ins_b = A().fun
>>> ins_a
<unbound method A.fun>
>>> ins_b
<bound method A.fun of <__main__.A object at 0x7f694866a6d0>>
As you can see, it is a matter of bound/unbound methods. A bound method is a method "tied" to an object. You can have a more thorough explanation in this SO answer.
The biggest difference is if you try to call the methods:
If we add a print "hello world", it will make it more obvious.
class A(object):
def fun(self):
print ("hello world")
ins_a = A.fun
ins_b = A().fun
Now try calling both:
In [10]: ins_a()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-52906495cc43> in <module>()
----> 1 ins_a()
TypeError: unbound method fun() must be called with A instance as first argument (got nothing instead)
In [11]: ins_b()
hello world
In python 3 they are different types as the unbound method type is gone:
In [2]: type(ins_a)
Out[2]: builtins.function
In [3]: type(ins_b)
Out[3]: builtins.method

Why does id() of an unbound method in Python 2 change for every access

Python 2.6.5 (r265:79063, Oct 1 2012, 22:07:21)
[GCC 4.4.3]
>>> class myclass:
... def func(self):
... pass
>>> dd = myclass.func
>>> ee = myclass.func
>>> cc = myclass.func
>>> ff = myclass.func
>>> ss = myclass.func
>>> uu = myclass.func
>>> pp = myclass.func
>>>
>>>
>>> id(dd) ; id(cc) ; id(ee) ; id(ff) ; id(ss) ; id(uu) ; id(pp)
3074535252L
3074534772L
3074522444L
3074531732L
3074497588L
3073003604L
3073003724L
Why is the ID of the unbound method different each time?
Shouldn't it be same ?
This is because the methods on a class (old or new) work really like attributes with the descriptor __get__ method; On python 2 the code
foo = FooClass.bar_method
is analogous to
import types
foo = types.MethodType(FooClass.__dict__['bar_method'], None, FooClass)
It will create a new instance of instancemethod(bar_method, None, FooClass) on each access. The original function is available as FooClass.bar_method.im_func and the class instance in foo.im_class. The type for both bound and unbound methods is the same instancemethod; if the im_self member is None, the instancemethod instance has the repr <unbound method ...>, whereas if im_self member is not None, the repr is <bound method...>
Python 3 is different. Unbound methods have a repr <function x.f at 0x7fd419cf69e0> and the id is always the same, that is they are just general functions. In Python 3 you can pass anything for self of an unbound undecorated method, even None, it is just a function with a dot in its name.

What does first argument to `type` do?

Some code.
In [1]: A = type('B', (), {})
In [2]: a = A()
In [3]: b = B()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/home/shabda/<ipython console> in <module>()
NameError: name 'B' is not defined
What does first argument to type doing here?
It's setting the __name__ property of the created class.
When you say:
class B(object):
two things happen with that 'B':
The name 'B' is assigned the class. This is just like if you'd said "B = ...".
The __name__ property of the class is set to 'B'.
When you invoke the type constructor manually only the latter half is done. If you don't assign the result to 'B' then B will remain set (or unset) as it was before.
Note that a similar result could be obtained by saying:
class B(object):
pass
A = B
del B
Now A refers to a class that calls itself 'B', and B doesn't refer to anything.
It's creating a new class with the name B:
Python 2.5.4 (r254:67916, Nov 19 2009, 22:14:20)
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> type('B', (), {})
<class '__main__.B'>
See the second form of type here for more information.
When you assign the result of calling type to a variable, you're just giving the class B another name. It's equivalent to doing
>>> class B(object):
... pass
...
>>> A = B
>>> a = A()
>>> b = B()
'B' is just a string which is the name of A
One place it is used is for the default __repr__ of classes and their objects
>>> A=type('B', (), {})
>>> A
<class '__main__.B'>
>>> a=A()
>>> a
<__main__.B object at 0xb7cf88ec>
The usual way to create a class has no way to explicitly set the __name__ attribute.
In this case it is implicitly set by the class constructor
>>> class A:pass
...
>>> A
<class __main__.A at 0xb7cf280c>
But there is nothing stopping you from changing the name afterward
>>> A.__name__
'A'
>>> A.__name__='B'
>>> A
<class __main__.B at 0xb7cf280c>
>>>

What is the significance of a function without a 'self' argument insde a class?

class a:
def b():
...
what is the Significance of b
thanks
class a:
#staticmethod
def b():
return 1
def c(self):
b()
print a.b()
print a().b()
print a().c()#error
and
class a:
#staticmethod
def b():
return 1
def c(self):
return self.b()
print a.b()
print a().b()
print a().c()
#1
#1
#1
Basically you should use b() as staticmethod so that you can call it either from Class or Object of class e.g:
bash-3.2$ python
Python 2.6 (trunk:66714:66715M, Oct 1 2008, 18:36:04)
[GCC 4.0.1 (Apple Computer, Inc. build 5370)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class a:
... #staticmethod
... def b():
... return 1
...
>>> a_obj = a()
>>> print a.b()
1
>>> print a_obj.b()
1
>>>
Syntax error. Try calling it.
>>> class a:
... def b():
... return 1
...
>>> x=a()
>>> x.b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: b() takes no arguments (1 given)
See also:
>>> class a:
... def b():
... return 1
... def c(self):
... return b()
...
>>> a().c()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in c
NameError: global name 'b' is not defined
in a class method self is the instance of the class the method is called on. beware that self is not a keyword in python just a conventional name given to the first argument of a method.
look at this example:
class A:
def foo(self):
print "I'm a.foo"
#staticmethod
def bar(s):
print s
a = A()
a.foo()
A.foo(a)
here a is the instance of the class A. calling a.foo() you are invoking the method foo of the instance a while A.foo(a) invoke the method foo in the class A but passing the instance a as first argument and they are exactly the same thing (but never use the second form).
staticmethod is a decorator that let you define a class method as static. that function is no more a method and the first argument is not the instance of the class but is exactly the first argument you passed at that function:
a.bar("i'm a static method")
i'm a static method
A.bar("i'm a static method too")
i'm a static method too
PS. i don't want to bothering you but these are the very basis of python, the python tutorial is a nice start for the beginners.

Categories

Resources