From 3. Data model:
Instance methods
An instance method object combines a class, a class instance and any
callable object (normally a user-deļ¬ned function).
If it is a definition, what does it mean?
If it is not a definition, what is the definition of an "instance method"?
Is an "instance method" the same concept of a method of a class?
Since someone brings up class methods and static methods, bound methods and unbound methods, let me clarify:
I understand a method of a class can be an ordinary method, a class method, or a static method. I understand a method of a class accessed via the class or its instance can be bound or function. I have never heard of "an instance method". I don't know what it is even after looking at the quote and am not sure if it is related to a ordinary method, a class method, or a static method, or a bound method or function.
>>> class Foo:
... def im_a_method(self):
... pass
...
>>> x = Foo()
>>> x.im_a_method
<bound method Foo.im_a_method of <__main__.Foo object at 0x7f4f1993dd30>>
Tada! That's an instance method object. It's the thing you get when you retrieve a method of an object, before you call it.
What is an instance method?
An instance method is a function the is bound to a class instance. The instance of the class is implicitly passed as the first argument to instance methods. It essentially belongs to that specific instance. An instance method is the "normal" type of method people use. This is opposed to a static method or class method created using staticmethod and classmethod respectively.
Here's an example of an instance method:
>>> class Class:
... def method(self):
... pass
>>> Class.method
<bound method Class.method of <Class object at 0x7f12781c5b70>>
It's that simple.
Your confusion comes from what exactly this definition is about. The term "instance method" is actually used to describe both the concept (a method that works on an instance - by opposition with a classmethod or staticmethod) and its technical implementation. The definition you quote is about the technical implementation.
If you want to understand the context of this definition, you can read this article in the Python wiki, which explains how Python turns functions into methods at runtime.
An instance method:
can call instance and class variables and instance, class and static methods by self.
can call class variables and instance, class and static methods by class name but not instance variables.
can be called by object.
can be also called directly by class name but when called directly by class name, we need to pass one argument to the instance method because self becomes the normal parameter which doesn't have the ability to call instance and class variables and instance, class and static methods.
needs self for the 1st argument otherwise the instance method cannot be called by an object but the instance method can still be called directly by class name and the name of self is used in convention so other names instead of self still work.
*I also explain about #classmethod and #staticmethod in my answer for #classmethod vs #staticmethod in Python.
For example, the instance method can call the instance and class variables and the instance, class and static methods by self and the instance method can call the class variable and the instance, class and static methods by class name but not the instance variables and the instance method can be called by object as shown below:
class Person:
x = "Hello"
def __init__(self, name):
self.name = name
def test1(self): # Instance method
print(self.name) # Instance variable by "self"
print(self.x) # Class variable by "self"
self.test2() # Instance method by "self"
self.test3() # Class method by "self"
self.test4() # Static method by "self"
print()
print(Person.x) # Class variable by class name
Person.test2("Test2") # Instance method by class name
Person.test3() # Class method by class name
Person.test4() # Static method by class name
def test2(self):
print("Test2")
#classmethod
def test3(cls):
print("Test3")
#staticmethod
def test4():
print("Test4")
obj = Person("John")
obj.test1() # By object
Output:
John # Instance variable by "self"
Hello # Class variable by "self"
Test2 # Instance method by "self"
Test3 # Class method by "self"
Test4 # Static method by "self"
Hello # Class variable by class name
Test2 # Instance method by class name
Test3 # Class method by class name
Test4 # Static method by class name
And, if the instance method tries to call the instance variable by class name as shown below:
# ...
def test1(self): # Instance method
print(Person.name) # Instance variable by class name
obj = Person("John")
obj.test1()
The error below occurs:
AttributeError: type object 'Person' has no attribute 'name'
And, the instance method can be also called directly by class name but when called directly by class name, we need to pass one argument to the instance method as shown below because self becomes the normal parameter which doesn't have the ability to call the instance and class variables and the instance, class and static methods by self:
# ...
def test1(self): # Instance method
print(self)
# ...
Person.test1("Test1") # Here
Output:
Test1
So, if the instance method tries to call the instance and class variables and the instance, class and static methods by self as shown below:
# ...
def test1(self): # Instance method
print(self.name) # Instance variable or
print(self.x) # Class variable or
self.test2() # Instance method or
self.test3() # Class method or
self.test4() # Static method
# ...
Person.test1("Test1") # Here
The errors below occur because again, self becomes the normal parameter which doesn't have the ability to call the instance and class variables and the instance, class and static methods:
AttributeError: 'str' object has no attribute 'name'
AttributeError: 'str' object has no attribute 'x'
AttributeError: 'str' object has no attribute 'test2'
AttributeError: 'str' object has no attribute 'test3'
AttributeError: 'str' object has no attribute 'test4'
And, if one argument is not passed to the instance method as shown below:
# ...
def test1(self): # Instance method
print(self)
# ...
Person.test1() # Here
The error below occurs:
TypeError: test1() missing 1 required positional argument: 'self'
And, the instance method needs self for the 1st argument otherwise the instance method cannot be called by object as shown below:
# ...
def test1(): # Without "self"
print("Test1")
# ...
obj = Person("John")
obj.test1() # Here
Then, the error below occurs:
TypeError: test1() takes 0 positional arguments but 1 was given
But, the instance method without self can still be called directly by class name as shown below:
# ...
def test1(): # Without "self"
print("Test1")
# ...
Person.test1() # Here
Output:
Test1
And, the name of self is used in convention in an instance method so other name instead of self still works as shown below:
# ...
# Here
def test1(orange): # Instance method
print(orange.name) # Instance variable
print(orange.x) # Class variable
orange.test2() # Instance method
orange.test3() # Class method
orange.test4() # Static method
# ...
obj = Person("John")
obj.test1()
Output:
John
Hello
Test2
Test3
Test4
Related
class Name():
def full_name(self):
self.firstname='[no name]'
self.lastname='[no name]'
class person:
def detail(self):
self.name=Name()
self.eye='[no eye]'
self.age=-1
myperson=person()
myperson.name.firstname='apple'
myperson.name.lastname='regmi'
myperson.name.firstname='cat'
print(myperson.name.firstname)
i could not find out why iam getting line 13, in
myperson.name.firstname='apple' AttributeError: 'person' object has no attribute 'name'
It seems like you're hoping to set the name, eye, and age attributes as defaults when you create any person object. If that's the case, detail should really be replaced with __init__, e.g.:
class person:
def __init__(self):
self.name=Name()
self.eye='[no eye]'
self.age=-1
A class's __init__ method defines how objects should be initialized when they are created. You don't need to call this method explicitly; instead, it is automatically run when you create an instance of a class:
# create an instance of persion, call
# `person.__init__()`, and assign the result
# to `myperson`:
myperson = person()
Now you should be able to reference and assign the attributes:
myperson.name.firstname='apple'
myperson.name.lastname='regmi'
myperson.name.firstname='cat'
Similarly, name.full_name should probably be name.__init__.
Note that by convention, classes in python usually use TitleCase, so this class would typically be named Person; likewise, name would be Name.
I was writing a simple implementation of classmethod decorator for a better understanding of both decorator and classmethod. Here is the problem I faced. When I called the class method with an instance of my class, everything was fine, but calling the method with the class object fails with error:
>>**TypeError: wrapper() missing 1 required positional argument: 'cls'**
and when I called the method with the explicit class object as parameter it succeed, but a call to classmethod from class object should pass the class object itself as the first parameter, right?
import functools
import inspect
def myclassmethod(meth):
#functools.wraps(meth)
def wrapper(cls, *args, **kwargs):
#print(f'obj:{cls}, cls:{cls.__class__}, isclass:{inspect.isclass(cls)}')
return meth(cls if inspect.isclass(cls) else cls.__class__, *args, **kwargs)
return wrapper
class MyDecoratedMethods(object):
_name = 'ClassName'
def __init__(self):
self._name = 'InstanceName'
def __repr__(self):
return f'{self.__class__.__name__}({self._name!r})'
#myclassmethod
def classname(cls):
return cls._name
MyDecoratedMethods().classname()
#MyDecoratedMethods.classname()
MyDecoratedMethods.classname(MyDecoratedMethods) # This works
To see what's going on, I removed the #functools.wraps(meth) line and then ran:
print(MyDecoratedMethods.classname)
# <function __main__.myclassmethod.<locals>.wrapper(cls, *args, **kwargs)>
This shows us, that MyDecoratedMethods.classname is simply the function you created inside your decorator. And this function knows nothing about the class it is called from.
However, we can override this behavior with Descriptors. A descriptor "knows" when it is accessed from a class or an instance and, most importantly, can distinguish between those cases (which is how regular methods are created).
Here is a first try:
class ClassMethod:
def __init__(self, function):
self.function = function
def __get__(self, instance, cls):
print(cls, instance)
class MyDecoratedMethods(object):
...
#ClassMethod
def classname(cls):
...
MyDecoratedMethods.classname
# prints <class '__main__.MyDecoratedMethods'> None
MyDecoratedMethods().classname
# prints <class '__main__.MyDecoratedMethods'> <__main__.MyDecoratedMethods object ...>
So we see that accessing the class method from the class sets instance to None and accessing it from an instance sets instance to that very object.
But actually we don't need the instance at all. We can implement the logic without it.
from functools import partial
class ClassMethod:
def __init__(self, function):
self.function = function
def __get__(self, instance, cls):
# create a new function and set cls to the first argument
return partial(self.function, cls)
...
MyDecoratedMethods().classname()
# "ClassName"
MyDecoratedMethods.classname()
# "ClassName"
And we are done. Our custom descriptor accomplished two things:
It prevented the function from binding the instance to the first argument when calling it from an instance of the class (like a function would normally do to become a method)
It always binds the class to the first argument when it is accessed from either the class or an instance.
Side note: Your approach to check whether an instance or the class called the function is also flawed (inspect.isclass(cls)). It will work for "normal" classes but not for meta classes, because then inspect.isclass returns True for the class and its instances.
I am trying to understand decorators and currently reading the documentation
import types
class SelfDocumenting( object ):
#classmethod
def getMethods( aClass ):
return [ (n,v.__doc__) for n,v in aClass.__dict__.items()
if type(v) == types.FunctionType ]
def help( self ):
"""Part of the self-documenting framework"""
print self.getMethods()
class SomeClass( SelfDocumenting ):
attr= "Some class Value"
def __init__( self ):
"""Create a new Instance"""
self.instVar= "some instance value"
def __str__( self ):
"""Display an instance"""
return "%s %s" % ( self.attr, self.instVar )
I do not understand why getMethods gets an argument called aClass but when SomeClass is defined and it is called later (see below) it can figure out what to replace with aClass in getMethods method:
>>> ac= SomeClass()
>>> ac.help()
[('__str__', 'Display an instance'), ('__init__', 'Create a new Instance')]
UPDATE:
Thanks to the answer but for future reference my confusion originated from the fact that self is a reserved word and aClass is not. So I wasn't sure how that is being handled. #abarnert's comment I think clarifies that the code in documentation is not really representative.
This isn't really related to the fact that it is a classmethod.
For the same reason we don't need to pass the instance when calling a "normal" instance method, the instance (and in this case, the class) is passed implicitly.
class Foo:
def instance_method(self):
print('No need to pass {} explictly'.format(self))
#classmethod
def class_method(cls):
print('No need to pass {} explictly'.format(cls))
obj = Foo()
obj.instance_method()
# No need to pass <__main__.Foo object at 0x0000000002A38DD8> explictly
obj.class_method()
# No need to pass <class '__main__.Foo'> explictly
Straight from the classmethod documentation:
A class method receives the class as implicit first argument, just like an instance method receives the instance
This is the same for derived classes:
If a class method is called for a derived class, the derived class object is passed as the implied first argument.
According to the description, as in the below mentioned link
https://docs.python.org/2/library/functions.html#classmethod
A class method is a method that is bound to a class rather than its object. It doesn't require creation of a class instance, much like staticmethod.
The difference between a static method and a class method is:
Static method knows nothing about the class and just deals with the
parameters Class method works with the class since its parameter is
always the class itself.
The class method can be called both by the class and its object.
source:
https://www.programiz.com/python-programming/methods/built-in/classmethod
You can see the description of the #ClassMethod here in the __ builtin __.py
class classmethod(object):
"""
classmethod(function) -> method
Convert a function to be a class method.
A class method receives the class as implicit first argument,
just like an instance method receives the instance.
To declare a class method, use this idiom:
class C:
#classmethod
def f(cls, arg1, arg2, ...):
...
It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()). The instance is ignored except for its class.
If a class method is called for a derived class, the derived class
object is passed as the implied first argument.
Class methods are different than C++ or Java static methods.
If you want those, see the staticmethod builtin.
"""
def __getattribute__(self, name): # real signature unknown; restored from __doc__
""" x.__getattribute__('name') <==> x.name """
pass
def __get__(self, obj, type=None): # real signature unknown; restored from __doc__
""" descr.__get__(obj[, type]) -> value """
pass
def __init__(self, function): # real signature unknown; restored from __doc__
pass
#staticmethod # known case of __new__
def __new__(S, *more): # real signature unknown; restored from __doc__
""" T.__new__(S, ...) -> a new object with type S, a subtype of T """
pass
__func__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
I'm trying to understand if there are differences between self and cls but I'm struggling, even though a lot of discussion on this topic exists. For instance:
class maclass():
A = "class method"
def __init__(self):
self.B = "instance method"
def getA_s(self):
print(self.A)
def getA_c(cls):
print(cls.A)
def getB_s(self):
print(self.B)
def getB_c(cls):
print(cls.B)
C = maclass()
C.getA_s()
C.getA_c()
C.getB_s()
C.getB_c()
which give me:
class method
class method
instance method
instance method
So whether I use self or cls, it always refers to the same variable. When I add a self.A in the Init__, the cls.A is just replaced
def __init__(self):
self.B = "instance method"
self.A = "new instance method"
and I get:
new instance method
new instance method
instance method
instance method
I don't understand the point of having two ways to call a class member if they are the same? I know this is a common question on this forum, yet I really don't understand why we would use different words to refer to the same thing (we even could use any variable name instead of self or cls).
update
In the following case:
class maclass():
A = "class method, "
def __init__(self):
self.A = "instance method, "
def getA_s(self):
print(self.A) #give me "instance method, "
#classmethod
def getA_c(cls):
print(cls.A) #give me "class method, "
C = maclass()
C.getA_s()
C.getA_c()
print(' ')
print(C.A) #give me "instance method, "
I get :
instance method,
class method,
instance method,
So in this case, in maclass: cls.A and self.A do not refer to the same variable.
All your methods are instance methods. None of them are class methods.
The first argument to a method is named self only by convention. You can name it anything you want, and naming it cls instead will not make it a reference to the class. That the first argument is bound to an instance is due to how method lookup works (accessing C.getA_s produces a bound method object, and calling that object causes C to be passed into the original function getA_s), the names of the parameters play no role.
In your methods, you are merely referencing instance attributes. That the A attribute is ultimately only defined on the class doesn't matter, you are still accessing that attribute through C.A (where C is the instance you created), not maclass.A. Looking up an attribute on the instance will also find attributes defined on the class if there is no instance attribute shadowing it.
To make a method a class method, decorate it with the #classmethod decorator:
#classmethod
def getA_c(cls):
print(cls.A)
Now cls will always be a reference to the class, never to the instance. I need to stress again that it doesn't actually matter to Python what name I picked for that first argument, but cls is the convention here as that makes it easier to remind the reader that this method is bound to the class object.
Note that if you do this for the getB_c() method, then trying to access cls.B in the method will fail because there is no B attribute on the maclass class object.
That's because classmethod wraps the function in a descriptor object that overrides the normal function binding behaviour. It is the descriptor protocol that causes methods to be bound to instances when accessed as attributes on the instance, a classmethod object redirects that binding process.
Here is a short demonstration with inline comments, I used the Python convertions for naming classes (using CamelCase), and for instances, attributes, functions and methods (using snake_case):
>>> class MyClass():
... class_attribute = "String attribute on the class"
... def __init__(self):
... self.instance_attribute = "String attribute on the instance"
... #classmethod
... def get_class_attribute(cls):
... return cls.class_attribute
... def get_instance_attribute(self):
... return self.instance_attribute
... #classmethod
... def get_instance_attribute_on_class(cls):
... return cls.instance_attribute
...
>>> instance = MyClass()
>>> instance.class_attribute # class attributes are visible on the instance
'String attribute on the class'
>>> MyClass.class_attribute # class attributes are also visible on the class
'String attribute on the class'
>>> instance.get_class_attribute() # bound to the class, but that doesn't matter here
'String attribute on the class'
>>> instance.class_attribute = "String attribute value overriding the class attribute"
>>> instance.get_class_attribute() # bound to the class, so the class attribute is found
'String attribute on the class'
>>> MyClass.get_instance_attribute_on_class() # fails, there is instance_attribute on the class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in get_instance_attribute_on_class
AttributeError: type object 'MyClass' has no attribute 'instance_attribute'
Note that the class method accesses the class attribute even though we set an attribute with the same name on the instance.
Next is binding behaviour:
>>> MyClass.get_instance_attribute # accessing the method on the class gives you the function
<function MyClass.get_instance_attribute at 0x10f94f268>
>>> instance.get_instance_attribute # accessing the method on the instance gives you the bound method
<bound method MyClass.get_instance_attribute of <__main__.MyClass object at 0x10f92b5f8>>
>>> MyClass.get_class_attribute # class methods are always bound, to the class
<bound method MyClass.get_class_attribute of <class '__main__.MyClass'>>
>>> instance.get_class_attribute # class methods are always bound, to the class
<bound method MyClass.get_class_attribute of <class '__main__.MyClass'>>
The bound methods tell you what they are bound to, calling the method passes in that bound object as the first argument. That object can also be introspected by looking at the __self__ attribute of a bound method:
>>> instance.get_instance_attribute.__self__ # the instance
<__main__.MyClass object at 0x10f92b5f8>
>>> instance.get_class_attribute.__self__ # the class
<class '__main__.MyClass'>
In Python, I am able to access the non-predefined class variables both from the class as well as instances. However, I am not able to access the predefined class variables (such as "name") from the object instances. What am I missing? Thanks.
Here is a test program that I wrote.
class Test:
'''
This is a test class to understand why we can't access predefined class variables
like __name__, __module__ etc from an instance of the class while still able
to access the non-predefined class variables from instances
'''
PI_VALUE = 3.14 #This is a non-predefined class variable
# the constructor of the class
def __init__(self, arg1):
self.value = arg1
def print_value(self):
print self.value
an_object = Test("Hello")
an_object.print_value()
print Test.PI_VALUE # print the class variable PI_VALUE from an instance of the class
print an_object.PI_VALUE # print the class variable PI_VALUE from the class
print Test.__name__ # print pre-defined class variable __name__ from the class
print an_object.__name__ #print the pre-defined class varible __name__ from an instance of the class
That's normal. Instances of a class look in that class's __dict__ for attribute resolution, as well as the __dict__s of all ancestors, but not all attributes of a class come from its __dict__.
In particular, Test's __name__ is held in a field in the C struct representing the class, rather than in the class's __dict__, and the attribute is found through a __name__ descriptor in type.__dict__. Instances of Test don't look at this for attribute lookup.
I don't have a great answer for "why". But here's how you can get to them, using __class__:
>>> class Foo(object): pass
...
>>> foo = Foo()
>>> foo.__name__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__name__'
>>> foo.__class__.__name__
'Foo'
>>>