Why does Python have some functions that are syntactically arranged as enclosed?


I’m taking an Introduction to Python course, and I’ve just learned the upper() function. However, I was really tripped up when I saw that the correct usage of upper() was not upper(string), but rather, string.upper(). Is there some particular logic or reasoning behind this convention? Why isn’t this the case for other functions, and what purpose do the parentheses serve (aside from identifying it as a function)?

Asked By: Arctiic



The first parameter of a (non-static) class method in Python is the self parameter. If you want to call it as upper(string), you’re close. Change it to str.upper(string). str is the type that defines the upper() method.

Why isn’t this the case for other functions

I’m not really sure what you’re referring to here. If it’s not a class method (parameter list doesn’t start with self), then this doesn’t apply.

Answered By: user

A basic design principle is that in Python, everything is an object. This is unfortunately not entirely consistent, but nevertheless a guiding principle which is good to keep in mind.

If you have an object instance named instance, it has a number of attributes, each of which can be referred to as instance.attribute. If the attribute is a "callable", you can invoke it as a function; so instance.method returns a function, whereas instance.method() with parentheses returns it and calls it, with instance as the first self arguments behind the scenes.

There are some cases where this principle is not observed. One is where something invokes two objects. When you add two things, you obviously need to pass in at least one of them as a parameter, rather than call a method on it. So the syntax 3 + 4 simply treats both terms as equals (though internally, this becomes 3.__add__(4) actually). Another place where this model is abandoned is with some very common string or list operations, like sorted() (which could be mylist.sorted() but in fact the syntax is sorted(mylist) instead).

If you are only just learning, this is probably a bit over your head. To understand this exposition, you need a basic understanding of classes. In very brief,

class Something:
   def method(self):
      print(f"hooray, I'm {self}")

will let you create new object instances with Something() and each of them has a separate identity, and a separate collection of private attributes (here, for example, just the built-in self). So you can do:

>>> a = Something()
>>> b = Something()
>>> a.method()
hooray, I'm <__main__.Something object at 0x107998e50>
>>> b.method()
hooray, I'm <__main__.Something object at 0x1079696d0>

(If you look closely, you can see that the stuff after 0x1079 is unique. Each object instance a and b is a new and unique entity in memory.)

Tying back to the beginning, 3 and 4 are int objects with a number of methods, such as __str__ (which is what str(3) actually calls behind the scene; there is a number of such "dunder" methods which allow each data type in Python to implement its own behavior for a particular function or operator). You can view the attributes of any object with dir (so dir(3) will show you the attributes of this int instance). Similarly, your string is a str object instance which has a method called upper which is defined by the built-in str class.

Answered By: tripleee
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.