Terminology
Mental model:
- A variable stored in an instance or class is called an attribute.
- A function stored in an instance or class is called a method.
According to Python's glossary:
attribute: A value associated with an object which is referenced by name using dotted expressions. For example, if an object o has an attribute a it would be referenced as o.a
method: A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called
self). See function and nested scope.
Examples
Terminology applied to actual code:
a = 10 # variable
def f(b): # function
return b ** 2
class C:
c = 20 # class attribute
def __init__(self, d): # "dunder" method
self.d = d # instance attribute
def show(self): # method
print(self.c, self.d)
e = C(30)
e.g = 40 # another instance attribute
Answer from Raymond Hettinger on Stack OverflowTerminology
Mental model:
- A variable stored in an instance or class is called an attribute.
- A function stored in an instance or class is called a method.
According to Python's glossary:
attribute: A value associated with an object which is referenced by name using dotted expressions. For example, if an object o has an attribute a it would be referenced as o.a
method: A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called
self). See function and nested scope.
Examples
Terminology applied to actual code:
a = 10 # variable
def f(b): # function
return b ** 2
class C:
c = 20 # class attribute
def __init__(self, d): # "dunder" method
self.d = d # instance attribute
def show(self): # method
print(self.c, self.d)
e = C(30)
e.g = 40 # another instance attribute
A method is an attribute, but not all attributes are methods. For example, if we have the class
class MyClass(object):
class_name = 'My Class'
def my_method(self):
print('Hello World!')
This class has two attributes, class_name and my_method. But only my_method is a method. Methods are functions that belong to your object. There are additional hidden attributes present on all classes, but this is what your exercise is likely talking about.
object oriented - Why are methods considered the class attributes in Python? - Software Engineering Stack Exchange
Why doesn’t dir() separate attributes and methods apart?
python - Differences between data attributes and method attributes - Stack Overflow
python - Creating an attribute of an object versus a method in the class - Software Engineering Stack Exchange
Videos
When exploring a new package I always find myself wanting what attributes are available in a class and what operations I can perform with it separately, but the dir() function just lumps them all together and displays them in a single list. After some searching around I still haven’t figured out how to just display all attributes or all methods of a class, and to this point I just wonder if I’m going the wrong way when learning about the basics of a newly installed package. Any advice or insights as to why python decided not to keep attributes and methods apart?
Thanks
Edit: Thanks all for the replies. Most of the answers pointed out that methods are just attributes that can be called. I think roughly get what it means, but don't quite understand why there is need to have both "method" and "attribute" concepts if they are just the same thing. Also, as I mentioned above, the reason I asked this question is that I always find myself wanting to know what attributes an object has, so I would print out dir(obj) and get a list of things [attr1, attr2, ...], then if I find, say, attr2 looks interesting/useful, I would try printing out obj.attr2 expecting to see some descriptive properties of the object, but the output would very often just tell me that attr2 is a method at some location... So I started wondering if I'm learning about a new package the wrong way, as I figure if most people do it the way I do, there should already be a function that does that!
An attribute is a variable that is looked up on another object using dot syntax: obj.attribute. The way Python is designed, attribute lookups can do a variety of things, and that variety can sometimes lead to bugs if you don't really understand what is happening (this is what the documentation you linked to warns about).
The most basic issue is that an attribute lookup can find either a value stored in the object's instance dictionary, or it can find something from the object's class (or a base class, if there's inheritance going on). Methods are functions stored in the class, but you usually use them by looking them up on an instance (which "binds" the method, inserting the object as the first arguemnt when the method is called).
The exact sequence of what is checked when is a bit complicated (I described the full process in an answer to another question), but at the most basic level, instance attributes usually take precedence over class attribute.
If an instance attribute and a class attribute with the same name both exist, usually only the instance attribute will be accessible. This can be very confusing if it is unintended.
Consider the following code:
class Foo(object):
def __init__(self, lst):
self.lst = lst
def sum(self):
self.sum = sum(self.lst)
return self.sum
f = Foo([1,2,3])
print(f.sum())
print(f.sum())
At the bottom of this code, we make two identical calls. The first works just fine, but the second will raise an exception.
This is because the first time we look up f.sum we find a method in the Foo class. We can call the method with no problems. The trouble comes from the fact that the sum method assigns the result of its calculation (the sum of the elements in self.lst) to an instance attribute also named sum. This hides the sum method from view.
When second f.sum() call looks up f.sum, it finds the instance attribute, containing the integer 6, rather than the expected method. An integer is not callable, so we get an exception.
The solution, of course, is not to use the same name for the method and attribute. The code above is a pretty trivial example. The bugs caused by this sort of thing in more complex code can be much more difficult to figure out.
If you're writing code that adds attributes to objects you don't know much about, you should be careful to avoid common names. If you're writing a mixin class, consider using two leading underscores in the attribute names to trigger Python's name mangling, which is designed for exactly this sort of situation.
Addendum: It's also possible that the distinction the documentation is trying to make is between data and non-data descriptors. Methods are the most common kind of non-data descriptor, so it might make a degree of sense to call them "method attributes" (especially in contrast to "data attributes" which would be the corresponding name for data descriptors), though I'm not aware of that language being used more widely. The important difference between the two kinds of descriptors is that data descriptors (like property) get processed before the instance dictionary is checked for an ordinary instance variable. As discussed above, non-data descriptors like methods get processed only after the instance dictionary is checked, so they can be shadowed by data stored on the instance.
An attribute is any thing for the lack of a better word that is bound to an object, for example:
class Dog:
def __init__(self):
self.name = "Rufus"
def bark(self):
print "Woof Woof!"
In this case the data attribute is the name, which is simply a value that is bound to the instance of the Dog. As for a method attribute, one answer would be the bark method, as it's not so much a value as it is an action. It's just as it is in English. A data attribute is exactly as it sounds; it's data, it is simply a property. A method is a procedure, an action, and this is exactly what a method attribute is.
Suppose I had the class `vehicle` which represents a motor vehicle. Suppose the horsepower of the vehicle was not passed as an inputs but, with some detailed calculation, could be calculated from the other properties of the vehicle class. Would it be better to add `horsepower` as a property of the `vehicle` class, or as a method?
As a property, this might look something like this:
class Vehicle:
def __init__(self, args):
# Set args
self._horsepower = None
@property
def horsepower(self):
if self._horsepower is None:
self._horsepower = calculate_horsepower()
return self._horsepowerAs a method, it may look like this:
class Vehicle:
def __init__(self, args):
# Set args
def calculate_horsepower(self):
# Calculate horsepower of instance vehicleWhich of the above is preferable?
In reality, horsepower is a property of a vehicle. However, if significant processing is required to calculate it then I'm not sure if it feels right to have it as a property of the `vehicle` class.